aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2023-09-05 22:00:43 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2023-09-12 07:07:51 +0200
commit05e0dc2a88e751e97573610fd483f79da3e78854 (patch)
treecb34c668a8b27f717ae98577fa9e93a304020563
parentcbef79711453bc65540c282897acbfe8c7a35c3f (diff)
Remove resize guards from qml tool
Resize guards were prohibiting the initialization of the top level item size to the window size in a qml script when executed with the qml tool. This is usually fine because the window size is set to the item size. However, if this is not possible (minimum window size from the system, no explicit size on the item), the item has a different size than the window. The item would only be adapted to the window size after resizing the window. This patch removes the resize guards to make the item always fill the window on startup. The resize guard should hopefully not be needed; the QQuickItem setters for width and height return early if it's unchanged; QWindow::resize() does not emit changed signals if there is not yet a platform window and width or height is unchanged; and we hope all the overrides of QPlatformWindow::setGeometry() will avoid making unnecessary changes. However the guards were added in 8d9a7e47aaa03efe2d3eddfc9ac37d02a99affc7 and I don't remember exactly why. Adds the test tst_qml::itemAndWindowGeometry to check combinations of --config, --qwindowgeometry and qml files whose root item has or doesn't have its own dimensions, or changes its dimensions after being shown. Done-with: Matthias Rauter <matthias.rauter@qt.io> Pick-to: 6.5 6.6 Fixes: QTBUG-114068 Fixes: QTBUG-116753 Change-Id: Ib972e0bfc25809441d378c53dabb60653314f5a6 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--tests/auto/qml/qml/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qml/data/resizeItem.qml28
-rw-r--r--tests/auto/qml/qml/data/sizedItem.qml19
-rw-r--r--tests/auto/qml/qml/data/unsizedItem.qml18
-rw-r--r--tests/auto/qml/qml/tst_qml.cpp125
-rw-r--r--tools/qml/ResizeItemToWindow.qml7
6 files changed, 194 insertions, 5 deletions
diff --git a/tests/auto/qml/qml/CMakeLists.txt b/tests/auto/qml/qml/CMakeLists.txt
index 66b7981105..39056384de 100644
--- a/tests/auto/qml/qml/CMakeLists.txt
+++ b/tests/auto/qml/qml/CMakeLists.txt
@@ -21,4 +21,6 @@ qt_internal_add_test(tst_qml
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
LIBRARIES
Qt::QuickTestUtilsPrivate
+ Qt::Gui
+ Qt::GuiPrivate
)
diff --git a/tests/auto/qml/qml/data/resizeItem.qml b/tests/auto/qml/qml/data/resizeItem.qml
new file mode 100644
index 0000000000..c416451ccc
--- /dev/null
+++ b/tests/auto/qml/qml/data/resizeItem.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Timer {
+ id: resizeTimer
+ running: false
+ onTriggered: {
+ rect.width = 100
+ rect.height = 50
+ exitTimer.start()
+ }
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ resizeTimer.start()
+ }
+}
diff --git a/tests/auto/qml/qml/data/sizedItem.qml b/tests/auto/qml/qml/data/sizedItem.qml
new file mode 100644
index 0000000000..edcb0e8629
--- /dev/null
+++ b/tests/auto/qml/qml/data/sizedItem.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "blue"
+ width: 200; height: 150
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/data/unsizedItem.qml b/tests/auto/qml/qml/data/unsizedItem.qml
new file mode 100644
index 0000000000..e32784762f
--- /dev/null
+++ b/tests/auto/qml/qml/data/unsizedItem.qml
@@ -0,0 +1,18 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/tst_qml.cpp b/tests/auto/qml/qml/tst_qml.cpp
index de884d8257..2014f1d561 100644
--- a/tests/auto/qml/qml/tst_qml.cpp
+++ b/tests/auto/qml/qml/tst_qml.cpp
@@ -4,8 +4,13 @@
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qprocess.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+Q_LOGGING_CATEGORY(lcQml, "qt.qml.tests");
+
class tst_qml : public QQmlDataTest
{
Q_OBJECT
@@ -15,6 +20,8 @@ public:
private slots:
void initTestCase() override;
void nonWindow();
+ void itemAndWindowGeometry_data();
+ void itemAndWindowGeometry();
private:
QString qmlPath;
@@ -42,6 +49,124 @@ void tst_qml::nonWindow()
QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2
}
+void tst_qml::itemAndWindowGeometry_data()
+{
+ QTest::addColumn<QString>("config");
+ QTest::addColumn<QString>("geometry");
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QSize>("expectedWindowSize");
+ QTest::addColumn<QSize>("expectedContentSize");
+
+ const QString none; // empty string
+
+ auto sizeOrInvalid = [](int w, int h) {
+ static const bool wm = QGuiApplicationPrivate::platformIntegration()->
+ hasCapability(QPlatformIntegration::WindowManagement);
+ return wm ? QSize(w, h) : QSize();
+ };
+
+ QTest::newRow("default: unsized")
+ << none << none << "unsizedItem.qml"
+ << QSize() << QSize(); // default size depends on window system
+ QTest::newRow("default: unsized with geometry")
+ << none << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: unsized")
+ << "resizeToItem" << none << "unsizedItem.qml"
+ << QSize() << QSize(0, 0);
+ QTest::newRow("resizeToItem: unsized with geometry")
+ << "resizeToItem" << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << QSize(0, 0);
+
+ QTest::newRow("default: sized")
+ << none << none << "sizedItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: sized with geometry")
+ << none << "100x100+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: sized")
+ << "resizeToItem" << none << "sizedItem.qml"
+ << sizeOrInvalid(200, 150) << sizeOrInvalid(200, 150);
+ QTest::newRow("resizeToItem: sized with geometry")
+ << "resizeToItem" << "320x240+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(320, 240) << QSize(200, 150);
+
+ QTest::newRow("default: resizing")
+ << none << none << "resizeItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: resizing with geometry")
+ << none << "100x100+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: resizing")
+ << "resizeToItem" << none << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+ QTest::newRow("resizeToItem: resizing with geometry")
+ << "resizeToItem" << "320x240+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+}
+
+/*
+ - A root Item will get put into a Window depending on config (implementations in
+ tools/qml/ResizeItemToWindow.qml and ResizeWindowToItem.qml).
+ - The window system will enforce a minimum size.
+ - In the default configuration, the root Item should then get resized to fit
+ (QTBUG-114068 / QTBUG-116753).
+ - In resizeToItem configuration, if the item width/height are not set, the window would
+ try to be 0x0, but the window system won't allow it.
+ - This also tests the `--qwindowgeometry` argument: with the default config, the
+ item should be resized to fit, but not with `-c resizeToItem`.
+*/
+void tst_qml::itemAndWindowGeometry()
+{
+#ifdef Q_OS_WIN
+ QSKIP("console.info does not go to stderr on Windows.");
+#endif
+
+ QFETCH(QString, config);
+ QFETCH(QString, geometry);
+ QFETCH(QString, qmlfile);
+ QFETCH(QSize, expectedWindowSize);
+ QFETCH(QSize, expectedContentSize);
+
+ QStringList args;
+ if (!config.isEmpty())
+ args << "-c" << config;
+ if (!geometry.isEmpty())
+ args << "--qwindowgeometry" << geometry;
+ args << testFile(qmlfile);
+ QProcess qml;
+ qml.start(qmlPath, args);
+ QVERIFY(qml.waitForFinished());
+ QCOMPARE(qml.exitStatus(), QProcess::NormalExit);
+ const QByteArray output = qml.readAllStandardError();
+ const auto sizeLineIndex = output.lastIndexOf("window");
+ QCOMPARE_GE(sizeLineIndex, 0);
+ const auto newlineIndex = output.indexOf('\n', sizeLineIndex);
+ QCOMPARE_GT(newlineIndex, sizeLineIndex);
+ // expect a line like "window 120 120 content 120 120"
+ const auto sizes = output.sliced(sizeLineIndex, newlineIndex - sizeLineIndex).split(' ');
+ QCOMPARE_GE(sizes.size(), 6);
+ QCOMPARE(sizes[0], "window");
+ QCOMPARE(sizes[3], "content");
+ const QSize windowSize(sizes[1].toInt(), sizes[2].toInt());
+ const QSize contentSize(sizes[4].toInt(), sizes[5].toInt());
+ qCDebug(lcQml) << sizes
+ << "window" << windowSize << "expect" << expectedWindowSize
+ << "content" << contentSize << "expect" << expectedContentSize;
+ QVERIFY(!windowSize.isEmpty());
+ if (config != "resizeToItem") {
+ // default config:
+ // ResizeItemToWindow.qml should have resized the item to its window
+ QCOMPARE(contentSize, windowSize);
+ }
+ // windowSize can be off-by-one on hidpi (e.g. QT_SCALE_FACTOR=2 on xcb);
+ // perhaps that's a bug somewhere, but so far we aren't testing hidpi on CI
+ if (expectedWindowSize.isValid())
+ QCOMPARE(windowSize, expectedWindowSize);
+ if (expectedContentSize.isValid())
+ QCOMPARE(contentSize, expectedContentSize);
+}
+
QTEST_MAIN(tst_qml)
#include <tst_qml.moc>
diff --git a/tools/qml/ResizeItemToWindow.qml b/tools/qml/ResizeItemToWindow.qml
index 4a6d06591c..fa31ebf943 100644
--- a/tools/qml/ResizeItemToWindow.qml
+++ b/tools/qml/ResizeItemToWindow.qml
@@ -5,19 +5,16 @@ import QtQuick 2.0
Window {
property Item containedObject: null
- property bool __resizeGuard: false
onContainedObjectChanged: {
if (containedObject == undefined || containedObject == null) {
visible = false;
return;
}
- __resizeGuard = true
width = containedObject.width;
height = containedObject.height;
containedObject.parent = contentItem;
visible = true;
- __resizeGuard = false
}
- onWidthChanged: if (!__resizeGuard && containedObject) containedObject.width = width
- onHeightChanged: if (!__resizeGuard && containedObject) containedObject.height = height
+ onWidthChanged: if (containedObject) containedObject.width = width
+ onHeightChanged: if (containedObject) containedObject.height = height
}