From a35a5bb5f3c67f867ac6a21cad479657085f0230 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 19 Jan 2017 16:30:38 +0100 Subject: x11: pseudo HiDPI scaling Scale the window by the assumed DPI scaling factor, using 96 DPI as base. For example, a screen that reports 192 DPI is assumed to have a DPI scale factor 2. The window will then be created with twice the size. For robustness reasons, we accept only integer DPI scales between 1 and 9. We also error out if the X and Y scales are very different, as this most likely indicates a multiscreen system with botched size reporting. I'm not sure if reading the X server's DPI is such a good idea - maybe the Xrdb "Xft.dpi" value should be used instead. The current method follows what xdpyinfo does. This can be disabled with --hidpi-window-scale=no. --- DOCS/man/options.rst | 2 +- video/out/win_state.c | 21 +++++++++++++++++---- video/out/win_state.h | 2 ++ video/out/x11_common.c | 19 ++++++++++++++++++- video/out/x11_common.h | 1 + 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 00c405bd5e..e2a5c286c0 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -2343,7 +2343,7 @@ Window - ``--monitoraspect=16:9`` or ``--monitoraspect=1.7777`` ``--hidpi-window-scale``, ``--no-hidpi-window-scale`` - (OS X only) + (OS X and X11 only) Scale the window size according to the backing scale factor (default: yes). On regular HiDPI resolutions the window opens with double the size but appears as having the same size as on none-HiDPI resolutions. This is the default OS X diff --git a/video/out/win_state.c b/video/out/win_state.c index 29eaa1b663..3546daadec 100644 --- a/video/out/win_state.c +++ b/video/out/win_state.c @@ -67,13 +67,17 @@ static void apply_autofit(int *w, int *h, int scr_w, int scr_h, // Compute the "suggested" window size and position and return it in *out_geo. // screen is the bounding box of the current screen within the virtual desktop. // Does not change *vo. +// screen: position of the screen on virtual desktop on which the window +// should be placed +// dpi_scale: the DPI multiplier to get from virtual to real coordinates +// (>1 for "hidpi") // Use vo_apply_window_geometry() to copy the result into the vo. // NOTE: currently, all windowing backends do their own handling of window // geometry additional to this code. This is to deal with initial window // placement, fullscreen handling, avoiding resize on reconfig() with no // size change, multi-monitor stuff, and possibly more. -void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, - struct vo_win_geometry *out_geo) +void vo_calc_window_geometry2(struct vo *vo, const struct mp_rect *screen, + double dpi_scale, struct vo_win_geometry *out_geo) { struct mp_vo_opts *opts = vo->opts; @@ -86,12 +90,15 @@ void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, if (vo->params) params = *vo->params; + if (!opts->hidpi_window_scale) + dpi_scale = 1; + int d_w, d_h; mp_image_params_get_dsize(¶ms, &d_w, &d_h); if ((vo->driver->caps & VO_CAP_ROTATE90) && params.rotate % 180 == 90) MPSWAP(int, d_w, d_h); - d_w = MPCLAMP(d_w * opts->window_scale, 1, 16000); - d_h = MPCLAMP(d_h * opts->window_scale, 1, 16000); + d_w = MPCLAMP(d_w * opts->window_scale * dpi_scale, 1, 16000); + d_h = MPCLAMP(d_h * opts->window_scale * dpi_scale, 1, 16000); int scr_w = screen->x1 - screen->x0; int scr_h = screen->y1 - screen->y0; @@ -118,6 +125,12 @@ void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, out_geo->flags |= VO_WIN_FORCE_POS; } +void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, + struct vo_win_geometry *out_geo) +{ + vo_calc_window_geometry2(vo, screen, 1.0, out_geo); +} + // Copy the parameters in *geo to the vo fields. // (Doesn't do anything else - windowing backends should trigger VO_EVENT_RESIZE // to ensure that the VO reinitializes rendering properly.) diff --git a/video/out/win_state.h b/video/out/win_state.h index 6c3988b42b..d495377bac 100644 --- a/video/out/win_state.h +++ b/video/out/win_state.h @@ -25,6 +25,8 @@ struct vo_win_geometry { void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, struct vo_win_geometry *out_geo); +void vo_calc_window_geometry2(struct vo *vo, const struct mp_rect *screen, + double dpi_scale, struct vo_win_geometry *out_geo); void vo_apply_window_geometry(struct vo *vo, const struct vo_win_geometry *geo); #endif diff --git a/video/out/x11_common.c b/video/out/x11_common.c index d42eb70dde..6f3cc41637 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -544,6 +544,7 @@ int vo_x11_init(struct vo *vo) .screensaver_enabled = true, .xrandr_event = -1, .wakeup_pipe = {-1, -1}, + .dpi_scale = 1, }; vo->x11 = x11; @@ -595,6 +596,22 @@ int vo_x11_init(struct vo *vo) x11->ws_width, x11->ws_height, dispName, x11->display_is_local ? "local" : "remote"); + int w_mm = DisplayWidthMM(x11->display, x11->screen); + int h_mm = DisplayHeightMM(x11->display, x11->screen); + double dpi_x = x11->ws_width * 25.4 / w_mm; + double dpi_y = x11->ws_height * 25.4 / h_mm; + double base_dpi = 96; + if (isfinite(dpi_x) && isfinite(dpi_y)) { + int s_x = lrint(MPCLAMP(dpi_x / base_dpi, 0, 10)); + int s_y = lrint(MPCLAMP(dpi_y / base_dpi, 0, 10)); + if (s_x == s_y && s_x > 1 && s_x < 10) { + x11->dpi_scale = s_x; + MP_VERBOSE(x11, "Assuming DPI scale %d for prescaling. This can " + "be disabled with --hidpi-window-scale=no.\n", + x11->dpi_scale); + } + } + x11->wm_type = vo_wm_detect(vo); x11->event_fd = ConnectionNumber(x11->display); @@ -1604,7 +1621,7 @@ void vo_x11_config_vo_window(struct vo *vo) vo_x11_update_screeninfo(vo); struct vo_win_geometry geo; - vo_calc_window_geometry(vo, &x11->screenrc, &geo); + vo_calc_window_geometry2(vo, &x11->screenrc, x11->dpi_scale, &geo); vo_apply_window_geometry(vo, &geo); struct mp_rect rc = geo.win; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index 6c92fdb480..e69640cc64 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -54,6 +54,7 @@ struct vo_x11_state { int display_is_local; int ws_width; int ws_height; + int dpi_scale; struct mp_rect screenrc; char *window_title; -- cgit v1.2.3