summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2020-05-20 14:27:16 +0200
committerMorten Johan Sørvig <morten.sorvig@qt.io>2020-10-20 07:26:38 +0200
commit0ab89881c5aecc31e44fd83b1a63bd4de52ebe4a (patch)
tree7695c6a3f3eda3b48bc8dc0a55c184b64cbd7515 /src/gui/kernel
parente8fabb29462e6ee268bde5267e3d7bca23addbb2 (diff)
high-dpi: Re-implement mapToGlobal and mapFromGlobal
(This code is required to handle corner cases such as a QWindow covering multiple screens, where the normal code path does not give correct results.) Move the map[to|from]Global implementation from qhighdpiscaling.cpp, and implement it in terms of [to|from]NativeGlobalPosition. These functions implement the required screenAt()-type searching. The implementation strategy for both mapping functions is to first map to the native coordinate system, perform the globalPos addition or subtraction, and then map the result back to device independent coordinates. Task-number: QTBUG-81695 Change-Id: I44e9e68651634650964e839b1e564b50f434553f Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp40
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h2
-rw-r--r--src/gui/kernel/qwindow.cpp28
3 files changed, 22 insertions, 48 deletions
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 6a47372b0b..9d166cb254 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -558,46 +558,6 @@ QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatform
return (pos - topLeft) / scaleFactor + topLeft;
}
-QPointF QHighDpiScaling::mapPositionToGlobal(const QPointF &pos, const QPoint &windowGlobalPosition, const QWindow *window)
-{
- QPointF globalPosCandidate = pos + QPointF(windowGlobalPosition);
- if (QGuiApplicationPrivate::screen_list.size() <= 1)
- return globalPosCandidate;
-
- // The global position may be outside device independent screen geometry
- // in cases where a window spans screens. Detect this case and map via
- // native coordinates to the correct screen.
- auto currentScreen = window->screen();
- if (currentScreen && !currentScreen->geometry().contains(globalPosCandidate.toPoint())) {
- QPointF nativeGlobalPos = QHighDpi::toNativePixels(globalPosCandidate, currentScreen);
- if (auto actualPlatformScreen = currentScreen->handle()->screenForPosition(nativeGlobalPos.toPoint()))
- return QHighDpi::fromNativePixels(nativeGlobalPos, actualPlatformScreen->screen());
- }
-
- return globalPosCandidate;
-}
-
-QPointF QHighDpiScaling::mapPositionFromGlobal(const QPointF &pos, const QPoint &windowGlobalPosition, const QWindow *window)
-{
- QPointF windowPosCandidate = pos - QPointF(windowGlobalPosition);
- if (QGuiApplicationPrivate::screen_list.size() <= 1 || window->handle() == nullptr)
- return windowPosCandidate;
-
- // Device independent global (screen) space may discontiguous when high-dpi scaling
- // is active. This means that the normal subtracting of the window global position from the
- // position-to-be-mapped may not work in cases where a window spans multiple screens.
- // Map both positions to native global space (using the correct screens), subtract there,
- // and then map the difference back using the scale factor for the window.
- QScreen *posScreen = QGuiApplication::screenAt(pos.toPoint());
- if (posScreen && posScreen != window->screen()) {
- QPointF nativePos = QHighDpi::toNativePixels(pos, posScreen);
- QPointF windowNativePos = window->handle()->geometry().topLeft();
- return QHighDpi::fromNativeLocalPosition(nativePos - windowNativePos, window);
- }
-
- return windowPosCandidate;
-}
-
qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen)
{
auto factor = qreal(1.0);
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index f7cf4792f2..cf21a90f70 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -123,8 +123,6 @@ public:
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
- static QPointF mapPositionToGlobal(const QPointF &pos, const QPoint &windowGlobalPosition, const QWindow *window);
- static QPointF mapPositionFromGlobal(const QPointF &pos, const QPoint &windowGlobalPosition, const QWindow *window);
static QDpi logicalDpi(const QScreen *screen);
private:
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 131f55908b..b0c07cb632 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -2684,10 +2684,20 @@ QPointF QWindow::mapToGlobal(const QPointF &pos) const
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
- if (QHighDpiScaling::isActive())
- return QHighDpiScaling::mapPositionToGlobal(pos, d->globalPosition(), this);
+ if (!QHighDpiScaling::isActive())
+ return pos + d->globalPosition();
- return pos + QPointF(d->globalPosition());
+ // The normal pos + windowGlobalPos calculation may give a point which is outside
+ // screen geometry for windows which span multiple screens, due to the way QHighDpiScaling
+ // creates gaps between screens in the the device indendent cooordinate system.
+ //
+ // Map the position (and the window's global position) to native coordinates, perform
+ // the addition, and then map back to device independent coordinates.
+ QPointF nativeLocalPos = QHighDpi::toNativeLocalPosition(pos, this);
+ QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ QPointF nativeGlobalPos = nativeLocalPos + nativeWindowGlobalPos;
+ QPointF deviceIndependentGlobalPos = QHighDpi::fromNativeGlobalPosition(nativeGlobalPos, this);
+ return deviceIndependentGlobalPos;
}
/*!
@@ -2716,10 +2726,16 @@ QPointF QWindow::mapFromGlobal(const QPointF &pos) const
return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
- if (QHighDpiScaling::isActive())
- return QHighDpiScaling::mapPositionFromGlobal(pos, d->globalPosition(), this);
+ if (!QHighDpiScaling::isActive())
+ return pos - d->globalPosition();
- return pos - QPointF(d->globalPosition());
+ // Calculate local position in the native coordinate system. (See comment for the
+ // correspinding mapToGlobal() code above).
+ QPointF nativeGlobalPos = QHighDpi::toNativeGlobalPosition(pos, this);
+ QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ QPointF nativeLocalPos = nativeGlobalPos - nativeWindowGlobalPos;
+ QPointF deviceIndependentLocalPos = QHighDpi::fromNativeLocalPosition(nativeLocalPos, this);
+ return deviceIndependentLocalPos;
}
/*!