Skip to content

Commit

Permalink
Revert "Update window state in QWindowsWindow and QXcbWindow geometry…
Browse files Browse the repository at this point in the history
… setters"

This reverts commit 99c8ffb. It fixed
QTBUG-104201, which in essence pointed out a state mismatch between
widgets and platform windows on Linux (X11 and wayland). Mismatches
occurred in the margins between calls to QWidget and async screen
rendering: While the widget layer reported the expected size, the
platform layer did so only after the rendering thread had finished.

As mentioned in the comments of QTBUG-104201, the state mismatch is
predictable, temporary and consistent.

By bridging the time gab, an async operation was made to look
synchronous. That gave more comfort to application developers. By
oversight, it broke code that relied on the platform window state
reflecting physical rendering. This has caused QTBUG-126479 as a
regression.

Both purposes can't be served at the same time: The platform window
state either reflects rendering, or the expected state. It's therefore
justified to revert.

Reason for revert: <Causes QTBUG-126479>

Pick-to: 6.8 6.7 6.5
Fixes: QTBUG-126479
Task-number: QTBUG-104201
Change-Id: I22380a6a463822a1cb4be90a44d2775954c7ca82
Reviewed-by: Liang Qi <[email protected]>
  • Loading branch information
ASpoerl authored and liangqi committed Jul 16, 2024
1 parent 49d5b0a commit 7d7be38
Show file tree
Hide file tree
Showing 3 changed files with 0 additions and 120 deletions.
4 changes: 0 additions & 4 deletions src/plugins/platforms/windows/qwindowswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2121,12 +2121,8 @@ 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),
Expand Down
2 changes: 0 additions & 2 deletions src/plugins/platforms/xcb/qxcbwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,6 @@ void QXcbWindow::destroy()

void QXcbWindow::setGeometry(const QRect &rect)
{
setWindowState(Qt::WindowNoState);

QPlatformWindow::setGeometry(rect);

propagateSizeHints();
Expand Down
114 changes: 0 additions & 114 deletions tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ private slots:
void reparent();
void setScreen();
void windowState();
void resizePropagation();
void showMaximized();
void showFullScreen();
void showMinimized();
Expand Down Expand Up @@ -3172,119 +3171,6 @@ 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

// Windows:
// When a widget is maximized after it has been resized, the widget retains its original size,
// while the window shows maximum size.
// windowStateChanged signal gets fired on a no-op change from/to WindowNoState

// Initialize widget and signal spy for window handle
QWidget widget;
widget.showMaximized();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
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);

enum CountIncrementCheck {Equal, Greater};
enum TargetSizeCheck {Fail, Warn};
auto verifyResize = [&](const QSize &size, Qt::WindowState windowState,
CountIncrementCheck checkCountIncrement,
TargetSizeCheck checkTargetSize)
{
// Capture count of latest async signals
if (checkCountIncrement == Equal)
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
switch (checkCountIncrement) {
case Greater: {
auto logger = qScopeGuard([&](){
qDebug() << "spy count:" << spy.count() << "previous count:" << count;
});
QTRY_VERIFY(spy.count() > count);
logger.dismiss();
count = spy.count();
}
break;
case Equal: {
auto logger = qScopeGuard([&](){
qDebug() << spy << widget.windowState() << window->windowState();
});
QCOMPARE(spy.count(), count);
logger.dismiss();
}
break;
}

// 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
switch (checkTargetSize) {
case Fail:
QCOMPARE(widget.size(), window->size());
break;
case Warn:
if (widget.size() != window->size()) {
qWarning() << m_platform << "size mismtach tolerated. Widget:"
<< widget.size() << "Window:" << window->size();
}
break;
}
};

// test state and size consistency of maximized window
verifyResize(QSize(), Qt::WindowMaximized, Equal, Fail);
if (QTest::currentTestFailed())
return;

// test state transition, state and size consistency after resize
verifyResize(size1, Qt::WindowNoState, Greater, xcb ? Warn : Fail );
if (QTest::currentTestFailed())
return;

// test unchanged state, state and size consistency after resize
verifyResize(size2, Qt::WindowNoState, Equal, xcb ? Warn : Fail);
if (QTest::currentTestFailed())
return;

// test state transition, state and size consistency after maximize
widget.showMaximized();
verifyResize(QSize(), Qt::WindowMaximized, Greater, xcb ? Fail : Warn);
if (QTest::currentTestFailed())
return;

#ifdef Q_OS_WIN
QCOMPARE(widget.size(), size2);
#endif
}

void tst_QWidget::showMaximized()
{
QWidget plain;
Expand Down

0 comments on commit 7d7be38

Please sign in to comment.