[Development] Cross-platform high-DPI Qt tech preview

Sorvig Morten Morten.Sorvig at theqtcompany.com
Thu Jun 4 22:46:17 CEST 2015


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)



More information about the Development mailing list