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>
This commit is contained in:
Laszlo Agocs 2013-09-14 20:31:54 +02:00 committed by The Qt Project
parent 69e78b9a07
commit 0a92295ca8
10 changed files with 115 additions and 25 deletions

View File

@ -1584,6 +1584,12 @@ public:
ScrollUpdate,
ScrollEnd
};
enum MouseEventSource {
MouseEventNotSynthesized,
MouseEventSynthesizedBySystem,
MouseEventSynthesizedByQt
};
}
#ifdef Q_MOC_RUN
;

View File

@ -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
*/

View File

@ -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

View File

@ -135,6 +135,8 @@ public:
QT_DEPRECATED inline QPointF posF() const { return l; }
#endif
Qt::MouseEventSource source() const;
protected:
QPointF l, w, s;
Qt::MouseButton b;

View File

@ -1560,6 +1560,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 (const QScreen *screen = window->screen())
if (QPlatformCursor *cursor = screen->handle()->cursor())
@ -1612,6 +1613,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);
}
}
@ -2024,7 +2026,8 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
synthIt->pos,
synthIt->screenPos,
Qt::NoButton,
e->modifiers);
e->modifiers,
Qt::MouseEventSynthesizedByQt);
fake.synthetic = true;
processMouseEvent(&fake);
}
@ -3103,9 +3106,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)
@ -3115,16 +3125,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"

View File

@ -264,7 +264,9 @@ public:
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();

View File

@ -161,31 +161,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);
}

View File

@ -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);

View File

@ -205,14 +205,17 @@ public:
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 {

View File

@ -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) {
@ -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
@ -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).
}
@ -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;
}