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 in8d9a7e47aa
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 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> (cherry picked from commit05e0dc2a88
) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
e070c48ad4
commit
410c2a4440
|
@ -15,4 +15,6 @@ qt_internal_add_test(tst_qml
|
|||
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
LIBRARIES
|
||||
Qt::QuickTestUtilsPrivate
|
||||
Qt::Gui
|
||||
Qt::GuiPrivate
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue