aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-09-03 15:39:04 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-09-05 15:59:10 +0000
commit14dd934c3203b614e43be9fa5b17761d43092351 (patch)
treef9027f1b1961842bb5ea2e2aa5fdc2302f3c4ad4
parent6f3f262574d2bb0cf7ccd5148f29e078aef8d16a (diff)
Use QQuickOverlay with plain QQuickWindow
Get rid of the ugly and broken event filter approach that was used with QQuickWindow. Create an instance of QQuickOverlay so that the same overlay code path is used for both QQuickApplicationWindow and plain QQuickWindow. Task-number: QTBUG-55729 Change-Id: I6e26b19cd94a9580418912803f50c30b9dcaeedb Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quicktemplates2/qquickapplicationwindow.cpp3
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp28
-rw-r--r--src/quicktemplates2/qquickoverlay_p.h2
-rw-r--r--src/quicktemplates2/qquickpopup.cpp19
-rw-r--r--src/quicktemplates2/qquickpopup_p.h1
-rw-r--r--tests/auto/popup/data/window.qml84
-rw-r--r--tests/auto/popup/tst_popup.cpp96
7 files changed, 186 insertions, 47 deletions
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp
index bf903b8a..28095aa6 100644
--- a/src/quicktemplates2/qquickapplicationwindow.cpp
+++ b/src/quicktemplates2/qquickapplicationwindow.cpp
@@ -476,6 +476,9 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const
QQuickOverlay *QQuickApplicationWindow::overlay() const
{
QQuickApplicationWindowPrivate *d = const_cast<QQuickApplicationWindowPrivate *>(d_func());
+ if (!d) // being deleted
+ return nullptr;
+
if (!d->overlay) {
d->overlay = new QQuickOverlay(QQuickWindow::contentItem());
d->overlay->stackAfter(QQuickApplicationWindow::contentItem());
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index c5818b90..0395ed41 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -37,6 +37,7 @@
#include "qquickoverlay_p.h"
#include "qquickpopup_p_p.h"
#include "qquickdrawer_p.h"
+#include "qquickapplicationwindow_p.h"
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlproperty.h>
#include <QtQml/qqmlcomponent.h>
@@ -204,8 +205,10 @@ QQuickOverlay::QQuickOverlay(QQuickItem *parent)
setFiltersChildMouseEvents(true);
setVisible(false);
- if (parent)
+ if (parent) {
+ setSize(QSizeF(parent->width(), parent->height()));
QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry);
+ }
}
QQuickOverlay::~QQuickOverlay()
@@ -249,6 +252,29 @@ void QQuickOverlay::setModeless(QQmlComponent *modeless)
emit modelessChanged();
}
+QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window)
+{
+ if (!window)
+ return nullptr;
+
+ QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow *>(window);
+ if (applicationWindow)
+ return applicationWindow->overlay();
+
+ const char *name = "_q_QQuickOverlay";
+ QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
+ if (!overlay) {
+ QQuickItem *content = window->contentItem();
+ // Do not re-create the overlay if the window is being destroyed
+ // and thus, its content item no longer has a window associated.
+ if (content->window()) {
+ overlay = new QQuickOverlay(window->contentItem());
+ window->setProperty(name, QVariant::fromValue(overlay));
+ }
+ }
+ return overlay;
+}
+
void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
{
Q_D(QQuickOverlay);
diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h
index 480a5a6a..ecb0e20a 100644
--- a/src/quicktemplates2/qquickoverlay_p.h
+++ b/src/quicktemplates2/qquickoverlay_p.h
@@ -72,6 +72,8 @@ public:
QQmlComponent *modeless() const;
void setModeless(QQmlComponent *modeless);
+ static QQuickOverlay *overlay(QQuickWindow *window);
+
Q_SIGNALS:
void modalChanged();
void modelessChanged();
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index b4022247..fa5864df 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -188,15 +188,7 @@ void QQuickPopupPrivate::prepareEnterTransition(bool notify)
return;
}
- QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window);
- if (!applicationWindow) {
- window->installEventFilter(q);
- popupItem->setZ(1000001); // DefaultWindowDecoration+1
- popupItem->setParentItem(window->contentItem());
- } else {
- popupItem->setParentItem(applicationWindow->overlay());
- }
-
+ popupItem->setParentItem(QQuickOverlay::overlay(window));
if (notify)
emit q->aboutToShow();
visible = notify;
@@ -208,8 +200,6 @@ void QQuickPopupPrivate::prepareEnterTransition(bool notify)
void QQuickPopupPrivate::prepareExitTransition()
{
Q_Q(QQuickPopup);
- if (window && !qobject_cast<QQuickApplicationWindow *>(window))
- window->removeEventFilter(q);
if (focus) {
// The setFocus(false) call below removes any active focus before we're
// able to check it in finalizeExitTransition.
@@ -1837,13 +1827,6 @@ bool QQuickPopup::isComponentComplete() const
return d->complete;
}
-bool QQuickPopup::eventFilter(QObject *object, QEvent *event)
-{
- if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object))
- return overlayEvent(window->contentItem(), event);
- return false;
-}
-
bool QQuickPopup::childMouseEventFilter(QQuickItem *child, QEvent *event)
{
Q_UNUSED(child);
diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h
index be6a8e22..9ef5c64b 100644
--- a/src/quicktemplates2/qquickpopup_p.h
+++ b/src/quicktemplates2/qquickpopup_p.h
@@ -334,7 +334,6 @@ protected:
void componentComplete() override;
bool isComponentComplete() const;
- bool eventFilter(QObject *object, QEvent *event) override;
virtual bool childMouseEventFilter(QQuickItem *child, QEvent *event);
virtual void focusInEvent(QFocusEvent *event);
virtual void focusOutEvent(QFocusEvent *event);
diff --git a/tests/auto/popup/data/window.qml b/tests/auto/popup/data/window.qml
new file mode 100644
index 00000000..92bfbd70
--- /dev/null
+++ b/tests/auto/popup/data/window.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.Window 2.2
+import QtQuick.Controls 2.0
+
+Window {
+ width: 400
+ height: 400
+
+ property alias popup: popup
+ property alias popup2: popup2
+ property alias button: button
+
+ Button {
+ id: button
+ text: "Open"
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -height
+
+ Popup {
+ id: popup
+ y: parent.height
+
+ Text {
+ color: "white"
+ text: "Hello, world!"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: popup.close()
+ }
+ }
+ }
+ }
+
+ Popup {
+ id: popup2
+ y: popup.y
+ z: 1
+ contentItem: Text {
+ text: "Popup2"
+ font.pixelSize: 36
+ }
+ }
+}
diff --git a/tests/auto/popup/tst_popup.cpp b/tests/auto/popup/tst_popup.cpp
index abd20df0..ef649187 100644
--- a/tests/auto/popup/tst_popup.cpp
+++ b/tests/auto/popup/tst_popup.cpp
@@ -51,8 +51,11 @@ class tst_popup : public QQmlDataTest
Q_OBJECT
private slots:
+ void visible_data();
void visible();
+ void overlay_data();
void overlay();
+ void zOrder_data();
void zOrder();
void windowChange();
void closePolicy_data();
@@ -64,46 +67,67 @@ private slots:
void parentDestroyed();
};
+void tst_popup::visible_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::newRow("Window") << "window.qml";
+ QTest::newRow("ApplicationWindow") << "applicationwindow.qml";
+}
+
void tst_popup::visible()
{
- QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml"));
+ QFETCH(QString, source);
+ QQuickApplicationHelper helper(this, source);
- QQuickApplicationWindow *window = helper.appWindow;
+ QQuickWindow *window = helper.window;
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup*>();
QVERIFY(popup);
QQuickItem *popupItem = popup->popupItem();
popup->open();
QVERIFY(popup->isVisible());
- QVERIFY(window->overlay()->childItems().contains(popupItem));
+
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ QVERIFY(overlay);
+ QVERIFY(overlay->childItems().contains(popupItem));
popup->close();
QVERIFY(!popup->isVisible());
- QVERIFY(!window->overlay()->childItems().contains(popupItem));
+ QVERIFY(!overlay->childItems().contains(popupItem));
popup->setVisible(true);
QVERIFY(popup->isVisible());
- QVERIFY(window->overlay()->childItems().contains(popupItem));
+ QVERIFY(overlay->childItems().contains(popupItem));
popup->setVisible(false);
QVERIFY(!popup->isVisible());
- QVERIFY(!window->overlay()->childItems().contains(popupItem));
+ QVERIFY(!overlay->childItems().contains(popupItem));
+}
+
+void tst_popup::overlay_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::newRow("Window") << "window.qml";
+ QTest::newRow("ApplicationWindow") << "applicationwindow.qml";
}
void tst_popup::overlay()
{
- QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml"));
+ QFETCH(QString, source);
+ QQuickApplicationHelper helper(this, source);
- QQuickApplicationWindow *window = helper.appWindow;
+ QQuickWindow *window = helper.window;
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QQuickItem *overlay = window->overlay();
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ QVERIFY(overlay);
+
QSignalSpy overlayPressedSignal(overlay, SIGNAL(pressed()));
QSignalSpy overlayReleasedSignal(overlay, SIGNAL(released()));
QVERIFY(overlayPressedSignal.isValid());
@@ -115,10 +139,10 @@ void tst_popup::overlay()
QCOMPARE(overlayPressedSignal.count(), 0);
QCOMPARE(overlayReleasedSignal.count(), 0);
- QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup*>();
QVERIFY(popup);
- QQuickButton *button = helper.appWindow->property("button").value<QQuickButton*>();
+ QQuickButton *button = window->property("button").value<QQuickButton*>();
QVERIFY(button);
popup->open();
@@ -156,20 +180,28 @@ void tst_popup::overlay()
QVERIFY(!overlay->isVisible());
}
+void tst_popup::zOrder_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::newRow("Window") << "window.qml";
+ QTest::newRow("ApplicationWindow") << "applicationwindow.qml";
+}
+
void tst_popup::zOrder()
{
- QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml"));
+ QFETCH(QString, source);
+ QQuickApplicationHelper helper(this, source);
- QQuickApplicationWindow *window = helper.appWindow;
+ QQuickWindow *window = helper.window;
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup*>();
QVERIFY(popup);
popup->setModal(true);
- QQuickPopup *popup2 = helper.appWindow->property("popup2").value<QQuickPopup*>();
+ QQuickPopup *popup2 = window->property("popup2").value<QQuickPopup*>();
QVERIFY(popup2);
popup2->setModal(true);
@@ -220,32 +252,42 @@ void tst_popup::closePolicy_data()
{
qRegisterMetaType<QQuickPopup::ClosePolicy>();
+ QTest::addColumn<QString>("source");
QTest::addColumn<QQuickPopup::ClosePolicy>("closePolicy");
- QTest::newRow("NoAutoClose") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::NoAutoClose);
- QTest::newRow("CloseOnPressOutside") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside);
- QTest::newRow("CloseOnPressOutsideParent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutsideParent);
- QTest::newRow("CloseOnPressOutside|Parent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
- QTest::newRow("CloseOnReleaseOutside") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside);
- QTest::newRow("CloseOnReleaseOutside|Parent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
- QTest::newRow("CloseOnEscape") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnEscape);
+ QTest::newRow("Window:NoAutoClose") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::NoAutoClose);
+ QTest::newRow("Window:CloseOnPressOutside") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside);
+ QTest::newRow("Window:CloseOnPressOutsideParent") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutsideParent);
+ QTest::newRow("Window:CloseOnPressOutside|Parent") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
+ QTest::newRow("Window:CloseOnReleaseOutside") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside);
+ QTest::newRow("Window:CloseOnReleaseOutside|Parent") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
+ QTest::newRow("Window:CloseOnEscape") << "window.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnEscape);
+
+ QTest::newRow("ApplicationWindow:NoAutoClose") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::NoAutoClose);
+ QTest::newRow("ApplicationWindow:CloseOnPressOutside") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside);
+ QTest::newRow("ApplicationWindow:CloseOnPressOutsideParent") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutsideParent);
+ QTest::newRow("ApplicationWindow:CloseOnPressOutside|Parent") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
+ QTest::newRow("ApplicationWindow:CloseOnReleaseOutside") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside);
+ QTest::newRow("ApplicationWindow:CloseOnReleaseOutside|Parent") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
+ QTest::newRow("ApplicationWindow:CloseOnEscape") << "applicationwindow.qml"<< static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::CloseOnEscape);
}
void tst_popup::closePolicy()
{
+ QFETCH(QString, source);
QFETCH(QQuickPopup::ClosePolicy, closePolicy);
- QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml"));
+ QQuickApplicationHelper helper(this, source);
- QQuickApplicationWindow *window = helper.appWindow;
+ QQuickWindow *window = helper.window;
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
- QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickPopup *popup = window->property("popup").value<QQuickPopup*>();
QVERIFY(popup);
- QQuickButton *button = helper.appWindow->property("button").value<QQuickButton*>();
+ QQuickButton *button = window->property("button").value<QQuickButton*>();
QVERIFY(button);
popup->setModal(true);