From 6d6ed64d6ca27c1b5fec305e6ed9b923b5bb1037 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 21 Jul 2020 22:08:36 +0200 Subject: [PATCH] Add QPointerEvent::is[Press|Update|Release]Event accessors QQuickPointerEvent had them, so despite how trivial they look, it's very convenient to keep using them in QQuickWindow rather than duplicating these kinds of checks in various places, and for multiple event types too. Change-Id: I32ad8110fd2361e69de50a679ddbdb2a2db7ecee Reviewed-by: Fabian Kosmale --- src/gui/kernel/qevent.cpp | 50 +++++++++++++++++++ src/gui/kernel/qevent.h | 12 +++++ .../kernel/qmouseevent/tst_qmouseevent.cpp | 15 ++++++ .../kernel/qtouchevent/tst_qtouchevent.cpp | 34 +++++++++++++ 4 files changed, 111 insertions(+) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 517233482f0..ea831f9a409 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -361,6 +361,30 @@ QSinglePointEvent::QSinglePointEvent(QEvent::Type type, const QPointingDevice *d mut.setGlobalPosition(globalPos); } +/*! + Returns true if this event represents a \l {button()}{button} being pressed. +*/ +bool QSinglePointEvent::isPressEvent() const +{ + return m_button != Qt::NoButton && m_mouseState.testFlag(m_button); +} + +/*! + Returns true if this event does not include a change in \l {buttons()}{button state}. +*/ +bool QSinglePointEvent::isUpdateEvent() const +{ + return m_button == Qt::NoButton; +} + +/*! + Returns true if this event represents a \l {button()}{button} being released. +*/ +bool QSinglePointEvent::isReleaseEvent() const +{ + return m_button != Qt::NoButton && !m_mouseState.testFlag(m_button); +} + /*! \fn QPointingDevice::PointerType QPointerEvent::pointerType() const @@ -4224,6 +4248,32 @@ QTouchEvent::QTouchEvent(QEvent::Type eventType, QTouchEvent::~QTouchEvent() { } +/*! + Returns true if this event includes at least one newly-pressed touchpoint. +*/ +bool QTouchEvent::isPressEvent() const +{ + return m_touchPointStates.testFlag(QEventPoint::State::Pressed); +} + +/*! + Returns true if this event does not include newly-pressed or newly-released + touchpoints. +*/ +bool QTouchEvent::isUpdateEvent() const +{ + return !m_touchPointStates.testFlag(QEventPoint::State::Pressed) && + !m_touchPointStates.testFlag(QEventPoint::State::Released); +} + +/*! + Returns true if this event includes at least one newly-released touchpoint. +*/ +bool QTouchEvent::isReleaseEvent() const +{ + return m_touchPointStates.testFlag(QEventPoint::State::Released); +} + /*! \fn QObject *QTouchEvent::target() const Returns the target object within the window on which the event occurred. diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index cfbaf8603e3..8ba138a1bb9 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -200,6 +200,9 @@ public: virtual ~QPointerEvent(); virtual int pointCount() const = 0; virtual const QEventPoint &point(int i) const = 0; + virtual bool isPressEvent() const { return false; } + virtual bool isUpdateEvent() const { return false; } + virtual bool isReleaseEvent() const { return false; } explicit QPointerEvent(Type type, const QPointingDevice *dev, Qt::KeyboardModifiers modifiers = Qt::NoModifier); const QPointingDevice *pointingDevice() const; @@ -225,6 +228,10 @@ public: inline QPointF scenePosition() const { return m_point.scenePosition(); } inline QPointF globalPosition() const { return m_point.globalPosition(); } + bool isPressEvent() const override; + bool isUpdateEvent() const override; + bool isReleaseEvent() const override; + protected: QEventPoint m_point; Qt::MouseButton m_button = Qt::NoButton; @@ -330,6 +337,8 @@ public: inline QPointF posF() const { return position(); } #endif // QT_DEPRECATED_SINCE(6, 0) + bool isUpdateEvent() const override { return true; } + // TODO deprecate when we figure out an actual replacement (point history?) inline QPoint oldPos() const { return m_oldPos.toPoint(); } inline QPointF oldPosF() const { return m_oldPos; } @@ -954,6 +963,9 @@ public: inline QObject *target() const { return m_target; } inline QEventPoint::States touchPointStates() const { return m_touchPointStates; } const QList &touchPoints() const { return m_touchPoints; } + bool isPressEvent() const override; + bool isUpdateEvent() const override; + bool isReleaseEvent() const override; protected: QObject *m_target = nullptr; diff --git a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp index eda66198b79..70e51696485 100644 --- a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp +++ b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp @@ -113,13 +113,28 @@ void tst_QMouseEvent::mouseEventBasic() QPointF local(100, 100); QPointF scene(200, 200); QPointF screen(300, 300); + // Press left button QMouseEvent me(QEvent::MouseButtonPress, local, scene, screen, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QCOMPARE(me.isAccepted(), true); QCOMPARE(me.button(), Qt::LeftButton); QCOMPARE(me.buttons(), Qt::LeftButton); + QVERIFY(me.isPressEvent()); + QVERIFY(!me.isReleaseEvent()); QCOMPARE(me.position(), local); QCOMPARE(me.scenePosition(), scene); QCOMPARE(me.globalPosition(), screen); + // Press right button while left is already pressed + me = QMouseEvent(QEvent::MouseButtonPress, local, scene, screen, Qt::RightButton, Qt::LeftButton | Qt::RightButton, Qt::NoModifier); + QVERIFY(me.isPressEvent()); + QVERIFY(!me.isReleaseEvent()); + // Release right button while left is still pressed + me = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::RightButton, Qt::LeftButton, Qt::NoModifier); + QVERIFY(!me.isPressEvent()); + QVERIFY(me.isReleaseEvent()); + // Release left button in the usual way + me = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + QVERIFY(!me.isPressEvent()); + QVERIFY(me.isReleaseEvent()); } void tst_QMouseEvent::checkMousePressEvent_data() diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 08c8dd3f78b..d3d8eba34d9 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -217,6 +217,7 @@ public: private slots: void cleanup(); void qPointerUniqueId(); + void state(); void touchDisabledByDefault(); void touchEventAcceptedByDefault(); void touchBeginPropagatesWhenIgnored(); @@ -290,6 +291,39 @@ void tst_QTouchEvent::qPointerUniqueId() QCOMPARE(set.size(), 2); } +void tst_QTouchEvent::state() +{ + QTouchEvent touchEvent(QEvent::TouchBegin, touchScreenDevice, + Qt::NoModifier, QList() << + QEventPoint(0, QEventPoint::State::Stationary, {}, {}) << + QEventPoint(1, QEventPoint::State::Pressed, {}, {})); + QCOMPARE(touchEvent.touchPointStates(), QEventPoint::State::Stationary | QEventPoint::State::Pressed); + QCOMPARE(touchEvent.pointCount(), 2); + QVERIFY(touchEvent.isPressEvent()); + QVERIFY(!touchEvent.isUpdateEvent()); + QVERIFY(!touchEvent.isReleaseEvent()); + + touchEvent = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, + Qt::NoModifier, QList() << + QEventPoint(0, QEventPoint::State::Updated, {}, {}) << + QEventPoint(1, QEventPoint::State::Pressed, {}, {})); + QCOMPARE(touchEvent.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Pressed); + QCOMPARE(touchEvent.pointCount(), 2); + QVERIFY(touchEvent.isPressEvent()); + QVERIFY(!touchEvent.isUpdateEvent()); + QVERIFY(!touchEvent.isReleaseEvent()); + + touchEvent = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, + Qt::NoModifier, QList() << + QEventPoint(0, QEventPoint::State::Updated, {}, {}) << + QEventPoint(1, QEventPoint::State::Released, {}, {})); + QCOMPARE(touchEvent.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Released); + QCOMPARE(touchEvent.pointCount(), 2); + QVERIFY(!touchEvent.isPressEvent()); + QVERIFY(!touchEvent.isUpdateEvent()); + QVERIFY(touchEvent.isReleaseEvent()); +} + void tst_QTouchEvent::touchDisabledByDefault() { // QWidget