// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHIGHDPISCALING_P_H #define QHIGHDPISCALING_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcHighDpi); class QScreen; class QPlatformScreen; typedef QPair QDpi; #ifndef QT_NO_HIGHDPISCALING class Q_GUI_EXPORT QHighDpiScaling { Q_GADGET public: enum class DpiAdjustmentPolicy { Unset, Enabled, Disabled, UpOnly }; Q_ENUM(DpiAdjustmentPolicy) QHighDpiScaling() = delete; ~QHighDpiScaling() = delete; QHighDpiScaling(const QHighDpiScaling &) = delete; QHighDpiScaling &operator=(const QHighDpiScaling &) = delete; QHighDpiScaling(QHighDpiScaling &&) = delete; QHighDpiScaling &operator=(QHighDpiScaling &&) = delete; static void initHighDpiScaling(); static void updateHighDpiScaling(); static void setGlobalFactor(qreal factor); static void setScreenFactor(QScreen *screen, qreal factor); 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, 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 static qreal factor(C *context) { return scaleAndOrigin(context).factor; } static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen); static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen); static QDpi logicalDpi(const QScreen *screen); static qreal roundScaleFactor(qreal rawFactor); private: struct ScreenFactor { ScreenFactor(QString name, qreal factor) :name(name), factor(factor) { } QString name; qreal factor; }; static qreal rawScaleFactor(const QPlatformScreen *screen); static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor); static qreal screenSubfactor(const QPlatformScreen *screen); static QScreen *screenForPosition(Point position, QScreen *guess); static QVector parseScreenScaleFactorsSpec(const QStringView &screenScaleFactors); static qreal m_factor; static bool m_active; static bool m_usePlatformPluginDpi; static bool m_platformPluginDpiScalingActive; static bool m_globalScalingActive; static bool m_screenFactorSet; static bool m_usePhysicalDpi; static QVector m_screenFactors; static DpiAdjustmentPolicy m_dpiAdjustmentPolicy; static QHash m_namedScreenScaleFactors; #ifndef QT_NO_DEBUG_STREAM friend Q_GUI_EXPORT QDebug operator<<(QDebug, const ScreenFactor &); #endif }; namespace QHighDpi { inline qreal scale(qreal value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0)) { return value * scaleFactor; } inline QSize scale(const QSize &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0)) { return value * scaleFactor; } inline QSizeF scale(const QSizeF &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0)) { return value * scaleFactor; } inline QVector2D scale(const QVector2D &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0)) { return value * float(scaleFactor); } inline QPointF scale(const QPointF &pos, qreal scaleFactor, QPointF origin = QPointF(0, 0)) { return (pos - origin) * scaleFactor + origin; } inline QPoint scale(const QPoint &pos, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { return (pos - origin) * scaleFactor + origin; } inline QRect scale(const QRect &rect, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { return QRect(scale(rect.topLeft(), scaleFactor, origin), scale(rect.size(), scaleFactor)); } inline QRectF scale(const QRectF &rect, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { return QRectF(scale(rect.topLeft(), scaleFactor, origin), scale(rect.size(), scaleFactor)); } inline QMargins scale(const QMargins &margins, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { Q_UNUSED(origin); return QMargins(qRound(qreal(margins.left()) * scaleFactor), qRound(qreal(margins.top()) * scaleFactor), qRound(qreal(margins.right()) * scaleFactor), qRound(qreal(margins.bottom()) * scaleFactor)); } template QList scale(const QList &list, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { if (!QHighDpiScaling::isActive()) return list; QList scaled; scaled.reserve(list.size()); for (const T &item : list) scaled.append(scale(item, scaleFactor, origin)); return scaled; } inline QRegion scale(const QRegion ®ion, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { if (!QHighDpiScaling::isActive()) return region; QRegion scaled = region.translated(-origin); scaled = QTransform::fromScale(scaleFactor, scaleFactor).map(scaled); return scaled.translated(origin); } template 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 T fromNativePixels(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context); return scale(value, qreal(1) / so.factor, so.origin); } template T toNativePixels(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context); return scale(value, so.factor, so.origin); } template T fromNativeLocalPosition(const T &value, const C *context) { return scale(value, qreal(1) / QHighDpiScaling::factor(context)); } template T toNativeLocalPosition(const T &value, const C *context) { return scale(value, QHighDpiScaling::factor(context)); } template T fromNativeGlobalPosition(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context, position(value, QHighDpiScaling::Point::Native)); return scale(value, qreal(1) / so.factor, so.origin); } template T toNativeGlobalPosition(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context, position(value, QHighDpiScaling::Point::DeviceIndependent)); return scale(value, so.factor, so.origin); } template T fromNativeWindowGeometry(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context); QPoint effectiveOrigin = (context && context->isTopLevel()) ? so.origin : QPoint(0,0); return scale(value, qreal(1) / so.factor, effectiveOrigin); } template T toNativeWindowGeometry(const T &value, const C *context) { QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context); QPoint effectiveOrigin = (context && context->isTopLevel()) ? so.origin : QPoint(0,0); return scale(value, so.factor, effectiveOrigin); } template inline T fromNative(const T &value, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { return scale(value, qreal(1) / scaleFactor, origin); } template inline T toNative(const T &value, qreal scaleFactor, QPoint origin = QPoint(0, 0)) { return scale(value, scaleFactor, origin); } inline QRect fromNative(const QRect &rect, const QScreen *screen, const QPoint &screenOrigin) { return scale(rect, qreal(1) / QHighDpiScaling::factor(screen), screenOrigin); } inline QRect fromNativeScreenGeometry(const QRect &nativeScreenGeometry, const QScreen *screen) { return QRect(nativeScreenGeometry.topLeft(), scale(nativeScreenGeometry.size(), qreal(1) / QHighDpiScaling::factor(screen))); } inline QRegion fromNativeLocalRegion(const QRegion &pixelRegion, const QWindow *window) { return scale(pixelRegion, qreal(1) / QHighDpiScaling::factor(window)); } // When mapping expose events to Qt rects: round top/left towards the origin and // bottom/right away from the origin, making sure that we cover the whole window. inline QRegion fromNativeLocalExposedRegion(const QRegion &pixelRegion, const QWindow *window) { if (!QHighDpiScaling::isActive()) return pixelRegion; const qreal scaleFactor = QHighDpiScaling::factor(window); QRegion pointRegion; for (const QRectF rect: pixelRegion) pointRegion += QRectF(rect.topLeft() / scaleFactor, rect.size() / scaleFactor).toAlignedRect(); return pointRegion; } inline QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *window) { return scale(pointRegion, QHighDpiScaling::factor(window)); } } // namespace QHighDpi #else // QT_NO_HIGHDPISCALING class Q_GUI_EXPORT QHighDpiScaling { public: static inline void initHighDpiScaling() {} static inline void updateHighDpiScaling() {} static inline void setGlobalFactor(qreal) {} static inline void setScreenFactor(QScreen *, qreal) {} 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 inline bool isActive() { return false; } static inline qreal factor(const QWindow *) { return 1.0; } static inline qreal factor(const QScreen *) { return 1.0; } static inline qreal factor(const QPlatformScreen *) { return 1.0; } static inline QPoint origin(const QScreen *) { return QPoint(); } static inline QPoint origin(const QPlatformScreen *) { return QPoint(); } static inline QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *) { return pos; } static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; } static inline QPointF mapPositionToGlobal(const QPointF &pos, const QPoint &, const QWindow *) { return pos; } static inline QPointF mapPositionFromGlobal(const QPointF &pos, const QPoint &, const QWindow *) { return pos; } static inline QDpi logicalDpi(const QScreen *) { return QDpi(-1,-1); } }; namespace QHighDpi { template inline T scale(const T &value, ...) { return value; } template inline T toNative(const T &value, ...) { return value; } template inline T fromNative(const T &value, ...) { return value; } template inline T fromNativeLocalPosition(const T &value, ...) { return value; } template inline T toNativeLocalPosition(const T &value, ...) { return value; } template inline T fromNativeGlobalPosition(const T &value, const C *) { return value; } template inline T toNativeGlobalPosition(const T &value, const C *) { return value; } template inline T fromNativeWindowGeometry(const T &value, const C *) { return value; } template inline T toNativeWindowGeometry(const T &value, const C *) { return value; } template inline T fromNativeLocalRegion(const T &value, ...) { return value; } template inline T fromNativeLocalExposedRegion(const T &value, ...) { return value; } template inline T toNativeLocalRegion(const T &value, ...) { return value; } template inline T fromNativeScreenGeometry(const T &value, ...) { return value; } template inline T toNativePixels(const T &value, const U*) {return value;} template inline T fromNativePixels(const T &value, const U*) {return value;} } #endif // QT_NO_HIGHDPISCALING QT_END_NAMESPACE #endif // QHIGHDPISCALING_P_H