From ba2584126b2047011e29ba0ea98bc55bd504ea62 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Wed, 15 Jun 2022 23:50:30 +0200 Subject: Update window state in QWindowsWindow and QXcbWindow geometry setters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QWidget::resize() is called on a maximized or minimized QWidget, the window state of the widget and the corresponding QWindow is not updated (i.e. remains maximized or minimized). This patch updates the window state to Qt:WindowNoState when setGeometry() is called in QWindowsWindow or QXcbWindow. A test is added in tst_QWidget. Fixes: QTBUG-104201 Change-Id: I07491fb9293d13509573fc403750da0a50f6a785 Reviewed-by: Tor Arne Vestbø Reviewed-by: Volker Hilsheimer (cherry picked from commit 99c8ffb9f259760e45618f0988bbd79237d6d291) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'tests') diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 06cb89f4d8..f65882611b 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -180,6 +180,7 @@ private slots: void reparent(); void setScreen(); void windowState(); + void resizePropagation(); void showMaximized(); void showFullScreen(); void showMinimized(); @@ -2675,6 +2676,102 @@ void tst_QWidget::windowState() QTRY_COMPARE(widget1.size(), size); } +// Test propagation of size and state from platform window to QWidget +// Windows and linux/XCB only +void tst_QWidget::resizePropagation() +{ +#if !defined(Q_OS_LINUX) && !defined(Q_OS_WIN) + QSKIP("resizePropagation test is designed for Linux/XCB and Windows only"); +#endif + const bool xcb = (m_platform == QStringLiteral("xcb")); +#ifdef Q_OS_LINUX + if (!xcb) + QSKIP("resizePropagation test is designed for XCB only"); +#endif + + // Platform specific notes: + // Linux/XCB: + // - Unless maximized, a widget and its corresponding window can have different sizes + // - windowStateChanged can be fired multiple times (QTBUG-102478) when widget is maximized + // + // Windows: + // When a widget is maximized after it has been resized, the widget retains its original size, + // while the window shows maximum size + + // Initialize widget and signal spy for window handle + QWidget widget; + widget.showMaximized(); + QWindow *window = widget.windowHandle(); + QTRY_VERIFY(window); + QSignalSpy spy(window, &QWindow::windowStateChanged); + int count = 0; + + const QSize screenSize = QGuiApplication::primaryScreen()->size(); + const QSize size1 = QSize(screenSize.width() * 0.5, screenSize.height() * 0.5); + const QSize size2 = QSize(screenSize.width() * 0.625, screenSize.height() * 0.833); + + auto verifyResize = [&](const QSize &size, Qt::WindowState windowState, bool checkCountIncrement, bool checkTargetSize) + { + // Capture count of latest async signals + if (!checkCountIncrement) + count = spy.count(); + + // Resize if required + if (size.isValid()) + widget.resize(size); + + // Wait for the widget anyway + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + // Check signal count and qDebug output for fail analysis + if (checkCountIncrement) { + QTRY_VERIFY(spy.count() > count); + qDebug() << "spy count:" << spy.count() << "previous count:" << count; + count = spy.count(); + } else { + qDebug() << spy << widget.windowState() << window->windowState(); + QCOMPARE(spy.count(), count); + } + + // QTRY necessary because state changes are propagated async + QTRY_COMPARE(widget.windowState(), windowState); + QTRY_COMPARE(window->windowState(), windowState); + + // Check target size with fail or warning + if (checkTargetSize) { + QCOMPARE(widget.size(), window->size()); + } else if (widget.size() != window->size()) { + qWarning() << m_platform << "size mismtach tolerated. Widget:" + << widget.size() << "Window:" << window->size(); + } + }; + + // test state and size consistency of maximized window + verifyResize(QSize(), Qt::WindowMaximized, true, true); + if (QTest::currentTestFailed()) + return; + + // test state transition, state and size consistency after resize + verifyResize(size1, Qt::WindowNoState, true, !xcb ); + if (QTest::currentTestFailed()) + return; + + // test unchanged state, state and size consistency after resize + verifyResize(size2, Qt::WindowNoState, false, !xcb); + if (QTest::currentTestFailed()) + return; + + // test state transition, state and size consistency after maximize + widget.showMaximized(); + verifyResize(QSize(), Qt::WindowMaximized, true, xcb); + if (QTest::currentTestFailed()) + return; + +#ifdef Q_OS_WIN + QCOMPARE(widget.size(), size2); +#endif +} + void tst_QWidget::showMaximized() { QWidget plain; -- cgit v1.2.3