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

Reply via email to