diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c index 6f073893a..9967f439a 100644 --- a/src/wayland/meta-window-xwayland.c +++ b/src/wayland/meta-window-xwayland.c @@ -20,6 +20,7 @@ #include "x11/window-x11.h" #include "x11/window-x11-private.h" +#include "x11/xprops.h" #include "wayland/meta-window-xwayland.h" #include "wayland/meta-wayland.h" @@ -53,6 +54,93 @@ meta_window_xwayland_init (MetaWindowXwayland *window_xwayland) { } +/** + * meta_window_xwayland_adjust_fullscreen_monitor_rect: + * + * This function implements a workaround for X11 apps which use randr to change the + * the monitor resolution, followed by setting _NET_WM_FULLSCREEN to make the + * window-manager fullscreen them. + * + * Newer versions of Xwayland support the randr part of this by supporting randr + * resolution change emulation in combination with using WPviewport to scale the + * app's window (at the emulated resolution) to fill the entire monitor. + * + * Apps using randr in combination with NET_WM_STATE_FULLSCREEN expect the + * fullscreen window to have the size of the emulated randr resolution since + * when running on regular Xorg the resolution will actually be changed and + * after that going fullscreen through NET_WM_STATE_FULLSCREEN will size + * the window to be equal to the new resolution. + * + * We need to emulate this behavior for these apps to work correctly. + * + * Xwayland's emulated resolution is a per X11 client setting and Xwayland + * will set a special _XWAYLAND_RANDR_EMU_MONITOR_RECTS property on the + * toplevel windows of a client (and only those of that client), which has + * changed the (emulated) resolution through a randr call. + * + * Here we check for that property and if it is set we adjust the fullscreen + * monitor rect for this window to match the emulated resolution. + * + * Here is a step-by-step of such an app going fullscreen: + * 1. App changes monitor resolution with randr. + * 2. Xwayland sets the _XWAYLAND_RANDR_EMU_MONITOR_RECTS property on all the + * apps current and future windows. This property contains the origin of the + * monitor for which the emulated resolution is set and the emulated + * resolution. + * 3. App sets _NET_WM_FULLSCREEN. + * 4. We check the property and adjust the app's fullscreen size to match + * the emulated resolution. + * 5. Xwayland sees a Window at monitor origin fully covering the emulated + * monitor resolution. Xwayland sets a viewport making the emulated + * resolution sized window cover the full actual monitor resolution. + */ +static void +meta_window_xwayland_adjust_fullscreen_monitor_rect (MetaWindow *window, + MetaRectangle *fs_monitor_rect) +{ + MetaX11Display *x11_display = window->display->x11_display; + MetaRectangle win_monitor_rect; + cairo_rectangle_int_t *rects; + uint32_t *list = NULL; + int i, n_items = 0; + + if (!window->monitor) + { + g_warning ("MetaWindow does not have a monitor"); + return; + } + + win_monitor_rect = meta_logical_monitor_get_layout (window->monitor); + + if (!meta_prop_get_cardinal_list (x11_display, + window->xwindow, + x11_display->atom__XWAYLAND_RANDR_EMU_MONITOR_RECTS, + &list, &n_items)) + return; + + if (n_items % 4) + { + meta_verbose ("_XWAYLAND_RANDR_EMU_MONITOR_RECTS on %s has %d values which is not a multiple of 4", + window->desc, n_items); + g_free (list); + return; + } + + rects = (cairo_rectangle_int_t *) list; + n_items = n_items / 4; + for (i = 0; i < n_items; i++) + { + if (rects[i].x == win_monitor_rect.x && rects[i].y == win_monitor_rect.y) + { + fs_monitor_rect->width = rects[i].width; + fs_monitor_rect->height = rects[i].height; + break; + } + } + + g_free (list); +} + static void meta_window_xwayland_force_restore_shortcuts (MetaWindow *window, ClutterInputDevice *source) @@ -115,6 +203,7 @@ meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) MetaWindowClass *window_class = META_WINDOW_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + window_class->adjust_fullscreen_monitor_rect = meta_window_xwayland_adjust_fullscreen_monitor_rect; window_class->force_restore_shortcuts = meta_window_xwayland_force_restore_shortcuts; window_class->shortcuts_inhibited = meta_window_xwayland_shortcuts_inhibited; diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h index b61f47ff4..4099d5d31 100644 --- a/src/x11/atomnames.h +++ b/src/x11/atomnames.h @@ -81,6 +81,7 @@ item(ATOM_PAIR) item(_XKB_RULES_NAMES) item(WL_SURFACE_ID) item(_XWAYLAND_MAY_GRAB_KEYBOARD) +item(_XWAYLAND_RANDR_EMU_MONITOR_RECTS) /* Oddities: These are used, and we need atoms for them, * but when we need all _NET_WM hints (i.e. when we're making