From 74443d7bbb319e949928dd081fde04bccb5f7845 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 4 Dec 2014 17:03:35 +0100 Subject: [PATCH] Add QWheelEvent::source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is analogous to 0a92295ca829a62125c9f122fd3daec991993855 which added QMouseEvent::source. For now, we say that a wheel event is synthetic when it comes from a trackpad or other device that provides scrolling by some means other than an actual wheel. Change-Id: I0452ca2080b551b18b9c2f6e42db925d14ae339e Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qevent.cpp | 58 ++++++++++++++++++++++- src/gui/kernel/qevent.h | 9 +++- src/gui/kernel/qguiapplication.cpp | 2 +- src/gui/kernel/qguiapplication_p.h | 2 + src/gui/kernel/qwindowsysteminterface.cpp | 14 +++--- src/gui/kernel/qwindowsysteminterface.h | 4 +- src/gui/kernel/qwindowsysteminterface_p.h | 5 +- src/plugins/platforms/cocoa/qnsview.mm | 4 +- src/widgets/kernel/qapplication.cpp | 2 +- src/widgets/kernel/qwidgetwindow.cpp | 2 +- 10 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index f845bf89c9..5bc70b9fb2 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -575,7 +575,8 @@ QHoverEvent::~QHoverEvent() wheel event delta: angleDelta() returns the delta in wheel degrees. This value is always provided. pixelDelta() returns the delta in screen pixels and is available on platforms that - have high-resolution trackpads, such as Mac OS X. + have high-resolution trackpads, such as Mac OS X. If that is the + case, source() will return Qt::MouseEventSynthesizedBySystem. The functions pos() and globalPos() return the mouse cursor's location at the time of the event. @@ -599,6 +600,22 @@ QHoverEvent::~QHoverEvent() Returns the mouse state when the event occurred. */ +/*! + \fn Qt::MouseEventSource QWheelEvent::source() const + \since 5.5 + + Returns information about the wheel event source. + + The source can be used to distinguish between events that come from a mouse + with a physical wheel and events that are generated by some other means, + such as a flick gesture on a touchpad. + + \note Many platforms provide no such information. On such platforms + \l Qt::MouseEventNotSynthesized is returned always. + + \sa Qt::MouseEventSource +*/ + /*! \fn Qt::Orientation QWheelEvent::orientation() const \obsolete @@ -731,7 +748,44 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(phase) + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(phase), + src(Qt::MouseEventNotSynthesized) +{} + +/*! + Constructs a wheel event object. + + The \a pos provides the location of the mouse cursor + within the window. The position in global coordinates is specified + by \a globalPos. + + \a pixelDelta contains the scrolling distance in pixels on screen, while + \a angleDelta contains the wheel rotation distance. \a pixelDelta is + optional and can be null. + + The mouse and keyboard states at the time of the event are specified by + \a buttons and \a modifiers. + + For backwards compatibility, the event can also hold monodirectional wheel + event data: \a qt4Delta specifies the rotation, and \a qt4Orientation the + direction. + + The scrolling phase of the event is specified by \a phase. + + If the wheel event comes from a physical mouse wheel, \a source is set to + Qt::MouseEventNotSynthesized. If it comes from a gesture detected by the + operating system, or from a non-mouse hardware device, such that \a pixelDelta is + directly related to finger movement, \a source is set to Qt::MouseEventSynthesizedBySystem. + If it comes from Qt, source would be set to Qt::MouseEventSynthesizedByQt. + + \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase() +*/ + +QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, + QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source) + : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(phase), src(source) {} #endif // QT_NO_WHEELEVENT diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 0b6d96a590..35a8884865 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -176,7 +176,9 @@ public: QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase); - + QWheelEvent(const QPointF &pos, const QPointF &globalPos, QPoint pixelDelta, QPoint angleDelta, + int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, + Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source); ~QWheelEvent(); @@ -201,6 +203,8 @@ public: inline Qt::ScrollPhase phase() const { return Qt::ScrollPhase(ph); } + Qt::MouseEventSource source() const { return Qt::MouseEventSource(src); } + protected: QPointF p; QPointF g; @@ -210,7 +214,8 @@ protected: Qt::Orientation qt4O; Qt::MouseButtons mouseState; uint ph : 2; - int reserved : 30; + uint src: 2; + int reserved : 28; }; #endif diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 9ddb9e15ee..a2953259ff 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1833,7 +1833,7 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh return; } - QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, buttons, e->modifiers, e->phase); + QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, buttons, e->modifiers, e->phase, e->source); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); #endif /* ifndef QT_NO_WHEELEVENT */ diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 165cd18580..8b444e1d34 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -270,6 +270,8 @@ public: static Qt::MouseEventFlags mouseEventFlags(const QMouseEvent *event); static void setMouseEventFlags(QMouseEvent *event, Qt::MouseEventFlags flags); + static Qt::MouseEventSource wheelEventSource(const QWheelEvent *event); + const QDrawHelperGammaTables *gammaTables(); // hook reimplemented in QApplication to apply the QStyle function on the QIcon diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index a564f507d8..6f41d85965 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -339,13 +339,13 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con handleWheelEvent(tlw, timestamp, local, global, QPoint(), point, mods); } -void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase) +void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleWheelEvent(w, time, local, global, pixelDelta, angleDelta, mods, phase); + handleWheelEvent(w, time, local, global, pixelDelta, angleDelta, mods, phase, source); } -void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase) +void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source) { // Qt 4 sends two separate wheel events for horizontal and vertical // deltas. For Qt 5 we want to send the deltas in one event, but at the @@ -363,14 +363,14 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con // Simple case: vertical deltas only: if (angleDelta.y() != 0 && angleDelta.x() == 0) { - e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase); + e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); return; } // Simple case: horizontal deltas only: if (angleDelta.y() == 0 && angleDelta.x() != 0) { - e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase); + e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); return; } @@ -378,12 +378,12 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con // Both horizontal and vertical deltas: Send two wheel events. // The first event contains the Qt 5 pixel and angle delta as points, // and in addition the Qt 4 compatibility vertical angle delta. - e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase); + e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); // The second event contains null pixel and angle points and the // Qt 4 compatibility horizontal angle delta. - e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase); + e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 7bb3938fe6..4d3bc43f1c 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -106,8 +106,8 @@ public: quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, ushort count = 1, bool tryShortcutOverride = true); - static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate); - static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate); + static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); // Wheel event compatibility functions. Will be removed: do not use. static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 57411d8101..782d3e9400 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -232,8 +232,8 @@ public: class WheelEvent : public InputEvent { public: WheelEvent(QWindow *w, ulong time, const QPointF & local, const QPointF & global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O, - Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::ScrollUpdate) - : InputEvent(w, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D), qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase) { } + Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) + : InputEvent(w, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D), qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src) { } QPoint pixelDelta; QPoint angleDelta; int qt4Delta; @@ -241,6 +241,7 @@ public: QPointF localPos; QPointF globalPos; Qt::ScrollPhase phase; + Qt::MouseEventSource source; }; class KeyEvent : public InputEvent { diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9dcad519a3..2f4dcd2a8c 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1268,6 +1268,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) return [super scrollWheel:theEvent]; QPoint angleDelta; + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; if ([theEvent hasPreciseScrollingDeltas]) { // The mouse device contains pixel scroll wheel support (Mighty Mouse, Trackpad). // Since deviceDelta is delivered as pixels rather than degrees, we need to @@ -1277,6 +1278,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const int pixelsToDegrees = 2; // 8 * 1/4 angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees); angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees); + source = Qt::MouseEventSynthesizedBySystem; } else { // Remove acceleration, and use either -120 or 120 as delta: angleDelta.setX(qBound(-120, int([theEvent deltaX] * 10000), 120)); @@ -1334,7 +1336,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) m_scrolling = false; } - QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph); + QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source); } #endif //QT_NO_WHEELEVENT diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 943abd1f1a..bf05b2029b 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3317,7 +3317,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) while (w) { QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), wheel->phase()); + wheel->modifiers(), wheel->phase(), wheel->source()); we.spont = wheel->spontaneous(); res = d->notify_helper(w, w == receiver ? wheel : &we); eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted(); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index f543086969..ed5d56c689 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -712,7 +712,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QPoint mapped = widget->mapFrom(m_widget, event->pos()); - QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase()); + QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source()); QGuiApplication::sendSpontaneousEvent(widget, &translated); }