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>
This commit is contained in:
Morten Johan Sørvig 2020-05-29 09:18:09 +02:00 committed by Tor Arne Vestbø
parent 210128cc0e
commit b8f5ed0d5a
2 changed files with 84 additions and 19 deletions

View File

@ -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

View File

@ -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)