Details
-
Bug
-
Resolution: Duplicate
-
P2: Important
-
None
-
5.13.2
-
None
Description
It is possible, with a quick succession of window state changes, for a Qt program to end up in a situation where (QWidget::windowState() & Qt::WindowMinized) == true even though the native window is not minimized. The following sample reproduces the problem with gnome (mutter):
// Build. g++ -std=c++17 -Wall -Wextra -g -fPIC $(pkg-config --cflags --libs Qt5Core Qt5Gui Qt5Widgets) -o example example.cc #include <iostream> #include <QApplication> #include <QLabel> #include <QTimer> int main(int argc, char **argv) { QApplication app(argc, argv); QLabel w(QLatin1String("Hello world")); w.show(); QTimer::singleShot(1000, [&] { w.setWindowState(w.windowState() | Qt::WindowMinimized); w.activateWindow(); }); QTimer::singleShot(3000, [&] { std::cout << "Window state: " << w.windowState() << std::endl; app.quit(); }); return app.exec(); }
The program above shows a window with the text "Hello world". After a second it will minimize and then immediately activate the window causing it to not be minimized again. After three seconds it prints the window state and quits. With gnome/mutter this prints "Window state: 1" (minimized) which is incorrect. It should print "Window state: 0".
I have also been able to reproduce the problem with metacity, though not as easily or reliably.
While the example above is synthetic I have observed this problem in a real application.
The problem is that w.setWindowState(w.windowState() | Qt::WindowMinimized); will update QWidget::windowState() directly and then effect the change via the platform QXcbWindow. QWidget::activateWindow() only affects the change via the platform QxcbWindow and relies on property notify events caused by the window manager updating WM_STATE and _NET_WM_STATE to feed the updated window state back to Qt. The problem is that QXcbWindow::handlePropertyNotifyEvent() ignores the updates because it determines that the new state reported is the same as the last update it reported by comparing it to QXcbWindow::m_lastWindowStateEvent.
I believe what goes wrong here is that if window state changes happen fast enough the window manager has changed the WM_STATE/_NET_WM_STATE to minimized and back to unminimized before QXcbWindow::handlePropertyNotifyEvent() runs, which means that from QXcbWindow's point of view there is nothing new to report and we never clear the Qt::WindowMinimized bit that was set directly by QWidget::setWindowState().
Attachments
Issue Links
- duplicates
-
QTBUG-68864 tst_QWidget_window::setWindowState autotest fails on Ubuntu 18.04
- Closed