From 72dfe1deb32bc1efcb71ea61a4de6e76ad396ee7 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 4 Sep 2017 09:48:08 +0200 Subject: [PATCH] touch: use enhanced mouse event when synthesizing mouse The documentation for AA_SynthesizeMouseForUnhandledTouchEvents states: "All touch events that are not accepted by the application will be translated to left button mouse events instead." This is exactly what this patch does. With the enhanced mouse event, we can simply pass event details as necessary. This should not conflict with the code doing its own mouse synthesis (as long as custom event handler accepts QEvent::Touch{Begin,Update,End}). What was wrong with the previous implementation: It was sharing the same state variable (mouse_buttons) to deduce button state/type on physical mouse and emulated mouse. This was wrong, you can't track state of two input devices by sharing one variable. Moreover, this variable is intended for tracking state of a hardware mouse only. Button state on physical mouse (as a separate pointer device) is irrelevant for touch input (which is another "pointer device"). The current API does not support multiple pointer devices, thus button state on one pointer device should not affect state on other pointer device. Task-number: QTBUG-57465 Task-number: QTBUG-52102 Change-Id: Id45d815508918b4e52319baddb2c9564d52ad783 Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qguiapplication.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 80a6a9c1e4..20fe738469 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2528,7 +2528,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To ++it; } for (QSet::const_iterator winIt = windowsNeedingCancel.constBegin(), - winItEnd = windowsNeedingCancel.constEnd(); winIt != winItEnd; ++winIt) { + winItEnd = windowsNeedingCancel.constEnd(); winIt != winItEnd; ++winIt) { touchEvent.setWindow(*winIt); QGuiApplication::sendSpontaneousEvent(*winIt, &touchEvent); } @@ -2541,8 +2541,10 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To e->timestamp, synthIt->pos, synthIt->screenPos, - mouse_buttons & ~Qt::LeftButton, + Qt::NoButton, e->modifiers, + Qt::LeftButton, + QEvent::MouseButtonRelease, Qt::MouseEventSynthesizedByQt); fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; processMouseEvent(&fake); @@ -2739,25 +2741,41 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To if (!e->synthetic() && !touchEvent.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) { // exclude devices which generate their own mouse events if (!(touchEvent.device()->capabilities() & QTouchDevice::MouseEmulation)) { - Qt::MouseButtons b = eventType == QEvent::TouchEnd ? Qt::NoButton : Qt::LeftButton; - if (b == Qt::NoButton) + + if (eventType == QEvent::TouchEnd) self->synthesizedMousePoints.clear(); const QList &touchPoints = touchEvent.touchPoints(); if (eventType == QEvent::TouchBegin) m_fakeMouseSourcePointId = touchPoints.first().id(); + const QEvent::Type mouseType = [&]() { + switch (eventType) { + case QEvent::TouchBegin: return QEvent::MouseButtonPress; + case QEvent::TouchUpdate: return QEvent::MouseMove; + case QEvent::TouchEnd: return QEvent::MouseButtonRelease; + default: Q_UNREACHABLE(); + } + }(); + + Qt::MouseButton button = mouseType == QEvent::MouseMove ? Qt::NoButton : Qt::LeftButton; + Qt::MouseButtons buttons = mouseType == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton; + for (int i = 0; i < touchPoints.count(); ++i) { const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i); if (touchPoint.id() == m_fakeMouseSourcePointId) { - if (b != Qt::NoButton) + if (eventType != QEvent::TouchEnd) self->synthesizedMousePoints.insert(w, SynthesizedMouseData( touchPoint.pos(), touchPoint.screenPos(), w)); + // All touch events that are not accepted by the application will be translated to + // left mouse button events instead (see AA_SynthesizeMouseForUnhandledTouchEvents docs). QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), - b | (mouse_buttons & ~Qt::LeftButton), + buttons, e->modifiers, + button, + mouseType, Qt::MouseEventSynthesizedByQt); fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; processMouseEvent(&fake);