summaryrefslogtreecommitdiff
path: root/hw/xwayland
diff options
context:
space:
mode:
authorOlivier Fourdan <ofourdan@redhat.com>2023-11-02 11:04:18 +0100
committerOlivier Fourdan <ofourdan@redhat.com>2024-03-20 09:05:36 +0100
commit4003b1f9a28c4a333cab9ca7e64a7027ed1da58f (patch)
treee706fa9eee8ef16d8eb89f4a53399e0c2c2960b1 /hw/xwayland
parent290ae87c02abf5070422bb50af948402345ab4e1 (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.man5
-rw-r--r--hw/xwayland/meson.build1
-rw-r--r--hw/xwayland/xwayland-screen.c32
-rw-r--r--hw/xwayland/xwayland-screen.h2
-rw-r--r--hw/xwayland/xwayland-window.c36
-rw-r--r--hw/xwayland/xwayland.c4
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;
}