summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/qnamespace.h3
-rw-r--r--src/corelib/global/qnamespace.qdoc2
-rw-r--r--src/gui/kernel/qevent.cpp6
-rw-r--r--src/gui/kernel/qevent.h2
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h12
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm2
-rw-r--r--src/widgets/kernel/qapplication.cpp68
-rw-r--r--src/widgets/kernel/qapplication_p.h1
9 files changed, 74 insertions, 24 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index c4f5415a01..4d0bd6903d 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1626,7 +1626,8 @@ public:
};
enum ScrollPhase {
- ScrollBegin = 1,
+ NoScrollPhase = 0, // Make public in 5.7 or asap
+ ScrollBegin,
ScrollUpdate,
ScrollEnd
};
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 7c5263ddbd..527bded3c2 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -3070,6 +3070,8 @@
This enum describes the phase of scrolling.
+ \omitvalue NoScrollPhase The input device doesn't support scroll phase.
+
\value ScrollBegin Scrolling is about to begin, but the scrolling
distance did not yet change.
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 4f368e1db3..8abec2b05e 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -727,7 +727,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons),
- ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized)
+ ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized)
{
g = QCursor::pos();
if (orient == Qt::Vertical)
@@ -762,7 +762,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons),
- ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized)
+ ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized)
{
if (orient == Qt::Vertical)
angleD = QPoint(0, delta);
@@ -798,7 +798,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta),
- angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate),
+ angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::NoScrollPhase),
src(Qt::MouseEventNotSynthesized)
{}
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index ed2deda9a0..b407663338 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -219,6 +219,8 @@ protected:
uint ph : 2;
uint src: 2;
int reserved : 28;
+
+ friend class QApplication;
};
#endif
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index a27c68649e..20d560f82e 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -94,8 +94,16 @@ 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, 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);
+ static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global,
+ QPoint pixelDelta, QPoint angleDelta,
+ Qt::KeyboardModifiers mods = Qt::NoModifier,
+ Qt::ScrollPhase phase = Qt::NoScrollPhase,
+ 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::NoScrollPhase,
+ 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 e48d1e965b..c2569f29cd 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -236,7 +236,7 @@ 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, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized)
+ Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, 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;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 0d80333e65..05dcbd33ad 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -1405,6 +1405,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) {
ph = Qt::ScrollEnd;
m_scrolling = false;
+ } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) {
+ ph = Qt::NoScrollPhase;
}
QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 3ab477ccfb..7c5a0da0c1 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -417,6 +417,7 @@ QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard inpu
QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus
#ifndef QT_NO_WHEELEVENT
int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll
+QWidget *QApplicationPrivate::wheel_widget = Q_NULLPTR;
#endif
bool qt_in_tab_key_event = false;
int qt_antialiasing_threshold = -1;
@@ -3309,7 +3310,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
case QEvent::Wheel:
{
QWidget* w = static_cast<QWidget *>(receiver);
- QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
// QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open.
if (const QWidget *popup = QApplication::activePopupWidget()) {
@@ -3317,27 +3317,61 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
return true;
}
- QPoint relpos = wheel->pos();
- bool eventAccepted = wheel->isAccepted();
+ QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
+ const bool spontaneous = wheel->spontaneous();
+ const Qt::ScrollPhase phase = wheel->phase();
- if (e->spontaneous() && wheel->phase() == Qt::ScrollUpdate)
- QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
+ if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin
+ || (phase == Qt::ScrollUpdate && !QApplicationPrivate::wheel_widget)) {
+
+ if (spontaneous && phase == Qt::ScrollBegin)
+ QApplicationPrivate::wheel_widget = Q_NULLPTR;
+
+ const QPoint &relpos = wheel->pos();
+
+ if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate))
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
- while (w) {
QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
- 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();
- e->spont = false;
- if ((res && eventAccepted)
- || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
- break;
+ wheel->modifiers(), phase, wheel->source());
+ bool eventAccepted;
+ while (w) {
+ we.spont = spontaneous && w == receiver;
+ we.ignore();
+ res = d->notify_helper(w, &we);
+ eventAccepted = we.isAccepted();
+ if (res && eventAccepted) {
+ if (spontaneous && phase != Qt::NoScrollPhase)
+ QApplicationPrivate::wheel_widget = w;
+ break;
+ }
+ if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
- relpos += w->pos();
- w = w->parentWidget();
+ we.p += w->pos();
+ w = w->parentWidget();
+ }
+ wheel->setAccepted(eventAccepted);
+ } else if (QApplicationPrivate::wheel_widget) {
+ if (!spontaneous) {
+ // wheel_widget may forward the wheel event to a delegate widget,
+ // either directly or indirectly (e.g. QAbstractScrollArea will
+ // forward to its QScrollBars through viewportEvent()). In that
+ // case, the event will not be spontaneous but synthesized, so
+ // we can send it straigth to the receiver.
+ d->notify_helper(w, wheel);
+ } else {
+ const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos());
+ QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
+ wheel->modifiers(), wheel->phase(), wheel->source());
+ we.spont = true;
+ we.ignore();
+ d->notify_helper(QApplicationPrivate::wheel_widget, &we);
+ wheel->setAccepted(we.isAccepted());
+ if (phase == Qt::ScrollEnd)
+ QApplicationPrivate::wheel_widget = Q_NULLPTR;
+ }
}
- wheel->setAccepted(eventAccepted);
}
break;
#endif
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 75d86a5eba..4cce2d84e8 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -202,6 +202,7 @@ public:
static QWidget *active_window;
#ifndef QT_NO_WHEELEVENT
static int wheel_scroll_lines;
+ static QWidget *wheel_widget;
#endif
static int enabledAnimations; // Combination of QPlatformTheme::UiEffect