Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.11, 5.12.2, 5.14.0, 6.0
-
-
51300566ffe2ece2455e1d0479a556c5dbb3bb8e, ec09900997e9b92206938ca5f9fe2e356440e513
Description
In Qt 5.11 and 5.12 native widgets inside a QDockWidget cause strange behavior. If the dock widget is closed via the Close button in docked state, via hide(), or by using toggleViewAction(), things are ok. Only if the Close button in floating state is used, the dock widget won't show() again. The apparent problem is that the latter will destroy the underlying QWidgetWindow resources in a way that show() won't recreate them.
Steps to reproduce:
- open the original Dock Widgets Example in Qt Creator
- in MainWindow::createDockWindows(), add the line "customerList->winId();" after the line "viewMenu->addAction(dock->toggleViewAction());"
- run the example
- close the docked "Customers" dock widget by using the menu "View->Customers"
- show the "Customers" dock widget again by using the menu "View->Customers"
- close the docked "Customers" dock widget by pressing its close button
- show the "Customers" dock widget again by using the menu "View->Customers"
- undock the "Customers" dock widget
- close the floating "Customers" dock widget by using the menu "View->Customers"
- show the "Customers" dock widget again by using the menu "View->Customers"
- close the floating "Customers" dock widget by pressing its close button
- show the "Customers" dock widget again by using the menu "View->Customers"
Expected result: showing the dock widget (steps 5, 7, 10, 12) makes it visible in its previous location
Actual result: step 12 fails to make the dock widget visible
Notes:
- steps 4-7 and 9-10 are not needed to reproduce the issue. They only demonstrate things are working properly.
- The issue can be reproduced in earlier versions. In our application it showed first time when upgrading from 5.11.1 to 5.12.0, but the example reproduces the issue in 5.11.0.
- Our application uses Direct3D rendering in a widget inside the dock widget, hence the winId() call.
- I did some more investigation and found the difference to be a close event being first delivered to the internal QWidgetWindow in step 11, which destroys its resources in a way that the next QDockWidget::show() won't recreate them.
- In our application, the change that made the issue surface in 5.12 is this: https://code.qt.io/cgit/qt/qtbase.git/commit/src/widgets/kernel/qwidgetwindow.cpp?id=e0b5ff4ad583befbecbcbe462998e3ed80899531, but as mentioned, the actual problem exists in 5.11 (and probably earlier) already.
- I only use Windows, I don't know if the same issue exists on other platforms
Based on my investigation I found a workaround: Implement an event filter like this (for the dock widget example)
bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (event->type()==QEvent::Close) { if (nativeDock && obj==nativeDock->windowHandle()) { nativeDock->hide(); return true; } } return false; }
and add it to qApp (nativeDock is a pointer to the QDockWidget containing a native child). This filter intercepts the offending close event to the QWidgetWindow and turns it into a working hide() call on the dock widget. While this workaround stops the issue, I don't know if it causes resource leaks.
I attached the modified dock widget example including the disabled workaround. I marked my changes with "// NEW". Uncommenting line mainwindow.cpp:339 will enable the workaround.
Attachments
Issue Links
- relates to
-
QTBUG-70137 Dockwidgets - Placing QDockWidget is almost impossible
- Closed
-
QTBUG-71519 Inconsistent handling of "close" w/QWindows
- Closed
-
QTBUG-79147 Windows: QColorDialog displays at wrong position when reshowing after closing via title bar
- Closed
-
QTBUG-93064 macOS: Setting Qt::WA_NativeWindow breaks dockwidget's behavior
- Closed