Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Relay mouse event synthesization information
Make platform plugins, like the windows one, able to indicate
if a mouse event is synthesized from a touch event by the OS.
This will be valuable information for the Quick2 event handlers.

No new member variables are added to QMouseEvent. Instead, the enum
value is encoded in the caps member, there are plenty of bits
available in it.

This introduces Qt::MouseEventSource and QMouseEvent::source() as
public APIs.

Change-Id: If087a0bafb33a6cd7891bd07b84871358f6aba69
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
  • Loading branch information
Laszlo Agocs authored and giucam committed May 13, 2015
1 parent b1a108b commit d57237f
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 25 deletions.
6 changes: 6 additions & 0 deletions src/corelib/global/qnamespace.h
Expand Up @@ -1596,6 +1596,12 @@ Qt {
ScrollUpdate,
ScrollEnd
};

enum MouseEventSource {
MouseEventNotSynthesized,
MouseEventSynthesizedBySystem,
MouseEventSynthesizedByQt
};
}
#ifdef Q_MOC_RUN
;
Expand Down
22 changes: 22 additions & 0 deletions src/corelib/global/qnamespace.qdoc
Expand Up @@ -2895,3 +2895,25 @@
\value ScrollEnd Scrolling has ended, but the scrolling distance
did not change anymore.
*/

/*!
\enum Qt::MouseEventSource
\since 5.3

This enum describes the source of a mouse event and can be useful
to determine if the event is an artificial mouse event originating
from another device such as a touchscreen.

\value MouseEventNotSynthesized The most common value. On
platforms where such information is available this value indicates
that the event was generated in response to a genuine mouse event
in the system.

\value MouseEventSynthesizedBySystem Indicates that the mouse
event was synthesized from a touch event by the platform.

\value MouseEventSynthesizedByQt Indicates that the mouse event was
synthesized from an unhandled touch event by Qt.

\sa Qt::AA_SynthesizeMouseForUnhandledTouchEvents
*/
18 changes: 18 additions & 0 deletions src/gui/kernel/qevent.cpp
Expand Up @@ -274,6 +274,24 @@ QMouseEvent::~QMouseEvent()
{
}

/*!
\since 5.3
Returns information about the mouse event source.
The mouse event source can be used to distinguish between genuine
and artificial mouse events. The latter are events that are
synthesized from touch events by the operating system or Qt itself.
\note Many platforms provide no such information. On such platforms
\l Qt::MouseEventNotSynthesized is returned always.
\sa Qt::MouseEventSource
*/
Qt::MouseEventSource QMouseEvent::source() const
{
return QGuiApplicationPrivate::mouseEventSource(this);
}

/*!
\fn QPointF QMouseEvent::localPos() const
Expand Down
2 changes: 2 additions & 0 deletions src/gui/kernel/qevent.h
Expand Up @@ -135,6 +135,8 @@ class Q_GUI_EXPORT QMouseEvent : public QInputEvent
QT_DEPRECATED inline QPointF posF() const { return l; }
#endif

Qt::MouseEventSource source() const;

protected:
QPointF l, w, s;
Qt::MouseButton b;
Expand Down
32 changes: 26 additions & 6 deletions src/gui/kernel/qguiapplication.cpp
Expand Up @@ -1572,6 +1572,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo

QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers);
ev.setTimestamp(e->timestamp);
setMouseEventSource(&ev, e->source);
#ifndef QT_NO_CURSOR
if (!e->synthetic) {
if (const QScreen *screen = window->screen())
Expand Down Expand Up @@ -1626,6 +1627,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint,
button, buttons, e->modifiers);
dblClickEvent.setTimestamp(e->timestamp);
setMouseEventSource(&dblClickEvent, e->source);
QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent);
}
}
Expand Down Expand Up @@ -2042,7 +2044,8 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
synthIt->pos,
synthIt->screenPos,
Qt::NoButton,
e->modifiers);
e->modifiers,
Qt::MouseEventSynthesizedByQt);
fake.synthetic = true;
processMouseEvent(&fake);
}
Expand Down Expand Up @@ -3147,9 +3150,16 @@ void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object)
emit q->focusObjectChanged(object);
}

enum {
MouseCapsMask = 0xFF,
MouseSourceMaskDst = 0xFF00,
MouseSourceMaskSrc = MouseCapsMask,
MouseSourceShift = 8,
};

int QGuiApplicationPrivate::mouseEventCaps(QMouseEvent *event)
{
return event->caps;
return event->caps & MouseCapsMask;
}

QVector2D QGuiApplicationPrivate::mouseEventVelocity(QMouseEvent *event)
Expand All @@ -3159,16 +3169,26 @@ QVector2D QGuiApplicationPrivate::mouseEventVelocity(QMouseEvent *event)

void QGuiApplicationPrivate::setMouseEventCapsAndVelocity(QMouseEvent *event, int caps, const QVector2D &velocity)
{
event->caps = caps;
Q_ASSERT(caps <= MouseCapsMask);
event->caps &= ~MouseCapsMask;
event->caps |= caps & MouseCapsMask;
event->velocity = velocity;
}

void QGuiApplicationPrivate::setMouseEventCapsAndVelocity(QMouseEvent *event, QMouseEvent *other)
Qt::MouseEventSource QGuiApplicationPrivate::mouseEventSource(const QMouseEvent *event)
{
event->caps = other->caps;
event->velocity = other->velocity;
return Qt::MouseEventSource((event->caps & MouseSourceMaskDst) >> MouseSourceShift);
}

void QGuiApplicationPrivate::setMouseEventSource(QMouseEvent *event, Qt::MouseEventSource source)
{
// Mouse event synthesization status is encoded in the caps field because
// QTouchDevice::CapabilityFlag uses only 6 bits from it.
int value = source;
Q_ASSERT(value <= MouseSourceMaskSrc);
event->caps &= ~MouseSourceMaskDst;
event->caps |= (value & MouseSourceMaskSrc) << MouseSourceShift;
}

#include "moc_qguiapplication.cpp"

Expand Down
4 changes: 3 additions & 1 deletion src/gui/kernel/qguiapplication_p.h
Expand Up @@ -268,7 +268,9 @@ class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate
static int mouseEventCaps(QMouseEvent *event);
static QVector2D mouseEventVelocity(QMouseEvent *event);
static void setMouseEventCapsAndVelocity(QMouseEvent *event, int caps, const QVector2D &velocity);
static void setMouseEventCapsAndVelocity(QMouseEvent *event, QMouseEvent *other);

static Qt::MouseEventSource mouseEventSource(const QMouseEvent *event);
static void setMouseEventSource(QMouseEvent *event, Qt::MouseEventSource source);

const QDrawHelperGammaTables *gammaTables();

Expand Down
20 changes: 12 additions & 8 deletions src/gui/kernel/qwindowsysteminterface.cpp
Expand Up @@ -165,31 +165,35 @@ void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted)
\a w == 0 means that the event is in global coords only, \a local will be ignored in this case
*/
void QWindowSystemInterface::handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
void QWindowSystemInterface::handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
handleMouseEvent(w, time, local, global, b, mods);
handleMouseEvent(w, time, local, global, b, mods, source);
}

void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
QWindowSystemInterfacePrivate::MouseEvent * e =
new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, local, global, b, mods);
new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, local, global, b, mods, source);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}

void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
handleFrameStrutMouseEvent(w, time, local, global, b, mods);
handleFrameStrutMouseEvent(w, time, local, global, b, mods, source);
}

void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
QWindowSystemInterfacePrivate::MouseEvent * e =
new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp,
QWindowSystemInterfacePrivate::FrameStrutMouse,
local, global, b, mods);
local, global, b, mods, source);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}

Expand Down
16 changes: 12 additions & 4 deletions src/gui/kernel/qwindowsysteminterface.h
Expand Up @@ -73,10 +73,18 @@ class QPlatformDropQtResponse;
class Q_GUI_EXPORT QWindowSystemInterface
{
public:
static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);

static bool tryHandleShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods,
const QString & text = QString(), bool autorep = false, ushort count = 1);
Expand Down
11 changes: 7 additions & 4 deletions src/gui/kernel/qwindowsysteminterface_p.h
Expand Up @@ -211,14 +211,17 @@ class Q_GUI_EXPORT QWindowSystemInterfacePrivate {
class MouseEvent : public InputEvent {
public:
MouseEvent(QWindow * w, ulong time, const QPointF & local, const QPointF & global,
Qt::MouseButtons b, Qt::KeyboardModifiers mods)
: InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b) { }
Qt::MouseButtons b, Qt::KeyboardModifiers mods,
Qt::MouseEventSource src = Qt::MouseEventNotSynthesized)
: InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b), source(src) { }
MouseEvent(QWindow * w, ulong time, EventType t, const QPointF & local, const QPointF & global,
Qt::MouseButtons b, Qt::KeyboardModifiers mods)
: InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b) { }
Qt::MouseButtons b, Qt::KeyboardModifiers mods,
Qt::MouseEventSource src = Qt::MouseEventNotSynthesized)
: InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b), source(src) { }
QPointF localPos;
QPointF globalPos;
Qt::MouseButtons buttons;
Qt::MouseEventSource source;
};

class WheelEvent : public InputEvent {
Expand Down
9 changes: 7 additions & 2 deletions src/plugins/platforms/windows/qwindowsmousehandler.cpp
Expand Up @@ -167,6 +167,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (et == QtWindows::MouseWheelEvent)
return translateMouseWheelEvent(window, hwnd, msg, result);

Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;

#ifndef Q_OS_WINCE
static const bool passSynthesizedMouseEvents = QWindowsIntegration::instance()->options() & QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch;
if (!passSynthesizedMouseEvents) {
Expand All @@ -177,6 +179,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0x80);
if (fromTouch)
return false;
source = Qt::MouseEventSynthesizedBySystem;
}
#endif // !Q_OS_WINCE

Expand All @@ -187,7 +190,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
globalPosition, buttons,
QWindowsKeyMapper::queryKeyboardModifiers());
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
return false; // Allow further event processing (dragging of windows).
}

Expand Down Expand Up @@ -335,7 +339,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}

QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
QWindowsKeyMapper::queryKeyboardModifiers());
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
m_previousCaptureWindow = hasCapture ? window : 0;
return true;
}
Expand Down

0 comments on commit d57237f

Please sign in to comment.