aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp29
-rw-r--r--src/quicktemplates2/qquickoverlay_p_p.h2
-rw-r--r--tests/auto/drawer/data/dragOverModalShadow.qml87
-rw-r--r--tests/auto/drawer/tst_drawer.cpp59
4 files changed, 163 insertions, 14 deletions
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index 0f7edc77..15104808 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -181,11 +181,23 @@ QQuickOverlayPrivate::QQuickOverlayPrivate()
{
}
-bool QQuickOverlayPrivate::startDrag(QEvent *event)
+bool QQuickOverlayPrivate::startDrag(QEvent *event, const QPointF &pos)
{
+ Q_Q(QQuickOverlay);
if (allDrawers.isEmpty())
return false;
+ // don't start dragging a drawer if a modal popup overlay is blocking (QTBUG-60602)
+ QQuickItem *item = q->childAt(pos.x(), pos.y());
+ if (item) {
+ const auto popups = stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
+ if (p->dimmer == item && popup->isVisible() && popup->isModal())
+ return false;
+ }
+ }
+
const QVector<QQuickDrawer *> drawers = stackingOrderDrawers();
for (QQuickDrawer *drawer : drawers) {
QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
@@ -251,7 +263,7 @@ bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *eve
{
switch (event->type()) {
case QEvent::MouseButtonPress:
- if (!target && startDrag(event))
+ if (!target && startDrag(event, event->windowPos()))
return true;
return handlePress(source, event, target);
case QEvent::MouseMove:
@@ -269,17 +281,12 @@ bool QQuickOverlayPrivate::handleTouchEvent(QQuickItem *source, QTouchEvent *eve
bool handled = false;
switch (event->type()) {
case QEvent::TouchBegin:
- if (!target && startDrag(event))
- handled = true;
- else
- handled = handlePress(source, event, target);
- break;
-
case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
switch (point.state()) {
case Qt::TouchPointPressed:
- if (!target && startDrag(event))
+ if (!target && startDrag(event, point.scenePos()))
handled = true;
else
handled |= handlePress(source, event, target);
@@ -296,10 +303,6 @@ bool QQuickOverlayPrivate::handleTouchEvent(QQuickItem *source, QTouchEvent *eve
}
break;
- case QEvent::TouchEnd:
- handled = handleRelease(source, event, target ? target : mouseGrabberPopup.data());
- break;
-
default:
break;
}
diff --git a/src/quicktemplates2/qquickoverlay_p_p.h b/src/quicktemplates2/qquickoverlay_p_p.h
index fa53d52b..5553bda8 100644
--- a/src/quicktemplates2/qquickoverlay_p_p.h
+++ b/src/quicktemplates2/qquickoverlay_p_p.h
@@ -70,7 +70,7 @@ public:
return overlay->d_func();
}
- bool startDrag(QEvent *event);
+ bool startDrag(QEvent *event, const QPointF &pos);
bool handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target);
bool handleMove(QQuickItem *source, QEvent *event, QQuickPopup *target);
bool handleRelease(QQuickItem *source, QEvent *event, QQuickPopup *target);
diff --git a/tests/auto/drawer/data/dragOverModalShadow.qml b/tests/auto/drawer/data/dragOverModalShadow.qml
new file mode 100644
index 00000000..66eb2f4b
--- /dev/null
+++ b/tests/auto/drawer/data/dragOverModalShadow.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias drawer: drawer
+ property alias popup: popup
+
+ Drawer {
+ id: drawer
+ width: 200
+ height: parent.height
+ dragMargin: parent.width
+ }
+
+ Popup {
+ id: popup
+ modal: true
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: parent.width / 2
+ height: parent.height / 2
+
+ Rectangle {
+ objectName: "shadow"
+ parent: popup.background
+ anchors.fill: parent
+ anchors.margins: -20
+
+ z: -1
+ opacity: 0.5
+ color: "silver"
+ }
+ }
+}
diff --git a/tests/auto/drawer/tst_drawer.cpp b/tests/auto/drawer/tst_drawer.cpp
index 6f3e1d64..9c30f8cf 100644
--- a/tests/auto/drawer/tst_drawer.cpp
+++ b/tests/auto/drawer/tst_drawer.cpp
@@ -94,6 +94,9 @@ private slots:
void flickable_data();
void flickable();
+ void dragOverModalShadow_data();
+ void dragOverModalShadow();
+
private:
struct TouchDeviceDeleter
{
@@ -962,6 +965,62 @@ void tst_Drawer::flickable()
QVERIFY(!flickable->isDragging());
}
+void tst_Drawer::dragOverModalShadow_data()
+{
+ QTest::addColumn<bool>("mouse");
+ QTest::newRow("mouse") << true;
+ QTest::newRow("touch") << false;
+}
+
+// QTBUG-60602
+void tst_Drawer::dragOverModalShadow()
+{
+ QFETCH(bool, mouse);
+
+ QQuickApplicationHelper helper(this, QStringLiteral("dragOverModalShadow.qml"));
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickDrawer *drawer = window->property("drawer").value<QQuickDrawer *>();
+ QVERIFY(drawer);
+
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup *>();
+ QVERIFY(popup);
+
+ popup->open();
+ QVERIFY(popup->isVisible());
+ QVERIFY(!drawer->isVisible());
+
+ const QPoint from(popup->x(), popup->y() + popup->height() + 5);
+ const QPoint to(popup->x() + popup->width(), popup->y() + popup->height() + 5);
+
+ if (mouse)
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, from);
+ else
+ QTest::touchEvent(window, touchDevice.data()).press(0, from);
+ QVERIFY(!drawer->isVisible());
+
+ static const int steps = 10;
+ for (int i = 0; i < steps; ++i) {
+ int x = from.x() + i * qAbs(from.x() - to.x()) / steps;
+ int y = from.y() + i * qAbs(from.y() - to.y()) / steps;
+
+ if (mouse)
+ QTest::mouseMove(window, QPoint(x, y));
+ else
+ QTest::touchEvent(window, touchDevice.data()).move(0, QPoint(x, y));
+ QTest::qWait(1); // avoid infinite velocity
+ QVERIFY(!drawer->isVisible());
+ }
+
+ if (mouse)
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, to);
+ else
+ QTest::touchEvent(window, touchDevice.data()).release(0, to);
+ QVERIFY(!drawer->isVisible());
+}
+
QTEST_MAIN(tst_Drawer)
#include "tst_drawer.moc"