Winit: X11 HiDPI scaling algorithm is broken

Created on 7 May 2017  路  11Comments  路  Source: rust-windowing/winit

As a well-known fact, X11 locks the DPI to 96 and the current code gets incorrect screen size, resulting in the scale factor always being 1.

The defacto standard is to use Xft.dpi to get font DPI.

hard X11 high in progress platform parity

All 11 comments

Hi. I was just burnt by this problem, and I've had a go at fixing it. PR: https://github.com/tomaka/winit/pull/198

@stevebob it sounds like you're fixing another problem. This issue is about hidpi_factor being virtually constant, with how most desktop environments sets the DPI.

Ah, I think I misinterpreted your comment. I set my dpi using xrandr and I observe it changing (with hidpi_factor), but when querying a window's size in points it instead reported its size in pixels, causing the result when querying it's size in pixels to be incorrect. It sounded close enough to this issue that I thought it might be related.

As a well-known fact, X11 locks the DPI to 96 and the current code gets incorrect screen size, resulting in the scale factor always being 1.

This is not well-known to me. If xrandr can freely set the DPI (and @stevebob's reports and my own experience suggest that it can), then it's manifestly the case that X11 does not lock the DPI to anything.

The defacto standard is to use Xft.dpi to get font DPI.

Can you support this claim?

About 96 dpi: https://bugs.freedesktop.org/show_bug.cgi?id=23705 https://bugs.freedesktop.org/show_bug.cgi?id=41115
The term "lock" is somewhat absurd, but I meant that the default is always 96 instead of the autodetect which is the behavior long ago.

Qt uses font DPI, and GNOME also sets that (although GTK itself uses a separate environment variable).

Upping this issue (as I just hit it: most of my system picks up the config in xft.dpi but winit does not).

Would it make sense to use xft.dpi if the value is set, and default to dpi reported by XRandr otherwise?

Few thoughts -

  • Xft.dpi is global and cannot support mixed DPI environments
  • If an application wants to use Xft.dpi, is winit really the right place to read that value?
  • winit should provide access to per-monitor scale factor. If you've got one hidpi monitor and one regular, you'd like your applications to appear reasonable on both (versus having huge/tiny text on one or the other).
  • Font rendering results (especially with subpixel aa, hinting) are best when physical DPI is used
  • xrandr provides physical DPI, and it provides it for each monitor.

Agreed that xft.dpi cannot properly handle mixed dpi environments.

But it looks like (cf the previously linked issues on Xorg's bugtracker), that DPI with X11 is a sad story anyway.

Personally, I'm still trying to figure out if I have a way to have XRandR correctly advertize the DPI as being 192 rather than its default 96 other than manually running xrandr --dpi 192 (and even then, it decides to set it to 192x193 for some reason).

@vberger AFAIK, the typical way to compute DPI using xrandr is to take the screen size in millimeters, divide by 25.4, and then divide the resolution by that value. For instance, my main display looks like this:

DVI-I-1 connected 2560x1440+1080+176 (normal left inverted right x axis y axis) 597mm x 336mm

Horizontal: 2560 / (597 / 25.4) = 109
Vertical: 1440 / (336 / 25.4) = 109

When the X server supports RANDR 1.2 or later, the DPI information reported by the core protocol is unreliable. DPI calculations should be done on a per-output (or per-Monitor with RANDR 1.5 or later) basis. This is e.g. what Qt does when QT_AUTO_SCREEN_SCALE_FACTOR=1 is set. My understanding (following this) is that the approach used in Qt is the following:

  • compute per-output DPI from the output's resolution and physical size;
  • compute a reference DPI using Xft.dpi falling back to the core DPI if Xft.dpi is unset;
  • compute per-output scaling as (monitor DPI)/(primary DPI) * (reference DPI)/96;

The individual window scaling then adapts to the output the window is on. As a frequent user of mixed-DPI environments, I find this approach works quite well, and I would recommend it for adoption everywhere.

@Oblomov thanks for the info! I also read your post.This looks like it will be easy to fix now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Osspial picture Osspial  路  5Comments

chemicstry picture chemicstry  路  3Comments

rukai picture rukai  路  4Comments

mistodon picture mistodon  路  4Comments

tomaka picture tomaka  路  3Comments