diff options
author | Olivier Fourdan <ofourdan@redhat.com> | 2023-11-02 11:04:18 +0100 |
---|---|---|
committer | Olivier Fourdan <ofourdan@redhat.com> | 2024-03-20 09:05:36 +0100 |
commit | 4003b1f9a28c4a333cab9ca7e64a7027ed1da58f (patch) | |
tree | e706fa9eee8ef16d8eb89f4a53399e0c2c2960b1 /hw/xwayland | |
parent | 290ae87c02abf5070422bb50af948402345ab4e1 (diff) |
xwayland: Update the global screen scale
Recompute and update the global screen scale based on the different
outputs the root window is placed on.
For backward compatibility, this functionality is however disabled by
default and can be enabled using a new command line option "-hidpi".
That option has no effect if Xwayland is running rootless.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-By: Kenny Levinsen <kl@kl.wtf>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1197>
Diffstat (limited to 'hw/xwayland')
-rw-r--r-- | hw/xwayland/man/Xwayland.man | 5 | ||||
-rw-r--r-- | hw/xwayland/meson.build | 1 | ||||
-rw-r--r-- | hw/xwayland/xwayland-screen.c | 32 | ||||
-rw-r--r-- | hw/xwayland/xwayland-screen.h | 2 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.c | 36 | ||||
-rw-r--r-- | hw/xwayland/xwayland.c | 4 |
6 files changed, 78 insertions, 2 deletions
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 @@ -769,6 +769,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) { static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS"; @@ -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; } |