aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-01-13 16:14:51 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-01-17 07:22:18 +0100
commit731cc2dbf6d6ebe041f232952dcc1af71e589b5a (patch)
treefd27ff12f083ed7713895e7549d7157154f8c75e /tests/auto
parent6137b73b9d39644f100a268e6d222939c98547d1 (diff)
QQuickPopup: fix logic for modally blocking wheel events
After caca7d7d4fcb7281332904c01950a66385bad0b3, QQuickOverlay ate wheel events to any item that was not a child of the top-most modal popup. This broke event delivery to children of modless popups higher up in the stack. Fix that logic so that we don't eat events if we find a popup that the item is a child of. Only eat the event if we don't find such a popup before hitting the first modal popup. Add a test with a relevant scenario, and as a drive-by, fix and simplify the helper function sending wheel events. Since the event gets delivered to the window, we have to use scene coordinates, not item coordinates. This happened to work in the wheel test case as the test sliders cover the entire window. Fixes: QTBUG-110023 Pick-to: 6.5 6.4 Change-Id: Ibc53114cf09693e23b1e66f28a0c2056f3bd810e Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/nested-wheel.qml44
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp50
2 files changed, 88 insertions, 6 deletions
diff --git a/tests/auto/quickcontrols/qquickpopup/data/nested-wheel.qml b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel.qml
new file mode 100644
index 0000000000..a0b319fd24
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel.qml
@@ -0,0 +1,44 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias modalPopup: popup
+ property alias comboBox: combobox
+
+ Popup {
+ id: popup
+ objectName: "Modal Dialog"
+ width: 300
+ height: 300
+ anchors.centerIn: parent
+ visible: true
+ modal: true
+
+ ComboBox {
+ id: combobox
+ anchors.centerIn: parent
+ width: 120
+ model: 30
+
+ popup: Popup {
+ objectName: "Combobox Popup"
+ y: combobox.height
+ width: combobox.width
+ height: contentItem.implicitHeight
+ contentItem: ListView {
+ objectName: "Combobox ListView"
+ clip: true
+ implicitHeight: 150
+ model: combobox.delegateModel
+ currentIndex: combobox.highlightedIndex
+ ScrollBar.vertical: ScrollBar {
+ objectName: "vbar"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
index ecd5479931..8343cc4f3a 100644
--- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
@@ -65,6 +65,7 @@ private slots:
void wheel();
void parentDestroyed();
void nested();
+ void nestedWheel();
void modelessOnModalOnModeless();
void grabber();
void cursorShape();
@@ -1012,16 +1013,23 @@ void tst_QQuickPopup::wheel_data()
QTest::newRow("ApplicationWindow:modeless") << "applicationwindow-wheel.qml" << false;
}
-static bool sendWheelEvent(QQuickItem *item, const QPoint &localPos, int degrees)
+static bool sendWheelEvent(QQuickItem *item, const QPointF &localPos, int degrees)
{
QQuickWindow *window = item->window();
- QWheelEvent wheelEvent(localPos, item->window()->mapToGlobal(localPos), QPoint(0, 0),
+ const QPoint scenePos = item->mapToScene(localPos).toPoint();
+ QWheelEvent wheelEvent(scenePos, window->mapToGlobal(scenePos), QPoint(0, 0),
QPoint(0, 8 * degrees), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase,
false);
QSpontaneKeyEvent::setSpontaneous(&wheelEvent);
return qGuiApp->notify(window, &wheelEvent);
}
+static bool sendWheelEvent(QQuickItem *item, int degrees)
+{
+ const QPointF localPos = QPointF(item->width() / 2, item->height() / 2);
+ return sendWheelEvent(item, localPos, degrees);
+}
+
void tst_QQuickPopup::wheel()
{
QFETCH(QString, source);
@@ -1052,7 +1060,7 @@ void tst_QQuickPopup::wheel()
qreal oldContentValue = contentSlider->value();
qreal oldPopupValue = popupSlider->value();
- QVERIFY(sendWheelEvent(contentSlider, QPoint(contentSlider->width() / 2, contentSlider->height() / 2), 15));
+ QVERIFY(sendWheelEvent(contentSlider, 15));
QVERIFY(!qFuzzyCompare(contentSlider->value(), oldContentValue)); // must have moved
QVERIFY(qFuzzyCompare(popupSlider->value(), oldPopupValue)); // must not have moved
@@ -1068,7 +1076,7 @@ void tst_QQuickPopup::wheel()
qreal oldContentValue = contentSlider->value();
qreal oldPopupValue = popupSlider->value();
- QVERIFY(sendWheelEvent(popupSlider, QPoint(popupSlider->width() / 2, popupSlider->height() / 2), 15));
+ QVERIFY(sendWheelEvent(popupSlider, 15));
QVERIFY(qFuzzyCompare(contentSlider->value(), oldContentValue)); // must not have moved
QVERIFY(!qFuzzyCompare(popupSlider->value(), oldPopupValue)); // must have moved
@@ -1084,7 +1092,7 @@ void tst_QQuickPopup::wheel()
qreal oldContentValue = contentSlider->value();
qreal oldPopupValue = popupSlider->value();
- QVERIFY(sendWheelEvent(popupSlider, QPoint(popupSlider->width() / 2, popupSlider->height() / 2), 15));
+ QVERIFY(sendWheelEvent(popupSlider, 15));
QVERIFY(qFuzzyCompare(contentSlider->value(), oldContentValue)); // must not have moved
QCOMPARE(qFuzzyCompare(popupSlider->value(), oldPopupValue), modal); // must not have moved unless modeless
@@ -1095,7 +1103,7 @@ void tst_QQuickPopup::wheel()
qreal oldContentValue = contentSlider->value();
qreal oldPopupValue = popupSlider->value();
- QVERIFY(sendWheelEvent(QQuickOverlay::overlay(window), QPoint(0, 0), 15));
+ QVERIFY(sendWheelEvent(QQuickOverlay::overlay(window), QPointF(0, 0), 15));
if (modal) {
// the content below a modal overlay must not move
@@ -1145,6 +1153,36 @@ void tst_QQuickPopup::nested()
QCOMPARE(modalPopup->isVisible(), true);
}
+void tst_QQuickPopup::nestedWheel()
+{
+ QQuickControlsApplicationHelper helper(this, QStringLiteral("nested-wheel.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickPopup *modalPopup = window->property("modalPopup").value<QQuickPopup *>();
+ QVERIFY(modalPopup);
+
+ QQuickComboBox *comboBox = window->property("comboBox").value<QQuickComboBox *>();
+ QVERIFY(comboBox);
+
+ const QPoint comboBoxCenter = comboBox->mapToScene(
+ QPointF(comboBox->width() / 2, comboBox->height() / 2)).toPoint();
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, comboBoxCenter);
+ QTRY_VERIFY(comboBox->popup()->isOpened());
+
+ QQuickItem *listView = comboBox->popup()->contentItem();
+ QVERIFY(listView);
+ QQuickItem *vbar = listView->findChild<QQuickItem *>("vbar");
+ QVERIFY(vbar);
+
+ const double startPosition = vbar->property("position").toDouble();
+ // wheel over the list view, verify that it scrolls
+ sendWheelEvent(listView, -30);
+ QTRY_COMPARE_GT(vbar->property("position").toDouble(), startPosition);
+}
+
void tst_QQuickPopup::modelessOnModalOnModeless()
{
QQuickControlsApplicationHelper helper(this, QStringLiteral("modelessOnModalOnModeless.qml"));