summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorbjørn Lund Martsum <tmartsum@gmail.com>2022-06-14 08:52:47 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-06-29 22:12:16 +0000
commit3c348cbfa0f674a574c56b0171e1bc0e474c2282 (patch)
tree36c77f8aff65679c4a1b7b73ac9e896ceddb1c38
parent681397fb5bc3f885d97dc738b12b2c4a8b656208 (diff)
Fix QDockWidget move between screens with different dpr
When partly moved back and forth between screens with different dprs (device pixel ratios) unexpected jumps and size changes could occur. (See the linked issue for details) This patch maps global coordinates to native ones and vice versa (in QDockWidgetPrivate::mouseMoveEvent()), so that the calculated position is the right coordinate on the right screen. Fixes: QTBUG-104205 Change-Id: I0e59792a946e0444fed2e2b857f2f8b140afc9b7 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit 54f328f0e8205480749a6d8d2ebe0e58cb1cdb67) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/widgets/widgets/qdockwidget.cpp29
-rw-r--r--src/widgets/widgets/qdockwidget_p.h2
2 files changed, 30 insertions, 1 deletions
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 7da1023f04..14022aa830 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -20,6 +20,7 @@
#include <private/qstylesheetstyle_p.h>
#include <qpa/qplatformtheme.h>
+#include <private/qhighdpiscaling_p.h>
#include "qdockwidget_p.h"
#include "qmainwindowlayout_p.h"
@@ -752,6 +753,8 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
state = new QDockWidgetPrivate::DragState;
state->pressPos = pos;
+ state->globalPressPos = q->mapToGlobal(pos);
+ state->widgetInitialPos = q->pos();
state->dragging = false;
state->widgetItem = nullptr;
state->ownWidgetItem = false;
@@ -981,7 +984,31 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
if (state && state->dragging && !state->nca) {
QMargins windowMargins = q->window()->windowHandle()->frameMargins();
QPoint windowMarginOffset = QPoint(windowMargins.left(), windowMargins.top());
- QPoint pos = event->globalPosition().toPoint() - state->pressPos - windowMarginOffset;
+
+ // TODO maybe use QScreen API (if/when available) to simplify the below code.
+ const QScreen *orgWdgScreen = QGuiApplication::screenAt(state->widgetInitialPos);
+ const QScreen *screenFrom = QGuiApplication::screenAt(state->globalPressPos);
+ const QScreen *screenTo = QGuiApplication::screenAt(event->globalPosition().toPoint());
+ const QScreen *wdgScreen = q->screen();
+
+ QPoint pos;
+ if (Q_LIKELY(screenFrom && screenTo && wdgScreen && orgWdgScreen)) {
+ const QPoint nativeWdgOrgPos = QHighDpiScaling::mapPositionToNative(
+ state->widgetInitialPos, orgWdgScreen->handle());
+ const QPoint nativeTo = QHighDpiScaling::mapPositionToNative(
+ event->globalPosition().toPoint(), screenTo->handle());
+ const QPoint nativeFrom = QHighDpiScaling::mapPositionToNative(state->globalPressPos,
+ screenFrom->handle());
+
+ // Calculate new nativePos based on startPos + mouse delta move.
+ const QPoint nativeNewPos = nativeWdgOrgPos + (nativeTo - nativeFrom);
+
+ pos = QHighDpiScaling::mapPositionFromNative(nativeNewPos, wdgScreen->handle())
+ - windowMarginOffset;
+ } else {
+ // Fallback in the unlikely case that source and target screens could not be established
+ pos = event->globalPosition().toPoint() - state->pressPos - windowMarginOffset;
+ }
QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
if (floatingTab && !q->isFloating())
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index 8e9f80d412..326c55cc78 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -41,6 +41,8 @@ class QDockWidgetPrivate : public QWidgetPrivate
struct DragState {
QPoint pressPos;
+ QPoint globalPressPos;
+ QPoint widgetInitialPos;
bool dragging;
QLayoutItem *widgetItem;
bool ownWidgetItem;