aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@digia.com>2013-11-27 17:57:25 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-30 17:56:22 +0100
commitd0644b040eb09e1ed147ff15e7c926c9e318cbca (patch)
tree2c6d9d08fc521c13c80cbeb300655042a3ef2870
parenta6348870ee1fc7b0270ceebf0f13dee7e5e54719 (diff)
Ensure that QML Windows respect the default platform window state
The 'visible' property of a Window would be set on the baseclass QWindow like any other property during QML component creation, which would cause create() to be called and the platform window would be created. This left the 'visibility' of the QML window as Windowed, not respecting the platform defaults for how windows should be shown. The user would have to explicitly set "visibility: Window.AutomaticVisibility" for this default to apply, which doesn't make sense -- it should be the default. We solve this by deferring setVisible and setVisibility on the window until the component is complete and we have a full picture of its state. We then ask the platform for the default state based on the window flags (ensuring that eg "flags: Qt.Popup" will not result in maximized windows on iOS and Android), and apply the deferred visibility. The deferred visibility may still be 'false', but setting the window state makes sense anyways, so that a later "visible = true" will apply the default window state. Deferring platform window creation until the geometry has been potentially set from user code also has the benefit that the platform window can check the geometry and apply a default geometry if it's null. This was not possible when the 'visible' property was a regular property, as you could not know if the user's geometry changes would come after platform window creation. Task-number: QTBUG-35174 Change-Id: Icf3236187992048a85b2196c059f9b54699041a4 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com> Reviewed-by: Robin Burchell <robin+qt@viroteck.net> Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
-rw-r--r--src/quick/items/qquickwindowmodule.cpp80
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp20
2 files changed, 99 insertions, 1 deletions
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index b91edc2fd5..cd1b68991d 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -45,12 +45,50 @@
#include <QtCore/QCoreApplication>
#include <QtQml/QQmlEngine>
+#include <private/qguiapplication_p.h>
+#include <private/qqmlengine_p.h>
+#include <qpa/qplatformintegration.h>
+
QT_BEGIN_NAMESPACE
class QQuickWindowQmlImpl : public QQuickWindow, public QQmlParserStatus
{
Q_INTERFACES(QQmlParserStatus)
Q_OBJECT
+
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged)
+
+public:
+ QQuickWindowQmlImpl(QWindow *parent = 0)
+ : QQuickWindow(parent)
+ , m_complete(false)
+ , m_visible(isVisible())
+ , m_visibility(AutomaticVisibility)
+ {
+ connect(this, &QWindow::visibleChanged, this, &QQuickWindowQmlImpl::visibleChanged);
+ connect(this, &QWindow::visibilityChanged, this, &QQuickWindowQmlImpl::visibilityChanged);
+ }
+
+ void setVisible(bool visible) {
+ if (!m_complete)
+ m_visible = visible;
+ else
+ QQuickWindow::setVisible(visible);
+ }
+
+ void setVisibility(Visibility visibility)
+ {
+ if (!m_complete)
+ m_visibility = visibility;
+ else
+ QQuickWindow::setVisibility(m_visibility);
+ }
+
+Q_SIGNALS:
+ void visibleChanged(bool arg);
+ void visibilityChanged(QWindow::Visibility visibility);
+
protected:
void classBegin() {
//Give QQuickView behavior when created from QML with QQmlApplicationEngine
@@ -61,7 +99,47 @@ protected:
}
}
- void componentComplete() {}
+ void componentComplete() {
+ m_complete = true;
+
+ // We have deferred window creation until we have the full picture of what
+ // the user wanted in terms of window state, geometry, visibility, etc.
+
+ if ((m_visibility == Hidden && m_visible) || (m_visibility > AutomaticVisibility && !m_visible)) {
+ QQmlData *data = QQmlData::get(this);
+ Q_ASSERT(data && data->context);
+
+ QQmlError error;
+ error.setObject(this);
+
+ const QQmlContextData* urlContext = data->context;
+ while (urlContext && urlContext->url.isEmpty())
+ urlContext = urlContext->parent;
+ error.setUrl(urlContext ? urlContext->url : QUrl());
+
+ QString objectId = data->context->findObjectId(this);
+ if (!objectId.isEmpty())
+ error.setDescription(QCoreApplication::translate("QQuickWindowQmlImpl",
+ "Conflicting properties 'visible' and 'visibility' for Window '%1'").arg(objectId));
+ else
+ error.setDescription(QCoreApplication::translate("QQuickWindowQmlImpl",
+ "Conflicting properties 'visible' and 'visibility'"));
+
+ QQmlEnginePrivate::get(data->context->engine)->warning(error);
+ }
+
+ if (m_visibility == AutomaticVisibility) {
+ setWindowState(QGuiApplicationPrivate::platformIntegration()->defaultWindowState(flags()));
+ setVisible(m_visible);
+ } else {
+ setVisibility(m_visibility);
+ }
+ }
+
+private:
+ bool m_complete;
+ bool m_visible;
+ Visibility m_visibility;
};
void QQuickWindowModule::defineModule()
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 984881c8da..b09f80a634 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -304,6 +304,7 @@ private slots:
void qmlCreation();
void clearColor();
+ void defaultState();
void grab_data();
void grab();
@@ -955,6 +956,25 @@ void tst_qquickwindow::clearColor()
QCOMPARE(window->color(), QColor(Qt::blue));
}
+void tst_qquickwindow::defaultState()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0; import QtQuick.Window 2.1; Window { }", QUrl());
+ QObject *created = component.create();
+ QScopedPointer<QObject> cleanup(created);
+ QVERIFY(created);
+
+ QQuickWindow *qmlWindow = qobject_cast<QQuickWindow*>(created);
+ QVERIFY(qmlWindow);
+
+ QQuickWindow cppWindow;
+ cppWindow.show();
+ QTest::qWaitForWindowExposed(&cppWindow);
+
+ QCOMPARE(qmlWindow->windowState(), cppWindow.windowState());
+}
+
void tst_qquickwindow::grab_data()
{
QTest::addColumn<bool>("visible");