summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2020-05-29 09:18:09 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-10-20 05:26:08 +0000
commitb8f5ed0d5aa52c93e092fa4df7ca2f44df8f03e0 (patch)
tree082a0bfcab8aa1a5c0575f3a6d65f625c17b6bd2
parent210128cc0e582b01a8dbd4dd9f71a19406d8c89d (diff)
QHighDpi: Add screenForPosition()
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>
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp61
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h42
2 files changed, 84 insertions, 19 deletions
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 53ecf8e0ad..6a47372b0b 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -649,34 +649,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);
}
#else
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 86f74b26a9..92a9a6929d 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)