aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohammadHossein Qanbari <mohammad.qanbari@qt.io>2024-03-07 14:48:10 +0100
committerMohammadHossein Qanbari <mohammad.qanbari@qt.io>2024-03-26 10:38:52 +0100
commit73eeb35f09fd1ea846bb0f5ce507316f587fda9f (patch)
tree706fbd90a740da7d44334683aee442c4b56c86ea
parent4299d0bb92745fc377b8df0fb246f3081465a195 (diff)
Flickable: don't allow dragging with mouse buttons other than left
The SwipeView's page did not change to a new page when the user right-clicked on text content inside the page. This occurred because the mouse press event enabled the 'pressed' variable, indicating the beginning of a drag. Since the text item did not accept the press event, there was no need to handle the move and release events. Consequently, the 'pressed' variable remained true. If the 'pressed' variable is true, then the SwipeView's contentItem does not update the highlight item. This implies that the highlight animators will not start. Consequently, although the current index and item would change, the content item view is not updated. To fix this issue, the 'pressed' variable should not be true when the press event is not accepted. When it's a mouse event, the value of the 'pressed' variable is set to true when the left button is pressed, similar to the existing condition in the handleMoveEvent() method. Since the bug originated in 'maybeBeginDrag()', the condition is added to this method by passing the event's buttons. The testcase creates a SwipeView component with two page items that include a Label item. The test involves performing mouse and touch events on the text content. Subsequently, when the current index is changed, the testcase compares the content item to ensure it is adjusted to its position to display the current item accordingly. [ChangeLog][Quick][Flickable][Drag] Flickable is meant to be dragged (flicked) by touch events; and as a matter of legacy support, for now it can also be dragged by the left mouse button. Dragging with other mouse buttons, such as the right and middle buttons, is not allowed. Task-number: QTBUG-97252 Pick-to: 5.15 Change-Id: Ice23650dd29fe400b80efe299c9294fad62dcefb Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/quick/items/qquickflickable.cpp7
-rw-r--r--src/quick/items/qquickflickable_p_p.h3
-rw-r--r--tests/auto/quick/qquickflickable/data/listviewWithTextDelegate.qml14
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp52
4 files changed, 72 insertions, 4 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index c7efdc47fb..713d512256 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1083,14 +1083,15 @@ void QQuickFlickablePrivate::handleMousePressEvent(QMouseEvent *event)
}
q->setKeepMouseGrab(stealMouse);
- maybeBeginDrag(computeCurrentTime(event), event->localPos());
+ maybeBeginDrag(computeCurrentTime(event), event->localPos(), event->buttons());
}
-void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn)
+void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn, Qt::MouseButtons buttons)
{
Q_Q(QQuickFlickable);
clearDelayedPress();
- pressed = true;
+ // consider dragging only when event is left mouse button or touch event which has no button
+ pressed = (buttons == Qt::LeftButton) || (buttons == Qt::NoButton);
if (hData.transitionToBounds)
hData.transitionToBounds->stopTransition();
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 6bff809b79..b801dd49de 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -268,7 +268,8 @@ public:
void handleMouseMoveEvent(QMouseEvent *);
void handleMouseReleaseEvent(QMouseEvent *);
- void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn);
+ void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn,
+ Qt::MouseButtons buttons = Qt::NoButton);
void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
const QVector2D &deltas, bool overThreshold, bool momentum,
bool velocitySensitiveOverBounds, const QVector2D &velocity);
diff --git a/tests/auto/quick/qquickflickable/data/listviewWithTextDelegate.qml b/tests/auto/quick/qquickflickable/data/listviewWithTextDelegate.qml
new file mode 100644
index 0000000000..63e99c4d2b
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/listviewWithTextDelegate.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+ListView {
+ id: root
+ width: 300; height: 300
+ orientation: ListView.Horizontal
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ model: 2
+ delegate: Text {
+ verticalAlignment: Qt.AlignVCenter; horizontalAlignment: Qt.AlignHCenter
+ width: root.width; height: root.height
+ text: "page " + index
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 62f7c67dd4..d9a0af1715 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -33,6 +33,7 @@
#include <QtQml/qqmlcomponent.h>
#include <private/qquickflickable_p.h>
#include <private/qquickflickable_p_p.h>
+#include <private/qquicklistview_p.h>
#include <private/qquickmousearea_p.h>
#include <private/qquicktransition_p.h>
#include <private/qqmlvaluetype_p.h>
@@ -208,6 +209,8 @@ private slots:
void visibleAreaBinding();
void setContentPositionWhileDragging_data();
void setContentPositionWhileDragging();
+ void acceptButtons_data();
+ void acceptButtons();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
@@ -2669,6 +2672,55 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966
QVERIFY(!flickable->isDragging());
}
+void tst_qquickflickable::acceptButtons_data()
+{
+ QTest::addColumn<bool>("isMouseEvent");
+ QTest::addColumn<bool>("isTouchEvent");
+ QTest::addColumn<int>("button");
+
+ QTest::newRow("middleClick") << true << false << static_cast<int>(Qt::MiddleButton);
+ QTest::newRow("rightClick") << true << false << static_cast<int>(Qt::RightButton);
+ QTest::newRow("leftClick") << true << false << static_cast<int>(Qt::LeftButton);
+ QTest::newRow("touchEvent") << false << true << static_cast<int>(Qt::NoButton);
+}
+
+void tst_qquickflickable::acceptButtons() // QTBUG-97252
+{
+ QFETCH(bool, isMouseEvent);
+ QFETCH(bool, isTouchEvent);
+ QFETCH(int, button);
+
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("listviewWithTextDelegate.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ QQuickListView *lv = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(lv);
+ QVERIFY(lv->isVisible());
+
+ lv->setCurrentIndex(0);
+ QCOMPARE(lv->currentIndex(), 0);
+ QVERIFY(QTest::qWaitFor([lv](){ return lv->contentX() == 0; }));
+
+ const QPoint center = lv->mapToScene({lv->width() / 2, lv->height() / 2}).toPoint();
+ if (isMouseEvent) {
+ const Qt::MouseButton mouseButton = static_cast<Qt::MouseButton>(button);
+ QTest::mouseClick(window.data(), mouseButton, Qt::NoModifier, center);
+ } else if (isTouchEvent) {
+ QTest::touchEvent(window.data(), touchDevice).press(0, center).commit();
+ QTest::touchEvent(window.data(), touchDevice).release(0, center).commit();
+ }
+ lv->setCurrentIndex(1);
+ const double expectedContentX = lv->width();
+ QCOMPARE(lv->currentIndex(), 1);
+ QVERIFY(QTest::qWaitFor([lv, expectedContentX](){ return lv->contentX() == expectedContentX; }));
+ QTRY_COMPARE(lv->contentX(), expectedContentX);
+}
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"