1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QHIGHDPISCALING_P_H
41#define QHIGHDPISCALING_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtGui/private/qtguiglobal_p.h>
55#include <QtCore/qmargins.h>
56#include <QtCore/qmath.h>
57#include <QtCore/qrect.h>
58#include <QtCore/qvector.h>
59#include <QtCore/qloggingcategory.h>
60#include <QtGui/qregion.h>
61#include <QtGui/qscreen.h>
62#include <QtGui/qvector2d.h>
63#include <QtGui/qwindow.h>
64
65QT_BEGIN_NAMESPACE
66
67Q_DECLARE_LOGGING_CATEGORY(lcScaling);
68
69class QScreen;
70class QPlatformScreen;
71typedef QPair<qreal, qreal> QDpi;
72
73#ifndef QT_NO_HIGHDPISCALING
74class Q_GUI_EXPORT QHighDpiScaling {
75 Q_GADGET
76public:
77 enum class DpiAdjustmentPolicy {
78 Unset,
79 Enabled,
80 Disabled,
81 UpOnly
82 };
83 Q_ENUM(DpiAdjustmentPolicy)
84
85 QHighDpiScaling() = delete;
86 ~QHighDpiScaling() = delete;
87 QHighDpiScaling(const QHighDpiScaling &) = delete;
88 QHighDpiScaling &operator=(const QHighDpiScaling &) = delete;
89 QHighDpiScaling(QHighDpiScaling &&) = delete;
90 QHighDpiScaling &operator=(QHighDpiScaling &&) = delete;
91
92 static void initHighDpiScaling();
93 static void updateHighDpiScaling();
94 static void setGlobalFactor(qreal factor);
95 static void setScreenFactor(QScreen *screen, qreal factor);
96
97 static bool isActive() { return m_active; }
98
99 struct ScaleAndOrigin
100 {
101 qreal factor;
102 QPoint origin;
103 };
104 static ScaleAndOrigin scaleAndOrigin(const QPlatformScreen *platformScreen, QPoint *nativePosition = nullptr);
105 static ScaleAndOrigin scaleAndOrigin(const QScreen *screen, QPoint *nativePosition = nullptr);
106 static ScaleAndOrigin scaleAndOrigin(const QWindow *platformScreen, QPoint *nativePosition = nullptr);
107
108 template<typename C>
109 static qreal factor(C *context, QPoint *nativePosition = nullptr) {
110 return scaleAndOrigin(context, nativePosition).factor;
111 }
112
113 static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
114 static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
115 static QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
116 static QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
117 static QDpi logicalDpi(const QScreen *screen);
118
119private:
120 static qreal rawScaleFactor(const QPlatformScreen *screen);
121 static qreal roundScaleFactor(qreal rawFactor);
122 static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor);
123 static qreal screenSubfactor(const QPlatformScreen *screen);
124
125 static qreal m_factor;
126 static bool m_active;
127 static bool m_usePixelDensity;
128 static bool m_globalScalingActive;
129 static bool m_pixelDensityScalingActive;
130 static bool m_screenFactorSet;
131 static QDpi m_logicalDpi;
132};
133
134// Coordinate system conversion functions:
135// QHighDpi::fromNativePixels : from physical(screen/backing) to logical pixels
136// QHighDpi::toNativePixels : from logical to physical pixels
137
138namespace QHighDpi {
139
140inline qreal scale(qreal value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0))
141{
142 return value * scaleFactor;
143}
144
145inline QSize scale(const QSize &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0))
146{
147 return value * scaleFactor;
148}
149
150inline QSizeF scale(const QSizeF &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0))
151{
152 return value * scaleFactor;
153}
154
155inline QVector2D scale(const QVector2D &value, qreal scaleFactor, QPointF /* origin */ = QPointF(0, 0))
156{
157 return value * float(scaleFactor);
158}
159
160inline QPointF scale(const QPointF &pos, qreal scaleFactor, QPointF origin = QPointF(0, 0))
161{
162 return (pos - origin) * scaleFactor + origin;
163}
164
165inline QPoint scale(const QPoint &pos, qreal scaleFactor, QPoint origin = QPoint(0, 0))
166{
167 return (pos - origin) * scaleFactor + origin;
168}
169
170inline QRect scale(const QRect &rect, qreal scaleFactor, QPoint origin = QPoint(0, 0))
171{
172 return QRect(scale(pos: rect.topLeft(), scaleFactor, origin), scale(value: rect.size(), scaleFactor));
173}
174
175inline QRectF scale(const QRectF &rect, qreal scaleFactor, QPoint origin = QPoint(0, 0))
176{
177 return QRectF(scale(pos: rect.topLeft(), scaleFactor, origin), scale(value: rect.size(), scaleFactor));
178}
179
180inline QMargins scale(const QMargins &margins, qreal scaleFactor, QPoint origin = QPoint(0, 0))
181{
182 Q_UNUSED(origin)
183 return QMargins(qRound(d: qreal(margins.left()) * scaleFactor), qRound(d: qreal(margins.top()) * scaleFactor),
184 qRound(d: qreal(margins.right()) * scaleFactor), qRound(d: qreal(margins.bottom()) * scaleFactor));
185}
186
187template <typename T>
188QVector<T> scale(const QVector<T> &vector, qreal scaleFactor, QPoint origin = QPoint(0, 0))
189{
190 if (!QHighDpiScaling::isActive())
191 return vector;
192
193 QVector<T> scaled;
194 scaled.reserve(vector.size());
195 for (const T &item : vector)
196 scaled.append(scale(item, scaleFactor, origin));
197 return scaled;
198}
199
200inline QRegion scale(const QRegion &region, qreal scaleFactor, QPoint origin = QPoint(0, 0))
201{
202 if (!QHighDpiScaling::isActive())
203 return region;
204
205 QRegion scaled;
206 for (const QRect &rect : region)
207 scaled += scale(rect: QRectF(rect), scaleFactor, origin).toRect();
208 return scaled;
209}
210
211template <typename T>
212inline QPoint position(T) { return QPoint(); }
213inline QPoint position(QPoint point) { return point; }
214inline QPoint position(QPointF point) { return point.toPoint(); }
215inline QPoint position(QRect rect) { return rect.center(); }
216inline QPoint position(QRectF rect) { return rect.center().toPoint(); }
217
218template <typename T, typename C>
219T fromNativePixels(const T &value, const C *context)
220{
221 QPoint nativePosition = position(value);
222 QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context, &nativePosition);
223 return scale(value, qreal(1) / so.factor, so.origin);
224}
225
226template <typename T, typename C>
227T toNativePixels(const T &value, const C *context)
228{
229 QHighDpiScaling::ScaleAndOrigin so = QHighDpiScaling::scaleAndOrigin(context);
230 return scale(value, so.factor, so.origin);
231}
232
233template <typename T, typename C>
234T fromNativeLocalPosition(const T &value, const C *context)
235{
236 return scale(value, qreal(1) / QHighDpiScaling::factor(context));
237}
238
239template <typename T, typename C>
240T toNativeLocalPosition(const T &value, const C *context)
241{
242 return scale(value, QHighDpiScaling::factor(context));
243}
244
245template <typename T>
246inline T fromNative(const T &value, qreal scaleFactor, QPoint origin = QPoint(0, 0))
247{
248 return scale(value, qreal(1) / scaleFactor, origin);
249}
250
251template <typename T>
252inline T toNative(const T &value, qreal scaleFactor, QPoint origin = QPoint(0, 0))
253{
254 return scale(value, scaleFactor, origin);
255}
256
257inline QRect fromNative(const QRect &rect, const QScreen *screen, const QPoint &screenOrigin)
258{
259 return scale(rect, scaleFactor: qreal(1) / QHighDpiScaling::factor(context: screen), origin: screenOrigin);
260}
261
262inline QRect fromNativeScreenGeometry(const QRect &nativeScreenGeometry, const QScreen *screen)
263{
264 return QRect(nativeScreenGeometry.topLeft(),
265 scale(value: nativeScreenGeometry.size(), scaleFactor: qreal(1) / QHighDpiScaling::factor(context: screen)));
266}
267
268inline QRegion fromNativeLocalRegion(const QRegion &pixelRegion, const QWindow *window)
269{
270 return scale(region: pixelRegion, scaleFactor: qreal(1) / QHighDpiScaling::factor(context: window));
271}
272
273// When mapping expose events to Qt rects: round top/left towards the origin and
274// bottom/right away from the origin, making sure that we cover the whole window.
275inline QRegion fromNativeLocalExposedRegion(const QRegion &pixelRegion, const QWindow *window)
276{
277 if (!QHighDpiScaling::isActive())
278 return pixelRegion;
279
280 const qreal scaleFactor = QHighDpiScaling::factor(context: window);
281 QRegion pointRegion;
282 for (const QRectF rect: pixelRegion) {
283 const QPointF topLeftP = rect.topLeft() / scaleFactor;
284 const QSizeF sizeP = rect.size() / scaleFactor;
285 pointRegion += QRect(QPoint(qFloor(v: topLeftP.x()), qFloor(v: topLeftP.y())),
286 QPoint(qCeil(v: topLeftP.x() + sizeP.width() - 1.0),
287 qCeil(v: topLeftP.y() + sizeP.height() - 1.0)));
288 }
289 return pointRegion;
290}
291
292inline QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *window)
293{
294 return scale(region: pointRegion, scaleFactor: QHighDpiScaling::factor(context: window));
295}
296
297} // namespace QHighDpi
298#else // QT_NO_HIGHDPISCALING
299class Q_GUI_EXPORT QHighDpiScaling {
300public:
301 static inline void initHighDpiScaling() {}
302 static inline void updateHighDpiScaling() {}
303 static inline void setGlobalFactor(qreal) {}
304 static inline void setScreenFactor(QScreen *, qreal) {}
305
306 static inline bool isActive() { return false; }
307 static inline qreal factor(const QWindow *) { return 1.0; }
308 static inline qreal factor(const QScreen *) { return 1.0; }
309 static inline qreal factor(const QPlatformScreen *) { return 1.0; }
310 static inline QPoint origin(const QScreen *) { return QPoint(); }
311 static inline QPoint origin(const QPlatformScreen *) { return QPoint(); }
312 static inline QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
313 static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
314 static inline QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; }
315 static inline QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; }
316 static inline QDpi logicalDpi(const QScreen *screen) { return QDpi(-1,-1); }
317};
318
319namespace QHighDpi {
320 template <typename T> inline
321 T toNative(const T &value, ...) { return value; }
322 template <typename T> inline
323 T fromNative(const T &value, ...) { return value; }
324
325 template <typename T> inline
326 T fromNativeLocalPosition(const T &value, ...) { return value; }
327 template <typename T> inline
328 T toNativeLocalPosition(const T &value, ...) { return value; }
329
330 template <typename T> inline
331 T fromNativeLocalRegion(const T &value, ...) { return value; }
332 template <typename T> inline
333 T fromNativeLocalExposedRegion(const T &value, ...) { return value; }
334 template <typename T> inline
335 T toNativeLocalRegion(const T &value, ...) { return value; }
336
337 template <typename T> inline
338 T fromNativeScreenGeometry(const T &value, ...) { return value; }
339
340 template <typename T, typename U> inline
341 T toNativePixels(const T &value, const U*) {return value;}
342 template <typename T, typename U> inline
343 T fromNativePixels(const T &value, const U*) {return value;}
344}
345#endif // QT_NO_HIGHDPISCALING
346QT_END_NAMESPACE
347
348#endif // QHIGHDPISCALING_P_H
349

source code of qtbase/src/gui/kernel/qhighdpiscaling_p.h