Update window state in QWindowsWindow and QXcbWindow geometry setters
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 Pick-to: 6.4 Change-Id: I07491fb9293d13509573fc403750da0a50f6a785 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
8790da8988
commit
99c8ffb9f2
@ -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),
|
||||
|
@ -515,6 +515,8 @@ void QXcbWindow::destroy()
|
||||
|
||||
void QXcbWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
setWindowState(Qt::WindowNoState);
|
||||
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
|
||||
propagateSizeHints();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user