summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp97
3 files changed, 103 insertions, 0 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index c953abbc61..8792c46e02 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2094,8 +2094,12 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
+
if (m_windowState & Qt::WindowMinimized)
m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
+ else
+ setWindowState(Qt::WindowNoState);// Update window state to WindowNoState unless minimized
+
if (m_data.hwnd) {
// A ResizeEvent with resulting geometry will be sent. If we cannot
// achieve that size (for example, window title minimal constraint),
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 0162d058a6..c18c1fcfd9 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -515,6 +515,8 @@ void QXcbWindow::destroy()
void QXcbWindow::setGeometry(const QRect &rect)
{
+ setWindowState(Qt::WindowNoState);
+
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
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;