eaf4422
From 1317f1f02fd0037e2bf7a678f2c3a9a4170161e9 Mon Sep 17 00:00:00 2001
3ae2631
From: Hans de Goede <hdegoede@redhat.com>
3ae2631
Date: Tue, 2 Jul 2019 11:55:26 +0200
efa2d86
Subject: [PATCH xserver 08/24] xwayland: Add support for randr-resolution
3ae2631
 change emulation using viewport
3ae2631
MIME-Version: 1.0
3ae2631
Content-Type: text/plain; charset=UTF-8
3ae2631
Content-Transfer-Encoding: 8bit
3ae2631
3ae2631
Add support for per client randr-resolution change emulation using viewport,
3ae2631
for apps which want to change the resolution when going fullscreen.
3ae2631
3ae2631
Partly based on earlier work on this by Robert Mader <robert.mader@posteo.de>
3ae2631
3ae2631
Note SDL2 and SFML do not restore randr resolution when going from
3ae2631
fullscreen -> windowed, I believe this is caused by us still reporting the
3ae2631
desktop resolution when they query the resolution.  This is not a problem
3ae2631
because when windowed the toplevel window size includes the window-decorations
3ae2631
so it never matches the emulated resolution.
3ae2631
3ae2631
One exception would be the window being resizable in Windowed mode and the
3ae2631
user resizing the window so that including decorations it matches the
3ae2631
emulated resolution *and* the window being at pos 0x0. But this is an
3ae2631
extreme corner case. Still I will submit patches upstream to SDL2
3ae2631
and SFML to always restore the desktop resolution under Xwayland,
3ae2631
disabling resolution emulation all together when going windowed.
3ae2631
3ae2631
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
3ae2631
Acked-by: Michel Dänzer <mdaenzer@redhat.com>
3ae2631
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
efa2d86
(cherry picked from commit d99b9ff0f237d15e7eb507484493c73b393d5dba)
3ae2631
---
3ae2631
 hw/xwayland/xwayland-input.c  |   5 +
3ae2631
 hw/xwayland/xwayland-output.c |  63 ++++++++++-
3ae2631
 hw/xwayland/xwayland.c        | 199 ++++++++++++++++++++++++++++++++++
3ae2631
 hw/xwayland/xwayland.h        |  15 +++
3ae2631
 4 files changed, 276 insertions(+), 6 deletions(-)
3ae2631
3ae2631
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
eaf4422
index a05d178ff..7d75a8f54 100644
3ae2631
--- a/hw/xwayland/xwayland-input.c
3ae2631
+++ b/hw/xwayland/xwayland-input.c
eaf4422
@@ -488,6 +488,11 @@ dispatch_pointer_motion_event(struct xwl_seat *xwl_seat)
3ae2631
             int dx = xwl_seat->focus_window->window->drawable.x;
3ae2631
             int dy = xwl_seat->focus_window->window->drawable.y;
3ae2631
 
3ae2631
+            if (xwl_window_has_viewport_enabled(xwl_seat->focus_window)) {
3ae2631
+                sx *= xwl_seat->focus_window->scale_x;
3ae2631
+                sy *= xwl_seat->focus_window->scale_y;
3ae2631
+            }
3ae2631
+
3ae2631
             x = dx + sx;
3ae2631
             y = dy + sy;
3ae2631
         } else {
3ae2631
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
eaf4422
index 64794dee7..e09d00108 100644
3ae2631
--- a/hw/xwayland/xwayland-output.c
3ae2631
+++ b/hw/xwayland/xwayland-output.c
eaf4422
@@ -371,6 +371,42 @@ err:
3ae2631
     FatalError("Failed to allocate memory for list of RR modes");
3ae2631
 }
3ae2631
 
3ae2631
+RRModePtr
3ae2631
+xwl_output_find_mode(struct xwl_output *xwl_output,
3ae2631
+                     int32_t width, int32_t height)
3ae2631
+{
3ae2631
+    RROutputPtr output = xwl_output->randr_output;
3ae2631
+    int i;
3ae2631
+
3ae2631
+    /* width & height -1 means we want the actual output mode, which is idx 0 */
3ae2631
+    if (width == -1 && height == -1 && output->modes)
3ae2631
+        return output->modes[0];
3ae2631
+
3ae2631
+    for (i = 0; i < output->numModes; i++) {
3ae2631
+        if (output->modes[i]->mode.width == width && output->modes[i]->mode.height == height)
3ae2631
+            return output->modes[i];
3ae2631
+    }
3ae2631
+
3ae2631
+    ErrorF("XWAYLAND: mode %dx%d is not available\n", width, height);
3ae2631
+    return NULL;
3ae2631
+}
3ae2631
+
3ae2631
+void
3ae2631
+xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
3ae2631
+                             RRModePtr mode, Bool from_vidmode)
3ae2631
+{
3ae2631
+    DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n",
3ae2631
+           from_vidmode ? "vidmode" : "randr",
3ae2631
+           mode->mode.width, mode->mode.height);
3ae2631
+
3ae2631
+    if (mode->mode.width == xwl_output->width && mode->mode.height == xwl_output->height)
3ae2631
+        xwl_output_remove_emulated_mode_for_client(xwl_output, client);
3ae2631
+    else
3ae2631
+        xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode);
3ae2631
+
3ae2631
+    xwl_screen_check_resolution_change_emulation(xwl_output->xwl_screen);
3ae2631
+}
3ae2631
+
3ae2631
 static void
3ae2631
 apply_output_change(struct xwl_output *xwl_output)
3ae2631
 {
eaf4422
@@ -613,21 +649,36 @@ xwl_randr_screen_set_size(ScreenPtr pScreen,
3ae2631
 static Bool
3ae2631
 xwl_randr_crtc_set(ScreenPtr pScreen,
3ae2631
                    RRCrtcPtr crtc,
3ae2631
-                   RRModePtr mode,
3ae2631
+                   RRModePtr new_mode,
3ae2631
                    int x,
3ae2631
                    int y,
3ae2631
                    Rotation rotation,
3ae2631
                    int numOutputs, RROutputPtr * outputs)
3ae2631
 {
3ae2631
     struct xwl_output *xwl_output = crtc->devPrivate;
3ae2631
+    RRModePtr mode;
3ae2631
 
3ae2631
-    if (!mode || (mode->mode.width  == xwl_output->width &&
3ae2631
-                  mode->mode.height == xwl_output->height)) {
3ae2631
-        RRCrtcChanged(crtc, TRUE);
3ae2631
-        return TRUE;
3ae2631
+    if (new_mode) {
3ae2631
+        mode = xwl_output_find_mode(xwl_output,
3ae2631
+                                    new_mode->mode.width,
3ae2631
+                                    new_mode->mode.height);
3ae2631
+    } else {
3ae2631
+        mode = xwl_output_find_mode(xwl_output, -1, -1);
3ae2631
     }
3ae2631
+    if (!mode)
3ae2631
+        return FALSE;
3ae2631
 
3ae2631
-    return FALSE;
3ae2631
+    xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), mode, FALSE);
3ae2631
+
3ae2631
+    /* A real randr implementation would call:
3ae2631
+     * RRCrtcNotify(xwl_output->randr_crtc, mode, xwl_output->x, xwl_output->y,
3ae2631
+     *              xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
3ae2631
+     * here to update the mode reported to clients querying the randr settings
3ae2631
+     * but that influences *all* clients and we do randr mode change emulation
3ae2631
+     * on a per client basis. So we just return success here.
3ae2631
+     */
3ae2631
+
3ae2631
+    return TRUE;
3ae2631
 }
3ae2631
 
3ae2631
 static Bool
3ae2631
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
eaf4422
index e00dba334..9c6cf7cf5 100644
3ae2631
--- a/hw/xwayland/xwayland.c
3ae2631
+++ b/hw/xwayland/xwayland.c
eaf4422
@@ -178,6 +178,23 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
3ae2631
     return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
3ae2631
 }
3ae2631
 
3ae2631
+/* Return the output @ 0x0, falling back to the first output in the list */
3ae2631
+struct xwl_output *
3ae2631
+xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
3ae2631
+{
3ae2631
+    struct xwl_output *xwl_output;
3ae2631
+
3ae2631
+    xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
3ae2631
+        if (xwl_output->x == 0 && xwl_output->y == 0)
3ae2631
+            return xwl_output;
3ae2631
+    }
3ae2631
+
3ae2631
+    if (xorg_list_is_empty(&xwl_screen->output_list))
3ae2631
+        return NULL;
3ae2631
+
3ae2631
+    return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
3ae2631
+}
3ae2631
+
3ae2631
 static void
3ae2631
 xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
3ae2631
                              const char *debug_msg)
eaf4422
@@ -514,6 +531,150 @@ xwl_pixmap_get(PixmapPtr pixmap)
3ae2631
     return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
3ae2631
 }
3ae2631
 
3ae2631
+Bool
3ae2631
+xwl_window_has_viewport_enabled(struct xwl_window *xwl_window)
3ae2631
+{
3ae2631
+    return (xwl_window->viewport != NULL);
3ae2631
+}
3ae2631
+
3ae2631
+static void
3ae2631
+xwl_window_disable_viewport(struct xwl_window *xwl_window)
3ae2631
+{
3ae2631
+    assert (xwl_window->viewport);
3ae2631
+
3ae2631
+    DebugF("XWAYLAND: disabling viewport\n");
3ae2631
+    wp_viewport_destroy(xwl_window->viewport);
3ae2631
+    xwl_window->viewport = NULL;
3ae2631
+}
3ae2631
+
3ae2631
+static void
3ae2631
+xwl_window_enable_viewport(struct xwl_window *xwl_window,
3ae2631
+                           struct xwl_output *xwl_output,
3ae2631
+                           struct xwl_emulated_mode *emulated_mode)
3ae2631
+{
3ae2631
+    /* If necessary disable old viewport to apply new settings */
3ae2631
+    if (xwl_window_has_viewport_enabled(xwl_window))
3ae2631
+        xwl_window_disable_viewport(xwl_window);
3ae2631
+
3ae2631
+    DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
3ae2631
+           emulated_mode->width, emulated_mode->height,
3ae2631
+           xwl_output->width, xwl_output->height);
3ae2631
+
3ae2631
+    xwl_window->viewport =
3ae2631
+        wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter,
3ae2631
+                                   xwl_window->surface);
3ae2631
+
3ae2631
+    wp_viewport_set_source(xwl_window->viewport,
3ae2631
+                           wl_fixed_from_int(0),
3ae2631
+                           wl_fixed_from_int(0),
3ae2631
+                           wl_fixed_from_int(emulated_mode->width),
3ae2631
+                           wl_fixed_from_int(emulated_mode->height));
3ae2631
+    wp_viewport_set_destination(xwl_window->viewport,
3ae2631
+                                xwl_output->width,
3ae2631
+                                xwl_output->height);
3ae2631
+
3ae2631
+    xwl_window->scale_x = (float)emulated_mode->width  / xwl_output->width;
3ae2631
+    xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height;
3ae2631
+}
3ae2631
+
3ae2631
+static Bool
3ae2631
+xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen,
3ae2631
+                                    ClientPtr client)
3ae2631
+{
3ae2631
+    WindowPtr root = xwl_screen->screen->root;
3ae2631
+    OtherClients *others;
3ae2631
+
3ae2631
+    for (others = wOtherClients(root); others; others = others->next) {
3ae2631
+        if (SameClient(others, client)) {
3ae2631
+            if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
3ae2631
+                return TRUE;
3ae2631
+        }
3ae2631
+    }
3ae2631
+
3ae2631
+    return FALSE;
3ae2631
+}
3ae2631
+
3ae2631
+static ClientPtr
3ae2631
+xwl_window_get_owner(struct xwl_window *xwl_window)
3ae2631
+{
3ae2631
+    WindowPtr window = xwl_window->window;
3ae2631
+    ClientPtr client = wClient(window);
3ae2631
+
3ae2631
+    /* If the toplevel window is owned by the window-manager, then the
3ae2631
+     * actual client toplevel window has been reparented to a window-manager
3ae2631
+     * decoration window. In that case return the client of the
3ae2631
+     * first *and only* child of the toplevel (decoration) window.
3ae2631
+     */
3ae2631
+    if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) {
3ae2631
+        if (window->firstChild && window->firstChild == window->lastChild)
3ae2631
+            return wClient(window->firstChild);
3ae2631
+        else
3ae2631
+            return NULL; /* Should never happen, skip resolution emulation */
3ae2631
+    }
3ae2631
+
3ae2631
+    return client;
3ae2631
+}
3ae2631
+
3ae2631
+static Bool
3ae2631
+xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
3ae2631
+                                  struct xwl_output **xwl_output_ret,
3ae2631
+                                  struct xwl_emulated_mode **emulated_mode_ret)
3ae2631
+{
3ae2631
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
3ae2631
+    struct xwl_emulated_mode *emulated_mode;
3ae2631
+    struct xwl_output *xwl_output;
3ae2631
+    ClientPtr owner;
3ae2631
+
3ae2631
+    if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
3ae2631
+        return FALSE;
3ae2631
+
3ae2631
+    owner = xwl_window_get_owner(xwl_window);
3ae2631
+    if (!owner)
3ae2631
+        return FALSE;
3ae2631
+
3ae2631
+    /* 1. Test if the window matches the emulated mode on one of the outputs
3ae2631
+     * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE)
3ae2631
+     */
3ae2631
+    xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
3ae2631
+        emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
3ae2631
+        if (!emulated_mode)
3ae2631
+            continue;
3ae2631
+
3ae2631
+        if (xwl_window->x == xwl_output->x &&
3ae2631
+            xwl_window->y == xwl_output->y &&
3ae2631
+            xwl_window->width  == emulated_mode->width &&
3ae2631
+            xwl_window->height == emulated_mode->height) {
3ae2631
+
3ae2631
+            *emulated_mode_ret = emulated_mode;
3ae2631
+            *xwl_output_ret = xwl_output;
3ae2631
+            return TRUE;
3ae2631
+        }
3ae2631
+    }
3ae2631
+
3ae2631
+    return FALSE;
3ae2631
+}
3ae2631
+
3ae2631
+static void
3ae2631
+xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
3ae2631
+{
3ae2631
+    struct xwl_emulated_mode *emulated_mode;
3ae2631
+    struct xwl_output *xwl_output;
3ae2631
+
3ae2631
+    if (xwl_window_should_enable_viewport(xwl_window, &xwl_output, &emulated_mode))
3ae2631
+        xwl_window_enable_viewport(xwl_window, xwl_output, emulated_mode);
3ae2631
+    else if (xwl_window_has_viewport_enabled(xwl_window))
3ae2631
+        xwl_window_disable_viewport(xwl_window);
3ae2631
+}
3ae2631
+
3ae2631
+void
3ae2631
+xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
3ae2631
+{
3ae2631
+    struct xwl_window *xwl_window;
3ae2631
+
3ae2631
+    xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window)
3ae2631
+        xwl_window_check_resolution_change_emulation(xwl_window);
3ae2631
+}
3ae2631
+
3ae2631
 static void
3ae2631
 xwl_window_init_allow_commits(struct xwl_window *xwl_window)
3ae2631
 {
eaf4422
@@ -584,6 +745,8 @@ ensure_surface_for_window(WindowPtr window)
3ae2631
 
3ae2631
     xwl_window->xwl_screen = xwl_screen;
3ae2631
     xwl_window->window = window;
3ae2631
+    xwl_window->width = window->drawable.width;
3ae2631
+    xwl_window->height = window->drawable.height;
3ae2631
     xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
3ae2631
     if (xwl_window->surface == NULL) {
3ae2631
         ErrorF("wl_display_create_surface failed\n");
eaf4422
@@ -625,6 +788,7 @@ ensure_surface_for_window(WindowPtr window)
3ae2631
 
3ae2631
     dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
3ae2631
     xorg_list_init(&xwl_window->link_damage);
3ae2631
+    xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list);
3ae2631
 
1e468bc
 #ifdef GLAMOR_HAS_GBM
1e468bc
     xorg_list_init(&xwl_window->frame_callback_list);
eaf4422
@@ -718,8 +882,12 @@ xwl_unrealize_window(WindowPtr window)
3ae2631
     if (!xwl_window)
3ae2631
         return ret;
3ae2631
 
3ae2631
+    if (xwl_window_has_viewport_enabled(xwl_window))
3ae2631
+        xwl_window_disable_viewport(xwl_window);
3ae2631
+
3ae2631
     wl_surface_destroy(xwl_window->surface);
3ae2631
     xorg_list_del(&xwl_window->link_damage);
3ae2631
+    xorg_list_del(&xwl_window->link_window);
3ae2631
     unregister_damage(window);
3ae2631
 
3ae2631
     if (xwl_window->frame_callback)
eaf4422
@@ -769,6 +937,33 @@ xwl_set_window_pixmap(WindowPtr window,
3ae2631
     ensure_surface_for_window(window);
3ae2631
 }
3ae2631
 
3ae2631
+static void
3ae2631
+xwl_resize_window(WindowPtr window,
3ae2631
+                  int x, int y,
3ae2631
+                  unsigned int width, unsigned int height,
3ae2631
+                  WindowPtr sib)
3ae2631
+{
3ae2631
+    ScreenPtr screen = window->drawable.pScreen;
3ae2631
+    struct xwl_screen *xwl_screen;
3ae2631
+    struct xwl_window *xwl_window;
3ae2631
+
3ae2631
+    xwl_screen = xwl_screen_get(screen);
3ae2631
+    xwl_window = xwl_window_get(window);
3ae2631
+
3ae2631
+    screen->ResizeWindow = xwl_screen->ResizeWindow;
3ae2631
+    (*screen->ResizeWindow) (window, x, y, width, height, sib);
3ae2631
+    xwl_screen->ResizeWindow = screen->ResizeWindow;
3ae2631
+    screen->ResizeWindow = xwl_resize_window;
3ae2631
+
3ae2631
+    if (xwl_window) {
3ae2631
+        xwl_window->x = x;
3ae2631
+        xwl_window->y = y;
3ae2631
+        xwl_window->width = width;
3ae2631
+        xwl_window->height = height;
3ae2631
+        xwl_window_check_resolution_change_emulation(xwl_window);
3ae2631
+    }
3ae2631
+}
3ae2631
+
3ae2631
 static void
3ae2631
 frame_callback(void *data,
3ae2631
                struct wl_callback *callback,
eaf4422
@@ -1246,6 +1441,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
3ae2631
     xorg_list_init(&xwl_screen->output_list);
3ae2631
     xorg_list_init(&xwl_screen->seat_list);
3ae2631
     xorg_list_init(&xwl_screen->damage_window_list);
3ae2631
+    xorg_list_init(&xwl_screen->window_list);
3ae2631
     xwl_screen->depth = 24;
3ae2631
 
eaf4422
     if (!monitorResolution)
eaf4422
@@ -1340,6 +1536,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
3ae2631
     xwl_screen->CloseScreen = pScreen->CloseScreen;
3ae2631
     pScreen->CloseScreen = xwl_close_screen;
3ae2631
 
3ae2631
+    xwl_screen->ResizeWindow = pScreen->ResizeWindow;
3ae2631
+    pScreen->ResizeWindow = xwl_resize_window;
3ae2631
+
3ae2631
     if (xwl_screen->rootless) {
3ae2631
         xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
3ae2631
         pScreen->SetWindowPixmap = xwl_set_window_pixmap;
3ae2631
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
eaf4422
index c886d77e9..36c4c4c8b 100644
3ae2631
--- a/hw/xwayland/xwayland.h
3ae2631
+++ b/hw/xwayland/xwayland.h
3ae2631
@@ -135,10 +135,12 @@ struct xwl_screen {
3ae2631
     DestroyWindowProcPtr DestroyWindow;
3ae2631
     XYToWindowProcPtr XYToWindow;
3ae2631
     SetWindowPixmapProcPtr SetWindowPixmap;
3ae2631
+    ResizeWindowProcPtr ResizeWindow;
3ae2631
 
3ae2631
     struct xorg_list output_list;
3ae2631
     struct xorg_list seat_list;
3ae2631
     struct xorg_list damage_window_list;
3ae2631
+    struct xorg_list window_list;
3ae2631
 
3ae2631
     int wayland_fd;
3ae2631
     struct wl_display *display;
3ae2631
@@ -179,9 +181,13 @@ struct xwl_screen {
3ae2631
 struct xwl_window {
3ae2631
     struct xwl_screen *xwl_screen;
3ae2631
     struct wl_surface *surface;
3ae2631
+    struct wp_viewport *viewport;
3ae2631
+    int32_t x, y, width, height;
3ae2631
+    float scale_x, scale_y;
3ae2631
     struct wl_shell_surface *shell_surface;
3ae2631
     WindowPtr window;
3ae2631
     struct xorg_list link_damage;
3ae2631
+    struct xorg_list link_window;
3ae2631
     struct wl_callback *frame_callback;
3ae2631
     Bool allow_commits;
3ae2631
 #ifdef GLAMOR_HAS_GBM
eaf4422
@@ -411,6 +417,9 @@ Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
3ae2631
 
3ae2631
 struct xwl_screen *xwl_screen_get(ScreenPtr screen);
3ae2631
 Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen);
3ae2631
+struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen);
3ae2631
+void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen);
3ae2631
+Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window);
3ae2631
 
3ae2631
 void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool);
3ae2631
 void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
eaf4422
@@ -444,6 +453,12 @@ void xwl_output_remove(struct xwl_output *xwl_output);
3ae2631
 struct xwl_emulated_mode *xwl_output_get_emulated_mode_for_client(
3ae2631
                             struct xwl_output *xwl_output, ClientPtr client);
3ae2631
 
3ae2631
+RRModePtr xwl_output_find_mode(struct xwl_output *xwl_output,
3ae2631
+                               int32_t width, int32_t height);
3ae2631
+void xwl_output_set_emulated_mode(struct xwl_output *xwl_output,
3ae2631
+                                  ClientPtr client, RRModePtr mode,
3ae2631
+                                  Bool from_vidmode);
3ae2631
+
3ae2631
 RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
3ae2631
                        float VRefresh, Bool Reduced, Bool Interlaced);
3ae2631
 
3ae2631
-- 
eaf4422
2.26.2
3ae2631