Query the X11 screen's DPI instead of monitor

When changing the DPI via xrandr --dpi <DPI>, xrandr will send a
RRScreenChangeEvent and the DPI value should get adjusted.

Falsely, we thought randr_update() would catch up and query the right
monitor values. But nothing changes, because we query the
XRRMonitorInfo. The monitor info contains the real physical width and
height of the monitor's screen.

But xrandr --dpi only changes the - let's say - virtual screen size of
the virtual overall screen (and therefore changing the DPI to the
matching value).

Important commands to understand:

- Changes dpi of the virtual screen

    xrandr --dpi

- Gives info about the "virtual" screen size (used by DisplayWidth)

    xdpyinfo | grep -B1 resolution

- Gives info about the "physical" screen size (used by XRRMonitorInfo)

    xrandr -q

I know, that I'm probably not right and might not understand the topic
in its full size yet[0]. But I'm 100% sure, that the terms "monitor",
"screen", "screens", "output" and "display" do not have a consistent
naming scheme.
[0] https://twitter.com/dechampsgu/status/857924498280124416

Fixes #382
This commit is contained in:
Benedikt Heine 2019-02-25 19:01:34 +01:00 committed by Nikos Tsipinakis
parent 121ddd2b94
commit 4f510e1703
3 changed files with 27 additions and 20 deletions

View File

@ -237,7 +237,7 @@ static PangoLayout *layout_create(cairo_t *c)
struct screen_info *screen = get_active_screen();
PangoContext *context = pango_cairo_create_context(c);
pango_cairo_context_set_resolution(context, get_dpi_for_screen(screen));
pango_cairo_context_set_resolution(context, screen_dpi_get(screen));
PangoLayout *layout = pango_layout_new(context);

View File

@ -37,7 +37,7 @@ static int x_follow_tear_down_error_handler(void);
static int FollowXErrorHandler(Display *display, XErrorEvent *e);
static Window get_focused_window(void);
static double get_xft_dpi_value(void)
static double screen_dpi_get_from_xft(void)
{
static double dpi = -1;
//Only run this once, we don't expect dpi changes during runtime
@ -64,6 +64,30 @@ static double get_xft_dpi_value(void)
return dpi;
}
static double screen_dpi_get_from_monitor(struct screen_info *scr)
{
return (double)scr->h * 25.4 / (double)scr->mmh;
}
double screen_dpi_get(struct screen_info *scr)
{
if ( ! settings.force_xinerama
&& settings.per_monitor_dpi)
return screen_dpi_get_from_monitor(scr);
if (screen_dpi_get_from_xft() > 0)
return screen_dpi_get_from_xft();
// Calculate the DPI on the overall screen size.
// xrandr --dpi <DPI> does only change the overall screen's millimeters,
// but not the physical screen's sizes.
//
// The screen parameter is XDefaultScreen(), as our scr->id references
// the xrandr monitor and not the xrandr screen
return ((((double)DisplayWidth (xctx.dpy, XDefaultScreen(xctx.dpy))) * 25.4) /
((double)DisplayWidthMM(xctx.dpy, XDefaultScreen(xctx.dpy))));
}
void init_screens(void)
{
if (!settings.force_xinerama) {
@ -132,11 +156,6 @@ void randr_update(void)
XRRFreeMonitors(m);
}
static int autodetect_dpi(struct screen_info *scr)
{
return (double)scr->h * 25.4 / (double)scr->mmh;
}
void screen_check_event(XEvent event)
{
if (XRRUpdateConfiguration(&event)) {
@ -349,18 +368,6 @@ sc_cleanup:
return &screens[ret];
}
double get_dpi_for_screen(struct screen_info *scr)
{
double dpi = 0;
if ((!settings.force_xinerama && settings.per_monitor_dpi &&
(dpi = autodetect_dpi(scr))))
return dpi;
else if ((dpi = get_xft_dpi_value()))
return dpi;
else
return 96;
}
/*
* Return the window that currently has
* the keyboard focus.

View File

@ -20,7 +20,7 @@ void init_screens(void);
void screen_check_event(XEvent event);
struct screen_info *get_active_screen(void);
double get_dpi_for_screen(struct screen_info *scr);
double screen_dpi_get(struct screen_info *scr);
/**
* Find the currently focused window and check if it's in