High resolution displays and GNOME
For years, developers have lived comfortably with the assumption that screen resolutions were in the predictable confines of a certain pixel density—around 75 to 100 pixels-per-inch (ppi). As everyone who sees the latest Chromebook models from Google knows, however, such is no longer the case: the newest displays are well over 200 ppi. There have been partially-completed attempts to modify GNOME for high-resolution display support, but with little success. But now there appears to be a workable solution, as Alex Larsson demonstrated at GUADEC 2013.
The latest Chromebook (the "Pixel") boasts a 239 ppi screen, Larsson said, at which resolution GNOME's user interface elements are unreadably tiny. Allegedly, the display resolution is configurable, via the Xft.DPI setting, which has long been hard-coded to 96 in GNOME. But simply changing it to 239 does not work; as he showed the audience, the result only scales the size of displayed text. Although that improves legibility, UI elements like buttons and scrollbars are still ridiculously tiny. In addition, text labels and icons no longer line up, the default heights of menu bars and buttons is no longer correct, and many other UI assumptions are broken.
Perhaps the system could be modified to scale everything according to this DPI setting, he said. But despite the fact that the idea seems intuitive, he continued, simply scaling all of the UI elements is not the solution—scaling lines to a non-integer-multiple gives the user fuzzy lines that should be sharp and blurry icons that arguably look worse than the unscaled originals. Vector elements need to be drawn so that they align to the pixel grid of the display, and a separate fix needs to be available for those elements still using PNG or other raster graphics formats.
There are a lot of places in GNOME's user interface that are implicitly sized according to raster images and pixel-specific measurements: icons, cursors, window borders, padding, the minimum sizes of GTK+ widgets—even the cursor speed is defined in terms of pixels. The list of places where the code would need to change is lengthy, and changing it holds the possibility for a lot of unexpected breakage.
But then again, he continued, scaling everything to the exact same physical size is not strictly required; users already cope well with the variations in size caused by the different resolutions of laptop displays and external monitors; no one complains that a button is 6mm high on one and 8mm high on the other. All that really matters is that the system scales elements to approximately similar size on the Pixel display.
Abstraction to the rescue
The notion that the correct solution only needs to approximate the difference in resolution turned out to be one of the key insights. Larsson's eventual answer was to treat the existing "pixel" sizes already in use as an abstract, rather than a physical measurement, so that high-resolution displays appear low-resolution to the top levels of the software stack, and to set a scaling factor that multiplies the actual pixel count rendered on high-resolution displays. For almost everything above the drawing layer, the current definition of pixel would suffice; the pixel size itself could be scaled only when rendered by the lower-level libraries like Cairo and GDK, with very few side effects. Moreover, by always scaling abstract pixels to monitor pixels by integer factors, the pixel grid would automatically be preserved, meaning vector images would remain sharp—and the math would be considerably simpler, too.
He then implemented the abstract pixel scaling plan in Cairo, GDK, and GTK+. Normal monitors are unaffected, as their scaling factor is 1. "HiDPI" monitors like the Pixel use a scaling factor of 2, which results in a usable desktop interface, despite the on-screen elements not quite being the same physical dimensions.
In Cairo, the high-resolution scale factor is applied when the Cairo surface is rendered; applications can access the scaling factor for the display with cairo_surface_get_device_scale(), but normally GTK+ hides it completely. Similarly, in GDK, the sizes and positions of windows, screens, and monitors is still reported in abstract pixels; gdk_window_get_scale_factor() will report the scaling factor, but it is usually unnecessary for applications to know it. Wayland compositors will scale client buffers as necessary, and will allow clients to provide double-scale buffers to cope with the occasional window that spans both a high- and low-resolution display. X support is less flexible; all displays must be the same scale, which is reported via the GDK_SCALE environment variable, but, Larsson said, Wayland is the protocol of the future, so the development there is more important.
There are new functions like gdk_window_create_similar_surface() to transparently create an offscreen surface for the purpose of double-buffering, and GtkIconTheme has been patched to support specifying both normal-resolution and high-resolution versions of icons, but by and large the scaling function is invisible to application code. There are also hooks in place for use when displaying images and other situations where scaling up window content is inappropriate. The scaling functionality is due to land in Cairo 1.13, and Wayland support has been added in version 1.2 of the Wayland protocol definition. The GTK+ and GDK changes are currently available in Larsson's wip/window-scales branch.
Larsson added that GTK+ on Mac OS X also supports the scaling factor, using the operating system's Quartz library. Windows support, however, remains on the to-do list. For the time being, there are very few displays on the market that require a scaling factor other than 1. Larsson described the Chromebook Pixel as the primary driving factor, but Apple Retina displays are also supported, and there are a handful of high-density netbook displays that qualify as high-resolution as well. For the present, 1 and 2 remain the only scaling factors in deployment. There is no telling if or when a 3 or 4 scaling factor will be required for some future display, but when it does, the GNOME stack will be prepared well in advance.
[The author wishes to thank the GNOME Foundation for assistance
with travel to GUADEC 2013.]
| Index entries for this article | |
|---|---|
| Conference | GUADEC/2013 |
