File 3003-QHighDpi-Add-screenForPosition.patch of Package libqt5-qtbase

From 8028ae23854d04b0d9161b78dea458a2b3afae1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io>
Date: Fri, 29 May 2020 09:18:09 +0200
Subject: [PATCH 3003/3009] QHighDpi: Add screenForPosition()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Implement support for using the screen at a given position
when determining the scale factor and origin.

Add QHighDpiScaling::screenForPosition(), which searches
for a screen at the specified device independent or native
coordinates. The function returns the QScreen or nullptr
if no screen was found.

Add QHighDpiScaling::Point, used for representing
an invalid, device independent, or native point.

Change-Id: I58e4e3eebb8cdd5171e59f97833a00e7f8d9ecd6
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
(cherry-picked from commit b8f5ed0d5aa52c93e092fa4df7ca2f44df8f03e0)
---
 src/gui/kernel/qhighdpiscaling_p.h | 42 +++++++++++++++-----
 src/gui/kernel/qhighdpiscaling.cpp | 61 +++++++++++++++++++++++++-----
 2 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index a9e756bcd8..3208415298 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -96,18 +96,29 @@ public:
 
     static bool isActive() { return m_active; }
 
+    struct Point {
+        enum Kind {
+            Invalid,
+            DeviceIndependent,
+            Native
+        };
+        Kind kind;
+        QPoint point;
+    };
+
     struct ScaleAndOrigin
     {
         qreal factor;
         QPoint origin;
     };
-    static ScaleAndOrigin scaleAndOrigin(const QPlatformScreen *platformScreen, QPoint *nativePosition = nullptr);
-    static ScaleAndOrigin scaleAndOrigin(const QScreen *screen, QPoint *nativePosition = nullptr);
-    static ScaleAndOrigin scaleAndOrigin(const QWindow *platformScreen, QPoint *nativePosition = nullptr);
+
+    static ScaleAndOrigin scaleAndOrigin(const QPlatformScreen *platformScreen, Point position = Point{ Point::Invalid, QPoint() });
+    static ScaleAndOrigin scaleAndOrigin(const QScreen *screen, Point position = Point{ Point::Invalid, QPoint() });
+    static ScaleAndOrigin scaleAndOrigin(const QWindow *platformScreen, Point position = Point{ Point::Invalid, QPoint() });
 
     template<typename C>
-    static qreal factor(C *context, QPoint *nativePosition = nullptr) {
-        return scaleAndOrigin(context, nativePosition).factor;
+    static qreal factor(C *context) {
+        return scaleAndOrigin(context).factor;
     }
 
     static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
@@ -121,6 +132,7 @@ private:
     static qreal roundScaleFactor(qreal rawFactor);
     static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor);
     static qreal screenSubfactor(const QPlatformScreen *screen);
+    static QScreen *screenForPosition(Point position, QScreen *guess);
 
     static qreal m_factor;
     static bool m_active;
@@ -209,11 +221,21 @@ inline QRegion scale(const QRegion &region, qreal scaleFactor, QPoint origin = Q
 }
 
 template <typename T>
-inline QPoint position(T) { return QPoint(); }
-inline QPoint position(QPoint point) { return point; }
-inline QPoint position(QPointF point) { return point.toPoint(); }
-inline QPoint position(QRect rect) { return rect.center(); }
-inline QPoint position(QRectF rect) { return rect.center().toPoint(); }
+inline QHighDpiScaling::Point position(T, QHighDpiScaling::Point::Kind) {
+    return QHighDpiScaling::Point{ QHighDpiScaling::Point::Invalid, QPoint() };
+}
+inline QHighDpiScaling::Point position(QPoint point, QHighDpiScaling::Point::Kind kind) {
+    return QHighDpiScaling::Point{ kind, point };
+}
+inline QHighDpiScaling::Point position(QPointF point, QHighDpiScaling::Point::Kind kind) {
+    return QHighDpiScaling::Point{ kind, point.toPoint() };
+}
+inline QHighDpiScaling::Point position(QRect rect, QHighDpiScaling::Point::Kind kind) {
+    return QHighDpiScaling::Point{ kind, rect.topLeft() };
+}
+inline QHighDpiScaling::Point position(QRectF rect, QHighDpiScaling::Point::Kind kind) {
+    return QHighDpiScaling::Point{ kind, rect.topLeft().toPoint() };
+}
 
 template <typename T, typename C>
 T fromNativePixels(const T &value, const C *context)
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 9bbf2773a9..d34b2a5dc6 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -694,34 +694,77 @@ QDpi QHighDpiScaling::logicalDpi(const QScreen *screen)
     return effectiveLogicalDpi(screen->handle(), scaleFactor, roundedScaleFactor);
 }
 
-QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *platformScreen, QPoint *nativePosition)
+// Returns the screen containing \a position, using \a guess as a starting point
+// for the search. \a guess might be nullptr. Returns nullptr if \a position is outside
+// of all screens.
+QScreen *QHighDpiScaling::screenForPosition(QHighDpiScaling::Point position, QScreen *guess)
 {
+    if (position.kind == QHighDpiScaling::Point::Invalid)
+        return nullptr;
+
+    auto getPlatformScreenGuess = [](QScreen *maybeScreen) -> QPlatformScreen * {
+        if (maybeScreen)
+            return maybeScreen->handle();
+        if (QScreen *primary = QGuiApplication::primaryScreen())
+            return primary->handle();
+        return nullptr;
+    };
+
+    QPlatformScreen *platformGuess = getPlatformScreenGuess(guess);
+    if (!platformGuess)
+        return nullptr;
+
+    auto onScreen = [](QHighDpiScaling::Point position, const QPlatformScreen *platformScreen) -> bool {
+        return position.kind == Point::Native
+          ?  platformScreen->geometry().contains(position.point)
+          :  platformScreen->screen()->geometry().contains(position.point);
+    };
+
+    // is the guessed screen correct?
+    if (onScreen(position, platformGuess))
+        return platformGuess->screen();
+
+    // search sibling screens
+    const auto screens = platformGuess->virtualSiblings();
+    for (const QPlatformScreen *screen : screens) {
+        if (onScreen(position, screen))
+            return screen->screen();
+    }
+
+    return nullptr;
+}
+
+QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *platformScreen, QHighDpiScaling::Point position)
+{
+    Q_UNUSED(position)
     if (!m_active)
         return { qreal(1), QPoint() };
     if (!platformScreen)
         return { m_factor, QPoint() }; // the global factor
-    const QPlatformScreen *actualScreen = nativePosition ?
-        platformScreen->screenForPosition(*nativePosition) : platformScreen;
-    return { m_factor * screenSubfactor(actualScreen), actualScreen->geometry().topLeft() };
+    return { m_factor * screenSubfactor(platformScreen), platformScreen->geometry().topLeft() };
 }
 
-QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QScreen *screen, QPoint *nativePosition)
+QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QScreen *screen, QHighDpiScaling::Point position)
 {
+    Q_UNUSED(position)
     if (!m_active)
         return { qreal(1), QPoint() };
     if (!screen)
         return { m_factor, QPoint() }; // the global factor
-    return scaleAndOrigin(screen->handle(), nativePosition);
+    return scaleAndOrigin(screen->handle(), position);
 }
 
-QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *window, QPoint *nativePosition)
+QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *window, QHighDpiScaling::Point position)
 {
     if (!m_active)
         return { qreal(1), QPoint() };
 
+    // Determine correct screen; use the screen which contains the given
+    // position if a valid position is passed.
     QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
-    const bool searchScreen = !window || window->isTopLevel();
-    return scaleAndOrigin(screen, searchScreen ? nativePosition : nullptr);
+    QScreen *overrideScreen = QHighDpiScaling::screenForPosition(position, screen);
+    QScreen *targetScreen = overrideScreen ? overrideScreen : screen;
+    return scaleAndOrigin(targetScreen, position);
 }
 
 #endif //QT_NO_HIGHDPISCALING
-- 
2.29.2

openSUSE Build Service is sponsored by