Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MAYA-131961: Apply docking fixes from Qt 6.7
This patch includes a series of 14 commits that were cherry-picked from Qt dev branch at the time Qt 6.7 was being developed. The commits were squashed together into one commit to more clearly delineate them as going together. These changes are intended to be included in Maya 2025.1 Here is my working list of things I cherry-picked, with titles and a few notes. --- Starting from the tip of dev, collecting all related commits that should be cherry-picked into Maya's Qt 6.5.3 branch after Senthil's QDockWidget patch is reverted: 3591ea9 - Not strictly necessary, but improves internal docs for QDockWidgetGroupWindow regarding need for it to not be focusable when only one child QDockWidget Sorta related, but not specifically to this relation chain: d462c7b - QMainWindowTabBar: make destructor public e6d85cf -- This is the main fix we want - "QDockWidget: Fix group unplugging" 0b10b74 - Refactor tst_QDockWidget::closeAndDelete() 26ded9d - tst_QDockWidget: use local context for timer 17372fa - Remove bool trap in QDockWidgetPrivate::endDrag() -- NOTE: This one requires manual conflict resolution in QDockWidget::startDrag, drop that change. The change it makes is in a newer commit from Qt 6.6 related to Wayland that we don't really need for this fix. c93ab8c - QDockWidget: Remove "group" bool trap -- this one also requires manual conflict resolution, but I can't find out what is different... c02f8b9 - Fully export QDockWidget debug operator bbeff2a - Extend qDebug functionality for QDockWidget b6b489d - QMainWindowTabBar: Add destructor 2c96f51 - QDockAreaLayout: implement widget based add() and remove() 1ab91b7 - QDockWidget: call raise() when a dock widget starts to hover 4c60a11 - QDockWidget: Always show dock widgets with the main window 0e435b7 - QMainWindowLayout: remove redundant #ifdef'ry --- Below you will find the commit messages of each of the cherry-picked commits, starting with the newest (so, for cherry-picking, you would apply in reverse order). At the top of the entry will have the qt dev branch commit hash that was cherry-picked, for easy lookup. Below that will be an indication that manual conflict resolution was needed to apply it to this branch, and what manual changes were needed. ================================= cherry-picked from 3591ea9 Harden internal documentation of QDockWidgetGroupWindow QDockWidgetGroupWindow was documented by a few lines of code comments, omitting the most critical part of its design: It must not become able to acquire focus (i.e. be dragged or dropped) while having only one QDockWidget child. => replace legacy code comments by structured internal documentation. Pick-to: 6.6 6.5 Change-Id: I410ebf2e4c20c7479038417a4d8448dce8ab995f Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from d462c7b QMainWindowTabBar: make destructor public Was private by mistake => make it public. Pick-to: 6.6 6.5 Change-Id: I6b07a19687ddf84e8456aa70bc34b1cc714a299e Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from e6d85cf QDockWidget: Fix group unplugging A floating dock widget could either be a single QDockWidget object, or a QDockWidgetGroupWindow with a single QDockWidget child. The former could be dropped on the latter. Dropping the latter on the former caused a crash. The existence of QDockWidgetGroupWindows with a single dock widget child was accepted to be by design. Previous fixes, such as 9ff40b5, attempted to wrap all single floating dock widgets in QDockWidgetGroupWindows. These attempts fell short, because of the manifold programmatic and manual options to create a floating dock widget: - drag a single dock widget out of a main window dock area - drag a dock widget out of a tab bar on the main window - drag a dock widget out of a floating tab - call `QDockWidget::setFloating(true)` in any situation - create a new QDockWidget, that floats from the beginning Whenever a QDockWidgetGroupWindow with a single QDockWidget child was hovered and/or dropped on a QDockWidget without a group window, crashes or screen artifacts were observed. Previous fixes made them occur less often. QDockWidgetGroupWindow is not designed to hold a single QDockWidget child. Such a state is inconsistent and may only exist, while a QDockWidgetGroupWindow is constructed. The reason why such invalid QDockWidgetGroupWindows started to exist, is a bool trap: QDockWidgetPrivate::mouseMoveEvent() starts a drag operation, when a dock widget is moved by mouse. It called startDrag() with no argument, which defaulted to startDrag(true) and caused a group drag. This assumption is *correct*, when a tabbed group of dock widgets is dragged out of the main dock as a whole, to become floating tabs. *wrong*, when a single dock widget is dragged out of a docked group, to become a single floating dock widget. In the second case, the dock widget was wrapped in a new, floating, invisible QDockWidgetGroupWindow. Looking like a single, floating dock widget, the group window caused a crash, when attempted to be dropped on another dock widget. This patch eliminates all cases, where a QDockWidgetGroupWindow with a single QDockWidget is created: (1) Implement QDockWidgetPrivate::isTabbed(). This enables mouseMoveEvent to determine, whether the move relates to a group of tabbed dock widgets, or to a single dock widget. startDrag() can therefore be called with the right argument. It will no longer create a QDockWidgetGroupWindow with a single QDockWidget child. (2) Change QMainWindowTabBar::mouseReleaseEvent When a dock widget was dragged out of a tab bar and became a single, floating dock widget, it was still parented to the group window. That is wrong, because it has no more relationship with that group window. => Reparent it to the main window, just like any other single floating dock widget. That enables QDockWidgetGroupWindow to detect, that the 2nd last child has gone and no more group window is needed (see next point). (3) React to reparenting, closing and deleting If the second last dock widget in a floating tab gets closed (manually or programmatically), reparented or deleted, also unplug the last one and remove the group window. (4) Amend 9ff40b5 Remove the code path where a QDockWidgetGroupWindow with a single QDockWidget child was created 'just in case', to make it compatible others, created by (1), (2) or (3). (5) Change QMainWindowLayout::hover() When the hover ends without a successful drop and a temporary group window with a single dock widget child has been created, remove the group window. The patch fixes smaller inconsistencies, which have not become visible due to assertions and crashes earlier in the chain. The patch finally extends tst_QDockWidget, to cover all 4 cases. - Creation of floating tabs The creation of floating tabs is extracted from floatingTabs() to the helper function createFloatingTabs(). In addition to creating floating tabs, the helper verifies that dragging a dock widget out of the main window doesn't accidently wrap it in a group window. This covers case (1). - tst_QDockWidget::floatingTabs() The test function verifies now, that both test dock widgets have the same path before plugging them together and after unplugging them from the floating tab. This covers case(4). - tst_QDockwidget::deleteFloatingTabWithSingleDockWidget() This test function is added, to cover cases (2) and (3). - tst_QDockWidget::hoverWithoutDrop() This test function hovers two floating dock widgets hover each other, and returns the moved dock widget to its origin before releasing the mouse. This covers case(5). This fixes a lot of long standing bugs, making the author of this patch modestly happy :-) Fixes: QTBUG-118223 Fixes: QTBUG-99136 Fixes: QTBUG-118578 Fixes: QTBUG-118579 Fixes: QTBUG-56799 Fixes: QTBUG-35736 Fixes: QTBUG-63448 Fixes: QTBUG-88329 Fixes: QTBUG-88157 Fixes: QTBUG-94097 Fixes: QTBUG-44540 Fixes: QTBUG-53808 Fixes: QTBUG-72915 Fixes: QTBUG-53438 Found-by: Keith Kyzivat <[email protected]> Found-by: Frederic Lefebvre <[email protected]> Pick-to: 6.6 6.5 Change-Id: I51b5f9e40cb2dbe55fb14d769541067730538463 Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from 0b10b74 Refactor tst_QDockWidget::closeAndDelete() The test function was temporarily blacklisted on Ubuntu, but also failing on other Linux platforms (e.g. openSuSE). It tested, whether closing all dock widgets and the main window, would close the application as well. It used one single shot timer, to close the windows and later one to check, whether the application was shut down. While that mechanism must work in an application environment, it is not guaranteed to work in testlib. More specifically, I could happen that the XCB / glib event loop continued to spin and wait for events. => Check the signal QGuiApplication::lastWindowClosed() instead. If the signal is fired, it is proven that all windows have been closed and the application would quit in a production environment. The underlying test case was: Application didn't quit with the last dock widget closed, because there was a dangling QDockWidgetGroupWindow. => finally: Clean up BLACKLIST Pick-to: 6.6 6.5 Change-Id: Ic5fde5967fc8dde70ab64dc30cc7367c908b5c51 Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from 26ded9d tst_QDockWidget: use local context for timer If we use 'this' as context it might still try to invoke the timer after we have left the function, leading to stack-use-after-return. To avoid doing an in-depth dive if it's okay to use mainWindow as the context or not, I just added a new local QObject. Amends 9ff40b5 Pick-to: 6.6 6.5 Change-Id: I2c3bdc1eb06731d9c38979610303876c2748fb73 Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from 17372fa Manual conflict resolution: This was built ontop of a change made for wayland, which I decided didn't need to be cherry-picked. In the conflict area, just drop the one conflict as the change made was modifying the change introduced by the wayland change. Remove bool trap in QDockWidgetPrivate::endDrag() endDrag(false) meant to end a drag with a dock location change. endDrag(true) meant to abort a drag without a dock location change. Replace this with a meaningful enumeration. Define a dummy enum for builds w/o QDockWidget. Task-number: QTBUG-118578 Task-number: QTBUG-118579 Pick-to: 6.6 6.5 Change-Id: I786f4210f5a3ee67ffcf0dc9285f77a480148569 Reviewed-by: David Faure <[email protected]> ================================= cherry-picked from c93ab8c Manual conflict resolution: Unclear what changed - all changes in the commit apply, but git stopped for manual conflict resolution. Possibly a whitespace change. QDockWidget: Remove "group" bool trap The unplug() and startDrag() functions of QMainWindowLayout and QDockWidget used a boolean argument specifying whether a single dock widget or a group of dock widgets should be unplugged. The argument defaulted to true. That has lead to inconsistent unplug operations, broken item_lists and crashes, especially when the methods were called without an argument. To improve code readability, replace bool trap with a meaningful enum. Remove default arguments, in order to force explicit calls. This patch does not change behavior, it is just carved out to facilitate reviews. Task-number: QTBUG-118578 Task-number: QTBUG-118579 Pick-to: 6.6 6.5 Change-Id: I50341b055f0bb76c2797b2fb1126a10de1fee7dd Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from c02f8b9 Fully export QDockWidget debug operator Amends bbeff2a. Task-number: QTBUG-118578 Task-number: QTBUG-118579 Found-by: Friedemann Kleint <[email protected]> Pick-to: 6.6 Change-Id: I60d8d11a82ff5de8b9641c86b824969fc9a34b91 Reviewed-by: Friedemann Kleint <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]> ================================= cherry-picked from bbeff2a Extend qDebug functionality for QDockWidget Add features and floating flag to QDockWidget debugging. Debug dockwidget parents of a group window. Task-number: QTBUG-118578 Task-number: QTBUG-118579 Pick-to: 6.6 Change-Id: If2a6caacf5d02f9018c2a3073fdbc1de39bce1ee Reviewed-by: Santhosh Kumar <[email protected]> Reviewed-by: Keith Kyzivat <[email protected]> ================================= cherry-picked from b6b489d QMainWindowTabBar: Add destructor QMainWindowLayout re-uses tab bars. A QSet and a QList member are kept, to track used and unused tab bars. Corner cases upon application close down leave dangling pointers in those containers. => Add a destructor to QMainWindowTabBar => remove the tab bar from used and unused tab bar containers, if not directly parented to the main window. => No longer reparent unused tab bars of a QDockWidgetGroupWindow to the main window. Let them be destroyed as a group window child, and its destructor remove it from the used/unused tab bar container. Pick-to: 6.6 6.5 Change-Id: If2388cf878553dc89583dbc8585748fad65bbab2 Reviewed-by: Volker Hilsheimer <[email protected]> ================================= cherry-picked from 2c96f51 QDockAreaLayout: implement widget based add() and remove() The item_list of a QDockAreaLayoutInfo has abstraction methods for reading the item list. Adding to and removing from the item list is done directly, by using the QList api. Implement an abstraction, that takes a QWidget *. The argument may either be a QDockWidgetGroupWindow or a QDockWidget. Task-number: QTBUG-118578 Task-number: QTBUG-118579 Pick-to: 6.6 6.5 Change-Id: Ib2ccd7557a21a43b68f184fe4575018f2a97004b Reviewed-by: David Faure <[email protected]> ================================= cherry-picked from 1ab91b7 QDockWidget: call raise() when a dock widget starts to hover When dock widget (1) starts to hover over another floating dock widget (2), the latter animates a rubber band, to indicate to the user that it is ready to accept a drop. The creation of a QRubberBand moves (2) one position up in the Z order. The consequence is a visual glitch: While - the mouse cursor dragging (1) is still outside (2) and - the visual rectangle of (1) starts overlapping (2) (1) hides behind (2). As soon as the mouse cursor enters (2), (1) suddenly comes on top and (2) hides behind (1). => raise() 1 as soon as it starts hovering. That brings it on top of the Z order, which is expected behavior. Pick-to: 6.6 6.5 Change-Id: I1140fc6ff109c7a713e7e2617072698467375585 Reviewed-by: Richard Moe Gustavsen <[email protected]> Reviewed-by: David Faure <[email protected]> ================================= cherry-picked from 4c60a11 QDockWidget: Always show dock widgets with the main window QMainWindow::show() also showed its dock widget children. When a main window with dock widget children consumed a show event for another reason, hidden dock widget children remained hidden. If a dock widget application went to the background, e.g. because it was hidden behind another application gaining focus, a klick on the dock widget application's app icon would not show its dock widget children. Unless the dock widget application provides shows them explicitly, they can never been shown again by the user. => show all dock widget and group window children, when QMainWindow consumes a show event. Pick-to: 6.6 6.5 Change-Id: I7e8b59f021ec4ec5679d0d08d0eeda1e3225a385 Reviewed-by: David Faure <[email protected]> ================================= cherry-picked from 0e435b7 QMainWindowLayout: remove redundant #ifdef'ry Remove #if QT_CONFIG(dockwidget) nested within each other. Pick-to: 6.6 6.5 Change-Id: I6c662909676ffada3ac52e41a9c2d8b9fd491689 Reviewed-by: David Faure <[email protected]>
- Loading branch information