QDockWidget: fix positioning after unplugging from floating tab
A floating tab is a QDockWidgetGroupWindow, containing a QMainWindowTabBar, with each tab representing a dock widget. Users can unplug dock widgets from the floating tab, by dragging the respective tab of the tab bar. Such a drag triggers an internal move of the tab at first. When a tab is dragged outside the tab bar, the dock widget is unplugged and becomes floating. It is supposed to be placed with its title bar under the mouse cursor, so the drag can seemlessly continue and move the newly unplugged dock widget. To position the dock widget's title bar under the mouse cursor, QTabBarPrivate::dragStartPosition was deducted from the mouse move event's global position. QTabBarPrivate::dragStartPosition holds the the position of the tab at the time when the drag had started. It is used, to restore its position, when a move is aborted. Using this point to calculate an unplug position is wrong. It results in random positions, away from the mouse cursor, especially if the tab has been dragged over a longer distance. Implement a helper function, that positions the dockwidget with its title bar under a given position. Use QDockWdget::titleBarWidget()->rect.center(), if it has a title bar widget. Otherwise, use QApplication::startDragDistance() as an offset on the short side and the middle of the long side as coordinates. The behavior can't be autotested, because - mouse move emulation doesn't follow a line. - drag and drop can't be tested on Windows platforms The dockwidgets manual test (former dockwidgets example) can be used for verification. Fixes: QTBUG-126084 Pick-to: 6.7 6.5 6.2 Change-Id: I276cb6ade3944921d747bf5e73b7b6fe402d10c5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 37861df8e5a41f0f654e15776c631da95ba26c03) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
9f1b4d4e09
commit
f54e50e513
@ -1954,6 +1954,30 @@ QDockWidget *QMainWindowTabBar::dockAt(int index) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Move \a dockWidget to its ideal unplug position.
|
||||
\list
|
||||
\li If \a dockWidget has a title bar widget, place its center under the mouse cursor.
|
||||
\li Otherwise place it in the middle of the title bar's long side, with a
|
||||
QApplication::startDragDistance() offset on the short side.
|
||||
\endlist
|
||||
*/
|
||||
static void moveToUnplugPosition(QPoint mouse, QDockWidget *dockWidget)
|
||||
{
|
||||
Q_ASSERT(dockWidget);
|
||||
|
||||
if (auto *tbWidget = dockWidget->titleBarWidget()) {
|
||||
dockWidget->move(mouse - tbWidget->rect().center());
|
||||
return;
|
||||
}
|
||||
|
||||
const bool vertical = dockWidget->features().testFlag(QDockWidget::DockWidgetVerticalTitleBar);
|
||||
const int deltaX = vertical ? QApplication::startDragDistance() : dockWidget->width() / 2;
|
||||
const int deltaY = vertical ? dockWidget->height() / 2 : QApplication::startDragDistance();
|
||||
dockWidget->move(mouse - QPoint(deltaX, deltaY));
|
||||
}
|
||||
|
||||
void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
// The QTabBar handles the moving (reordering) of tabs.
|
||||
@ -1991,9 +2015,8 @@ void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
|
||||
if (draggingDock) {
|
||||
QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
|
||||
if (dockPriv->state && dockPriv->state->dragging) {
|
||||
QPoint pos = e->globalPosition().toPoint() - dockPriv->state->pressPos;
|
||||
draggingDock->move(pos);
|
||||
// move will call QMainWindowLayout::hover
|
||||
moveToUnplugPosition(e->globalPosition().toPoint(), draggingDock);
|
||||
}
|
||||
}
|
||||
QTabBar::mouseMoveEvent(e);
|
||||
|
Loading…
x
Reference in New Issue
Block a user