We are happy to share the results of our work on cross-platform high-DPI
scaling in Qt, which is planned for Qt 5.6. It is now at a stage where it can
be tested by others. You can get the code from our branch in qtbase:
wip/highdpi. The branch is open for business, and contributions are welcome. We
also have a IRC channel: #qt-highdpi on Freenode. There will also be a session
in the Qt Contributors’ Summit this weekend. :)
Quick Getting Started
There are three ways to test the high-DPI scaling:
1) Set QT_SCALE_FACTOR (to a number != 1) and run your favorite Qt app.
2) Try the DPI scale slider in tests/manual/highdpi .
3) Set QT_AUTO_SCREEN_SCALE_FACTOR=1 on Windows or X11 multi-screen setups.
The rest of this mail will describe the changes in detail.
This project is a part of a larger effort of making Qt more resolution
independent. There are two approaches in development:
1) Adding resolution independent units to QML / Qt Quick.
2) Scaling with devicePixelRatio.
This project is part of “Scaling with devicePixelRatio”: implementing
devicePixelRatio scaling in cross-platform Qt code. We have had unofficial
scaling support for X11 and Windows in Qt 5.4 and 5.5. That was implemented
completely in the platform plugins. The main benefits of now moving the scaling
logic to QtGui are:
1) Support for devicePixelRatio scaling on platforms that have limited or no
native support. (X11, Windows, Android, Embedded linux)
2) Improving the developer experience: any devicePixelRatio can be simulated on
any hardware.
3) Support for “de-scaling” on platforms that natively scales: Qt application
can operate entierly in device pixels.
Sidebar: How does devicePixelRatio scaling work again?
devicePixelRatio scaling works by virtualizing the main coordinate system seen
by applications. The “pixel” coordinate system is split into two: device
independent pixels and device pixels. Window and event geometry is specified in
device independent pixels which are closely related to visual size. Backing
stores and graphics output in general are in device pixels which are closely
related to the display resolution.
Project Scope
devicePixelRatio scaling is best implemented as a part of the Windowing system,
at least for production use. Depending in the level of operating system support
the Qt scaling Depending in the level of operating system support the Qt
scaling will have known edge case bugs. This also varies with the use case: A
single screen with a fullscreen window is relatively simple, multi-screen
desktop environments are more complex.
Officially, we aim to support only integer scale factors. However, fractional
scale factors do work, since we use qreal everywhere. This means that
developers can test and evaluate the effects of fractional scale factors, and
it also gives the end user the option to decide whether the results are
acceptable or not.
Implementation Overview
The high-DPI patches inserts a coordinate scaling layer in the lower parts of
QtGui and introduces a new coordinate system: native pixels. The platform
plugins now operate in native pixels and are mostly unaware of the scaling
layer added to QtGui. Native pixels are internal to Qt and are not exposed to
applications.
Proper layering now becomes more important, effectively restricting where
certain API can be called from.
* In the platform plugins: Don’t use QWindow. QPlatformWindow now has geometry
accessor convenience functions.
* In the platform plugins: Don’t call QGuiApplication, go through
QWindowSystemInterface.
* In QtGui: Don’t use QPlatformFoo classes outside of the corresponding QFoo
class (QPlatformWindow, QPlatformScreen)
* In auto tests: Don’t call QWindowSystemInterface, use the QTest event synth.
functions.
These are not set-in-stone rules. If you find you need to break one of them,
add QHighDpi scaling calls.
API For Setting Scale Factors
(note that since this mail goes to development@ we’re also discussing private
API here, which may change or be removed.)
Environment variables:
* QT_DEVICE_PIXEL_RATIO: Now deprecated (but still supported in 5.6).
* QT_SCALE_FACTOR: Sets a global scale factor for the process.
* QT_AUTO_SCREEN_SCALE_FACTOR: Enables a per-screen scale factor defined by the
platform plugin based on the physical DPI of each screen. Currently implemented
on Xcb and Windows.
Private API:
QPlatformScreen:pixelDensity() : Tells Qt to apply the given scale
factor to all windows on a screen.
QHighDpiScaling::setScreenFactor(QScreen *, factor): set a screen
scaling factor at run-time. Currently used by the tests/manual/highdpi manual
test.
API For Accessing devicePIxelRatio
The devicePixelRatio is the product of the OS and Qt scale factors. The
preferred accessor functions are:
QWindow::devicePixelRatio()
QPaintDevice::devicePixelRatioF()
For QtGui implementation work the principal functions for converting between
native and device independent pixels are:
T fromNativePixels(T, QWindow *)
T toNativePixels(T, QWindow *)
plus a number of overloads and variants for handling special cases (screen
position mapping, window screen change, etc.). We are currently working on
reducing and managing the overload set.
Signed,
Paul, Morten, Friedemann (in absentia)
_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development