diff --git a/hw/xwayland/man/Xwayland.man b/hw/xwayland/man/Xwayland.man index 46fd6c2d9..e30799e9a 100644 --- a/hw/xwayland/man/Xwayland.man +++ b/hw/xwayland/man/Xwayland.man @@ -82,6 +82,11 @@ and fallback to GL ES if GL version is less than 2.1. This option is not compatible with \fI-shm\fP option. .TP 8 +.B \-hidpi +Adjust to the scale of the outputs when running rootful in windowing mode. + +This option is not compatible with rootless mode (\fI-rootless\fP). +.TP 8 .B \-host-grab Disable host keyboard shorcuts and confine the pointer when running rootful. diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build index ee05749d7..f27c3ea2b 100644 --- a/hw/xwayland/meson.build +++ b/hw/xwayland/meson.build @@ -174,6 +174,7 @@ xwayland_vars = [ 'have_decorate=' + have_libdecor.to_string(), 'have_enable_ei_portal=' + build_ei_portal.to_string(), 'have_byteswappedclients=true', + 'have_hidpi=true', ] pkgconfig = import('pkgconfig') diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index 11460a723..39e2439df 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -768,6 +768,35 @@ xwl_screen_lost_focus(struct xwl_screen *xwl_screen) } } +Bool +xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen) +{ + ScreenPtr screen = xwl_screen->screen; + struct xwl_window *xwl_window; + int32_t old_scale; + + if (xwl_screen->rootless) + return FALSE; + + if (xwl_screen->fullscreen) + return FALSE; + + if (!xwl_screen->hidpi) + return FALSE; + + if (screen->root == NullWindow) + return FALSE; + + xwl_window = xwl_window_get(screen->root); + if (!xwl_window) + return FALSE; + + old_scale = xwl_screen->global_surface_scale; + xwl_screen->global_surface_scale = xwl_window_get_max_output_scale(xwl_window); + + return (xwl_screen->global_surface_scale != old_scale); +} + Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) { @@ -881,6 +910,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) else if (strcmp(argv[i], "-nokeymap") == 0) { xwl_screen->nokeymap = 1; } + else if (strcmp(argv[i], "-hidpi") == 0) { + xwl_screen->hidpi = 1; + } } if (!xwl_screen->rootless) { diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index c8c093fbe..1770053d6 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -66,6 +66,7 @@ struct xwl_screen { int decorate; int enable_ei_portal; int nokeymap; + int hidpi; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; @@ -170,5 +171,6 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen, int32_t x, int32_t y, int32_t width, int32_t height); int xwl_screen_get_next_output_serial(struct xwl_screen * xwl_screen); void xwl_screen_lost_focus(struct xwl_screen *xwl_screen); +Bool xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen); #endif /* XWAYLAND_SCREEN_H */ diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index 626a5d22d..a10453e13 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -671,10 +671,10 @@ xwl_window_maybe_resize(struct xwl_window *xwl_window, double width, double heig xwl_screen->height = height; xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (!xwl_randr_add_modes_fixed(xwl_output, round(width), round(height))) + if (!xwl_randr_add_modes_fixed(xwl_output, round(width / scale), round(height / scale))) return; - mode = xwl_output_find_mode(xwl_output, round(width), round(height)); + mode = xwl_output_find_mode(xwl_output, round(width / scale), round(height / scale)); xwl_output_set_mode_fixed(xwl_output, mode); xwl_window_attach_buffer(xwl_window); @@ -797,7 +797,39 @@ static const struct xdg_surface_listener xdg_surface_listener = { static void xwl_window_update_surface_scale(struct xwl_window *xwl_window) { + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + int previous_scale, new_scale; + double new_width, new_height; + + previous_scale = xwl_screen->global_surface_scale; + assert(previous_scale != 0); xwl_window->surface_scale = xwl_window_get_max_output_scale(xwl_window); + + if (xwl_screen_update_global_surface_scale(xwl_screen)) { + new_scale = xwl_screen->global_surface_scale; + + DebugF("XWAYLAND: Global scale is now %i (was %i)\n", + new_scale, previous_scale); + + new_width = xwl_screen->width / previous_scale * new_scale; + new_height = xwl_screen->height / previous_scale * new_scale; + + wl_surface_set_buffer_scale(xwl_window->surface, xwl_screen->global_surface_scale); + /* Reflect the scale factor using XRandR transform */ + xwl_output_set_xscale(xwl_screen->fixed_output, new_scale); + xwl_window_maybe_resize(xwl_window, new_width, new_height); +#ifdef XWL_HAS_LIBDECOR + if (xwl_window->libdecor_frame) { + xwl_window_libdecor_set_size_limits(xwl_window); + xwl_window_update_libdecor_size(xwl_window, + NULL, + round(new_width / new_scale), + round(new_height / new_scale)); + } + else +#endif + wl_surface_commit(xwl_window->surface); + } } static void diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 7ef0056e8..81b8a7ec0 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -97,6 +97,7 @@ ddxUseMsg(void) ErrorF("-rootless run rootless, requires wm support\n"); ErrorF("-fullscreen run fullscreen when rootful\n"); ErrorF("-geometry WxH set Xwayland window size when rootful\n"); + ErrorF("-hidpi adjust to output scale when rootful\n"); ErrorF("-host-grab disable host keyboard shortcuts when rootful\n"); ErrorF("-nokeymap ignore keymap from the Wayland compositor\n"); ErrorF("-output specify which output to use for fullscreen when rootful\n"); @@ -269,6 +270,9 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (strcmp(argv[i], "-nokeymap") == 0) { return 1; } + else if (strcmp(argv[i], "-hidpi") == 0) { + return 1; + } return 0; }