summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets/qtoolbar.cpp
diff options
context:
space:
mode:
authorDavid Redondo <qt@david-redondo.de>2023-03-10 16:44:20 +0100
committerDavid Redondo <qt@david-redondo.de>2023-06-02 19:53:34 +0200
commit581c4bcb62a9d3cbb4c33df3f0f7a0a965225e74 (patch)
tree22da571a5a8c0d5fdbfd14a17654cf3a8b28d5ba /src/widgets/widgets/qtoolbar.cpp
parent1eb4d17cb48a70501ebf51fc8732e14fec2cc12f (diff)
Use platform drags for drags of docks and toolbars on wayland
On Wayland we can't know where windows are in relation to each other so the whole mechanism was broken, toolbars were unmovable once undocked and could be blindly redocked. Dockwidgets had native toolbars to move them around but could not be redocked. This introduces an alternative code path that uses a platform drag with a special mimetype that enables the platform to issue a combined drag and window move using the relevant protocol. Should the protocol not be available this doesn't make things actively worse as it will be similar broken as before. Fixes: QTBUG-87332 Change-Id: I3b8bdc0b1bc22569a64cb8bf7ca7d37d223936a6 Reviewed-by: David Edmundson <davidedmundson@kde.org> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/widgets/widgets/qtoolbar.cpp')
-rw-r--r--src/widgets/widgets/qtoolbar.cpp37
1 files changed, 34 insertions, 3 deletions
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index b5950fdf23..54fd3ac525 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -7,6 +7,9 @@
#if QT_CONFIG(combobox)
#include <qcombobox.h>
#endif
+#if QT_CONFIG(draganddrop)
+#include <qdrag.h>
+#endif
#include <qevent.h>
#include <qlayout.h>
#include <qmainwindow.h>
@@ -14,6 +17,7 @@
#if QT_CONFIG(menubar)
#include <qmenubar.h>
#endif
+#include <qmimedata.h>
#if QT_CONFIG(rubberband)
#include <qrubberband.h>
#endif
@@ -40,6 +44,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// qmainwindow.cpp
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
@@ -105,7 +111,9 @@ void QToolBarPrivate::updateWindowFlags(bool floating, bool unplug)
flags |= Qt::FramelessWindowHint;
- if (unplug)
+ // If we are performing a platform drag the flag is not needed and we want to avoid recreating
+ // the platform window when it would be removed later
+ if (unplug && !QMainWindowLayout::needsPlatformDrag())
flags |= Qt::X11BypassWindowManagerHint;
q->setWindowFlags(flags);
@@ -117,8 +125,6 @@ void QToolBarPrivate::setWindowState(bool floating, bool unplug, const QRect &re
bool visible = !q->isHidden();
bool wasFloating = q->isFloating(); // ...is also currently using popup menus
- q->hide();
-
updateWindowFlags(floating, unplug);
if (floating != wasFloating)
@@ -172,12 +178,27 @@ void QToolBarPrivate::startDrag(bool moving)
QMainWindowLayout *layout = qt_mainwindow_layout(win);
Q_ASSERT(layout != nullptr);
+ const bool wasFloating = q->isFloating();
+
if (!moving) {
state->widgetItem = layout->unplug(q);
Q_ASSERT(state->widgetItem != nullptr);
}
state->dragging = !moving;
state->moving = moving;
+
+#if QT_CONFIG(draganddrop)
+ if (QMainWindowLayout::needsPlatformDrag() && state->dragging) {
+ auto result = layout->performPlatformWidgetDrag(state->widgetItem, state->pressPos);
+ if (result == Qt::IgnoreAction && !wasFloating) {
+ layout->revert(state->widgetItem);
+ delete state;
+ state = nullptr;
+ } else {
+ endDrag();
+ }
+ }
+#endif
}
void QToolBarPrivate::endDrag()
@@ -243,6 +264,11 @@ bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
bool QToolBarPrivate::mouseReleaseEvent(QMouseEvent*)
{
+ // if we are peforming a platform drag ignore the release here and end the drag when the actual
+ // drag ends.
+ if (QMainWindowLayout::needsPlatformDrag())
+ return false;
+
if (state != nullptr) {
endDrag();
return true;
@@ -293,6 +319,11 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
q->grabMouse();
}
+ if (!state) {
+ q->releaseMouse();
+ return true;
+ }
+
if (state->dragging) {
QPoint pos = event->globalPosition().toPoint();
// if we are right-to-left, we move so as to keep the right edge the same distance