xserver: Branch 'master' - 11 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Feb 23 17:51:46 UTC 2020


 hw/xwayland/xwayland-output.c |   14 ++-
 hw/xwayland/xwayland-screen.c |    6 +
 hw/xwayland/xwayland-screen.h |    3 
 hw/xwayland/xwayland-window.c |  155 ++++++++++++++++++++++++++----------------
 hw/xwayland/xwayland-window.h |    7 +
 5 files changed, 120 insertions(+), 65 deletions(-)

New commits:
commit d4faab8708779df265239b203ed5f020bff681bf
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Nov 4 15:01:18 2019 +0100

    xwayland: Remove unnecessary xwl_window_is_toplevel() check from xwl_output_set_window_randr_emu_props()
    
    Since the recent fix to call xwl_output_set_window_randr_emu_props() from
    ensure_surface_for_window(), it is now only called on a toplevel window,
    so the is-toplevel check is not necessary for the
    xwl_output_set_window_randr_emu_props() case.
    
    This commit moves the check to xwl_output_set_randr_emu_prop_callback()
    so that we only do it when we are walking over all Windows of a client
    to update the property on a change of the emulated resolution.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 933f8f63b..04eb42e8e 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -472,9 +472,6 @@ static void
 xwl_output_set_randr_emu_prop(WindowPtr window,
                               struct xwl_output_randr_emu_prop *prop)
 {
-    if (!xwl_window_is_toplevel(window))
-        return;
-
     if (prop->rect_count) {
         dixChangeWindowProperty(serverClient, window, prop->atom,
                                 XA_CARDINAL, 32, PropModeReplace,
@@ -487,7 +484,8 @@ xwl_output_set_randr_emu_prop(WindowPtr window,
 static void
 xwl_output_set_randr_emu_prop_callback(void *resource, XID id, void *user_data)
 {
-    xwl_output_set_randr_emu_prop(resource, user_data);
+    if (xwl_window_is_toplevel(resource))
+        xwl_output_set_randr_emu_prop(resource, user_data);
 }
 
 static void
commit 148f428dfccf606b932a00d5a00af06e8dca8a7e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Nov 4 14:32:29 2019 +0100

    xwayland: Fix setting of _XWAYLAND_RANDR_EMU_MONITOR_RECTS prop on new windows
    
    For window-manager managed windows, xwl_realize_window is only called for
    the window-manager's decoration window and not for the actual client window
    on which we should set the _XWAYLAND_RANDR_EMU_MONITOR_RECTS prop.
    
    Usualy this is not a problem since we walk all client windows to update
    the property when the resolution is changed through a randr call.
    
    But for apps which first do the randr change and only then create their
    window this does not work, and our xwl_output_set_window_randr_emu_props
    call in xwl_realize_window is a no-op as that is only called for the wm
    decoration window and not for the actual client's window.
    
    This commit fixes this by making ensure_surface_for_window() call
    xwl_output_set_window_randr_emu_props on the first and only child of
    window-manager managed windows.
    
    Note this also removes the non-functional xwl_output_set_window_randr_emu_props
    call from xwl_realize_window, which was intended to do this, but does not
    work.
    
    This fixes apps using the ogre3d library always running at the
    monitors native resolution.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 5772d7d5b..63024ac70 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -432,6 +432,7 @@ ensure_surface_for_window(WindowPtr window)
     struct xwl_screen *xwl_screen;
     struct xwl_window *xwl_window;
     struct wl_region *region;
+    WindowPtr toplevel;
 
     if (xwl_window_get(window))
         return TRUE;
@@ -504,7 +505,14 @@ ensure_surface_for_window(WindowPtr window)
 
     xwl_window_init_allow_commits(xwl_window);
 
-    if (!window_is_wm_window(window)) {
+    /* When a new window-manager window is realized, then the randr emulation
+     * props may have not been set on the managed client window yet.
+     */
+    if (window_is_wm_window(window)) {
+        toplevel = window_get_client_toplevel(window);
+        if (toplevel)
+            xwl_output_set_window_randr_emu_props(xwl_screen, toplevel);
+    } else {
         /* CSD or O-R toplevel window, check viewport on creation */
         xwl_window_check_resolution_change_emulation(xwl_window);
     }
@@ -553,8 +561,6 @@ xwl_realize_window(WindowPtr window)
             return FALSE;
     }
 
-    xwl_output_set_window_randr_emu_props(xwl_screen, window);
-
     return ensure_surface_for_window(window);
 }
 
commit 4cfc2677f5c82ca5db0919de549b9b077f1ba113
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Nov 4 11:46:49 2019 +0100

    xwayland: Call xwl_window_check_resolution_change_emulation() on newly created O-R windows
    
    Some clients, which use vidmode to change the resolution when going fullscreen,
    create an override-redirect window and never trigger the screen->ResizeWindow
    callback we rely on to do the xwl_window_check_resolution_change_emulation().
    
    This causes us to not apply a viewport to them, causing the fullscreen window
    to not fill the entire monitor.
    
    This commit adds a call to xwl_window_check_resolution_change_emulation()
    at the end of ensure_surface_for_window() to fix this. Note that
    ensure_surface_for_window() exits early without creating an xwl_window
    for new windows which will not be backed by a wayland surface and which
    thus will not have an xwl_window.
    
    This fixes ClanLib-0.6.x and alleggl-4.4.x using apps not properly
    fullscreening.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 085d26cbe..5772d7d5b 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -504,6 +504,11 @@ ensure_surface_for_window(WindowPtr window)
 
     xwl_window_init_allow_commits(xwl_window);
 
+    if (!window_is_wm_window(window)) {
+        /* CSD or O-R toplevel window, check viewport on creation */
+        xwl_window_check_resolution_change_emulation(xwl_window);
+    }
+
     return TRUE;
 
 err_surf:
commit 88342353de45e64f408c38bb10cd1506ba0f159a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Oct 7 14:27:49 2019 +0200

    xwayland: Fix emulated modes not being removed when screen rotation is used
    
    The code building the mode-list does the following to deal with screen
    rotation:
    
        if (need_rotate || xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
            mode_width = xwl_output->width;
            mode_height = xwl_output->height;
        } else {
            mode_width = xwl_output->height;
            mode_height = xwl_output->width;
        }
    
    This means we need to do something similar in xwl_output_set_emulated_mode()
    to determine if the mode being set is the actual (not-emulated) output mode
    and we this should remove any emulated modes set by the client.
    
    All callers of xwl_output_set_emulated_mode always pass a mode pointer
    to a member of xwl_output->randr_output->modes, so we do not need to
    duplicate this code, instead we can simply check that the passed in mode
    is modes[0] which always is the actual output mode.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index fab47fe35..933f8f63b 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -313,8 +313,11 @@ xwl_output_remove_emulated_mode_for_client(struct xwl_output *xwl_output,
     struct xwl_emulated_mode *emulated_mode;
 
     emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client);
-    if (emulated_mode)
+    if (emulated_mode) {
+        DebugF("XWAYLAND: xwl_output_remove_emulated_mode: %dx%d\n",
+               emulated_mode->width, emulated_mode->height);
         memset(emulated_mode, 0, sizeof(*emulated_mode));
+    }
 }
 
 /* From hw/xfree86/common/xf86DefModeSet.c with some obscure modes dropped */
@@ -515,7 +518,8 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
            from_vidmode ? "vidmode" : "randr",
            mode->mode.width, mode->mode.height);
 
-    if (mode->mode.width == xwl_output->width && mode->mode.height == xwl_output->height)
+    /* modes[0] is the actual (not-emulated) output mode */
+    if (mode == xwl_output->randr_output->modes[0])
         xwl_output_remove_emulated_mode_for_client(xwl_output, client);
     else
         xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode);
commit 10df0437a2b142e61c4d84ffffa9592ac6846ef1
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Jan 9 11:00:36 2020 +0100

    xwayland: Also hook screen's MoveWindow method
    
    Not only hook the ResizeWindow method of the screen (which really is
    MoveAndResize) but also hook the MoveWindow method for checking if we
    need to setup a viewport for resolution change emulation.
    
    Our resolution change emulation check if the windows origin matches
    the monitors origin and the windows origin can also be changed by just
    a move without being resized.
    
    Also checking on a move becomes esp. important when we move to checking
    on changes to the top-level non-window-manager client (X11)Window instead
    of on changes to the xwl_window later on in this patch series.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 91de40c2d..551efb9f0 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -644,6 +644,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
     xwl_screen->ResizeWindow = pScreen->ResizeWindow;
     pScreen->ResizeWindow = xwl_resize_window;
 
+    xwl_screen->MoveWindow = pScreen->MoveWindow;
+    pScreen->MoveWindow = xwl_move_window;
+
     if (xwl_screen->rootless) {
         xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
         pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index fb87ddb30..abfbc9f1b 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -65,6 +65,7 @@ struct xwl_screen {
     SetWindowPixmapProcPtr SetWindowPixmap;
     ChangeWindowAttributesProcPtr ChangeWindowAttributes;
     ResizeWindowProcPtr ResizeWindow;
+    MoveWindowProcPtr MoveWindow;
 
     struct xorg_list output_list;
     struct xorg_list seat_list;
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 4dc6f2486..085d26cbe 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -693,6 +693,28 @@ xwl_resize_window(WindowPtr window,
         xwl_window_check_resolution_change_emulation(xwl_window);
 }
 
+void
+xwl_move_window(WindowPtr window,
+                int x, int y,
+                WindowPtr next_sib,
+                VTKind kind)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen;
+    struct xwl_window *xwl_window;
+
+    xwl_screen = xwl_screen_get(screen);
+    xwl_window = xwl_window_from_window(window);
+
+    screen->MoveWindow = xwl_screen->MoveWindow;
+    (*screen->MoveWindow) (window, x, y, next_sib, kind);
+    xwl_screen->MoveWindow = screen->MoveWindow;
+    screen->MoveWindow = xwl_move_window;
+
+    if (xwl_window && (xwl_window_get(window) || xwl_window_is_toplevel(window)))
+        xwl_window_check_resolution_change_emulation(xwl_window);
+}
+
 static void
 frame_callback(void *data,
                struct wl_callback *callback,
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index 550edb28c..86292e930 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -33,6 +33,7 @@
 #include <X11/X.h>
 #include <dix.h>
 #include <propertyst.h>
+#include <validate.h>
 
 #include "xwayland-types.h"
 
@@ -73,6 +74,10 @@ void xwl_resize_window(WindowPtr window,
                        int x, int y,
                        unsigned int width, unsigned int height,
                        WindowPtr sib);
+void xwl_move_window(WindowPtr window,
+                     int x, int y,
+                     WindowPtr next_sib,
+                     VTKind kind);
 Bool xwl_destroy_window(WindowPtr window);
 void xwl_window_post_damage(struct xwl_window *xwl_window);
 void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
commit 4fc107460a349a1a46f0e5251e6fd2a31f4c0428
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jan 15 14:36:45 2020 +0100

    xwayland: Also check resolution-change-emulation when the xwl_window itself moves
    
    The recent change to use the top-level non-window-manager Window drawable
    coordinates from xwl_window_check_resolution_change_emulation() in
    combination with only calling it on a resize when the top-level window
    is moved breaks things with mutter/gnome-shell.
    
    When fullscreening a X11 window, mutter moves its window-decoration Window
    wrapping the top-level Window to the monitor's origin coordinates (e.g. 0x0)
    last. This updates the top-level's drawable coordinates, but as the
    actual MoveWindow is called on the wrapper Window and not on the toplevel
    we do not call xwl_window_check_resolution_change_emulation() and we never
    enable the viewport.
    
    This commit fixes this by also calling
    xwl_window_check_resolution_change_emulation() if the Window being moved
    is an xwl_window itself.
    
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index d787637e8..4dc6f2486 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -689,7 +689,7 @@ xwl_resize_window(WindowPtr window,
     xwl_screen->ResizeWindow = screen->ResizeWindow;
     screen->ResizeWindow = xwl_resize_window;
 
-    if (xwl_window && xwl_window_is_toplevel(window))
+    if (xwl_window && (xwl_window_get(window) || xwl_window_is_toplevel(window)))
         xwl_window_check_resolution_change_emulation(xwl_window);
 }
 
commit 6d98f840da6dfcf2a69e03a1b3fa0bf602ba1f27
Author: Roman Gilg <subdiff at gmail.com>
Date:   Fri Jan 3 17:55:28 2020 +0100

    xwayland: Check emulation on client toplevel resize
    
    When a reparented window is resized directly check the emulation instead of
    doing this only when the window manager parent window is resized, what might
    never happen.
    
    For that to work we need to make sure that we compare the current size of the
    client toplevel when looking for an emulated mode.
    
    Changes by Hans de Goede:
    - Remove xwl_window x, y, width and height members as those are no longer used.
    - Add check for xwl_window_from_window() returning NULL.
    
    Signed-off-by: Roman Gilg <subdiff at gmail.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index f2d5891ca..d787637e8 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -276,6 +276,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
     struct xwl_output *xwl_output;
     ClientPtr owner;
     WindowPtr window;
+    DrawablePtr drawable;
 
     if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
         return FALSE;
@@ -285,6 +286,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
         return FALSE;
 
     owner = wClient(window);
+    drawable = &window->drawable;
 
     /* 1. Test if the window matches the emulated mode on one of the outputs
      * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE)
@@ -294,10 +296,10 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
         if (!emulated_mode)
             continue;
 
-        if (xwl_window->x == xwl_output->x &&
-            xwl_window->y == xwl_output->y &&
-            xwl_window->width  == emulated_mode->width &&
-            xwl_window->height == emulated_mode->height) {
+        if (drawable->x == xwl_output->x &&
+            drawable->y == xwl_output->y &&
+            drawable->width  == emulated_mode->width &&
+            drawable->height == emulated_mode->height) {
 
             *emulated_mode_ret = emulated_mode;
             *xwl_output_ret = xwl_output;
@@ -313,9 +315,9 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
     emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
     if (xwl_output && xwl_window->window->overrideRedirect &&
         emulated_mode && emulated_mode->from_vidmode &&
-        xwl_window->x == 0 && xwl_window->y == 0 &&
-        xwl_window->width  == xwl_screen->width &&
-        xwl_window->height == xwl_screen->height) {
+        drawable->x == 0 && drawable->y == 0 &&
+        drawable->width  == xwl_screen->width &&
+        drawable->height == xwl_screen->height) {
 
         *emulated_mode_ret = emulated_mode;
         *xwl_output_ret = xwl_output;
@@ -451,8 +453,6 @@ ensure_surface_for_window(WindowPtr window)
 
     xwl_window->xwl_screen = xwl_screen;
     xwl_window->window = window;
-    xwl_window->width = window->drawable.width;
-    xwl_window->height = window->drawable.height;
     xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
     if (xwl_window->surface == NULL) {
         ErrorF("wl_display_create_surface failed\n");
@@ -682,20 +682,15 @@ xwl_resize_window(WindowPtr window,
     struct xwl_window *xwl_window;
 
     xwl_screen = xwl_screen_get(screen);
-    xwl_window = xwl_window_get(window);
+    xwl_window = xwl_window_from_window(window);
 
     screen->ResizeWindow = xwl_screen->ResizeWindow;
     (*screen->ResizeWindow) (window, x, y, width, height, sib);
     xwl_screen->ResizeWindow = screen->ResizeWindow;
     screen->ResizeWindow = xwl_resize_window;
 
-    if (xwl_window) {
-        xwl_window->x = x;
-        xwl_window->y = y;
-        xwl_window->width = width;
-        xwl_window->height = height;
+    if (xwl_window && xwl_window_is_toplevel(window))
         xwl_window_check_resolution_change_emulation(xwl_window);
-    }
 }
 
 static void
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index 526e08fb7..550edb28c 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -40,7 +40,6 @@ struct xwl_window {
     struct xwl_screen *xwl_screen;
     struct wl_surface *surface;
     struct wp_viewport *viewport;
-    int32_t x, y, width, height;
     float scale_x, scale_y;
     struct wl_shell_surface *shell_surface;
     WindowPtr window;
commit 060f10062eb1761515b762b46cba56c7a53db72c
Author: Roman Gilg <subdiff at gmail.com>
Date:   Wed Jan 15 10:07:58 2020 +0100

    xwayland: Make window_get_none_wm_owner return a Window instead of a Client
    
    Make window_get_none_wm_owner return the first non-wm-window instead of the
    owner (client) of the first non-wm-window and rename it to
    window_get_client_toplevel to match its new behavior.
    
    This is a preparation patch for switching to using the drawable coordinates
    in xwl_window_should_enable_viewport()
    
    Changes by Hans de Goede:
    - Split this change out into a separate patch for easier reviewing
    - Rename window_get_none_wm_owner to window_get_client_toplevel to match
      its new behavior
    
    Signed-off-by: Roman Gilg <subdiff at gmail.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 805f2a214..f2d5891ca 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -246,10 +246,10 @@ window_is_wm_window(WindowPtr window)
     return CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id;
 }
 
-static ClientPtr
-window_get_none_wm_owner(WindowPtr window)
+static WindowPtr
+window_get_client_toplevel(WindowPtr window)
 {
-    ClientPtr client = wClient(window);
+    assert(window);
 
     /* If the toplevel window is owned by the window-manager, then the
      * actual client toplevel window has been reparented to some window-manager
@@ -258,12 +258,12 @@ window_get_none_wm_owner(WindowPtr window)
      */
     if (window_is_wm_window(window)) {
         if (window->firstChild && window->firstChild == window->lastChild)
-            return window_get_none_wm_owner(window->firstChild);
+            return window_get_client_toplevel(window->firstChild);
         else
             return NULL; /* Should never happen, skip resolution emulation */
     }
 
-    return client;
+    return window;
 }
 
 static Bool
@@ -275,14 +275,17 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
     struct xwl_emulated_mode *emulated_mode;
     struct xwl_output *xwl_output;
     ClientPtr owner;
+    WindowPtr window;
 
     if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
         return FALSE;
 
-    owner = window_get_none_wm_owner(xwl_window->window);
-    if (!owner)
+    window = window_get_client_toplevel(xwl_window->window);
+    if (!window)
         return FALSE;
 
+    owner = wClient(window);
+
     /* 1. Test if the window matches the emulated mode on one of the outputs
      * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE)
      */
commit a69f7fbb54efc8ffad320c8afd23cb41fc9edc27
Author: Roman Gilg <subdiff at gmail.com>
Date:   Fri Jan 3 17:27:28 2020 +0100

    xwayland: Recurse on finding the none-wm owner
    
    An X11 window manager might add a chain of parent windows when reparenting to a
    decoration window.
    
    That is for example the case for KWin, which reparents client windows to one
    decoration and another wrapper parent window.
    
    Account for that by a recursion into the tree. For now assume as before that
    all X11 window managers reparent with one child only for these parent windows.
    
    Changes by Hans de Goede:
    - Move the xwl_window_is_toplevel() from a later patch in this series here
      as it really belongs together with these changes
    - Drop no longer necessary xwl_window argument from window_get_none_wm_owner
      parameters
    
    Signed-off-by: Roman Gilg <subdiff at gmail.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 787e863b1..805f2a214 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -247,19 +247,18 @@ window_is_wm_window(WindowPtr window)
 }
 
 static ClientPtr
-xwl_window_get_owner(struct xwl_window *xwl_window)
+window_get_none_wm_owner(WindowPtr window)
 {
-    WindowPtr window = xwl_window->window;
     ClientPtr client = wClient(window);
 
     /* If the toplevel window is owned by the window-manager, then the
-     * actual client toplevel window has been reparented to a window-manager
-     * decoration window. In that case return the client of the
-     * first *and only* child of the toplevel (decoration) window.
+     * actual client toplevel window has been reparented to some window-manager
+     * decoration/wrapper windows. In that case recurse by checking the client
+     * of the first *and only* child of the decoration/wrapper window.
      */
     if (window_is_wm_window(window)) {
         if (window->firstChild && window->firstChild == window->lastChild)
-            return wClient(window->firstChild);
+            return window_get_none_wm_owner(window->firstChild);
         else
             return NULL; /* Should never happen, skip resolution emulation */
     }
@@ -280,7 +279,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
     if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
         return FALSE;
 
-    owner = xwl_window_get_owner(xwl_window);
+    owner = window_get_none_wm_owner(xwl_window->window);
     if (!owner)
         return FALSE;
 
@@ -350,8 +349,8 @@ xwl_window_is_toplevel(WindowPtr window)
     if (window_get_damage(window))
         return TRUE;
 
-    /* Normal toplevel client windows, reparented to decoration window */
-    return (window->parent && window_get_damage(window->parent));
+    /* Normal toplevel client windows, reparented to a window-manager window */
+    return window->parent && window_is_wm_window(window->parent);
 }
 
 static void
commit 948e02872feb641a176b3af82b6ef1201c97bb16
Author: Roman Gilg <subdiff at gmail.com>
Date:   Fri Jan 3 17:12:14 2020 +0100

    xwayland: Reuse viewport instead of recreating
    
    When a viewport is already created we can reuse this object instead of
    destroying it and getting a new one for updating the source rectangle and
    destination size.
    
    Signed-off-by: Roman Gilg <subdiff at gmail.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 89106d0a3..787e863b1 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -217,17 +217,13 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window,
                            struct xwl_output *xwl_output,
                            struct xwl_emulated_mode *emulated_mode)
 {
-    /* If necessary disable old viewport to apply new settings */
-    if (xwl_window_has_viewport_enabled(xwl_window))
-        xwl_window_disable_viewport(xwl_window);
-
-    DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
-           emulated_mode->width, emulated_mode->height,
-           xwl_output->width, xwl_output->height);
-
-    xwl_window->viewport =
-        wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter,
-                                   xwl_window->surface);
+    if (!xwl_window_has_viewport_enabled(xwl_window)) {
+        DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
+               emulated_mode->width, emulated_mode->height,
+               xwl_output->width, xwl_output->height);
+        xwl_window->viewport = wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter,
+                                                          xwl_window->surface);
+    }
 
     wp_viewport_set_source(xwl_window->viewport,
                            wl_fixed_from_int(0),
commit ded89300c1dd541f59fe6e93c5c69d7fe7088244
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jan 27 11:08:00 2020 +0100

    xwayland: Cache client-id for the window-manager client
    
    Instead of iterating over all clients which are listening for events on the
    root window and checking if the client we are dealing with is the one
    listening for SubstructureRedirectMask | ResizeRedirectMask events and thus
    is the window-manager, cache the client-id of the window-manager in
    xwl_screen and use that when checking if a client is the window-manager.
    
    Note that we cache and compare the client-id rather then the ClienPtr,
    this saves reading the ClientPtr from the global clients array when doing
    the comparison.
    
    Suggested-by: Olivier Fourdan <ofourdan at redhat.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 74f27d345..91de40c2d 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -638,6 +638,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
     xwl_screen->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = xwl_close_screen;
 
+    xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
+    pScreen->ChangeWindowAttributes = xwl_change_window_attributes;
+
     xwl_screen->ResizeWindow = pScreen->ResizeWindow;
     pScreen->ResizeWindow = xwl_resize_window;
 
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 264c6b515..fb87ddb30 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -48,6 +48,7 @@ struct xwl_screen {
     int height;
     int depth;
     ScreenPtr screen;
+    int wm_client_id;
     int expecting_event;
     enum RootClipMode root_clip_mode;
 
@@ -62,6 +63,7 @@ struct xwl_screen {
     DestroyWindowProcPtr DestroyWindow;
     XYToWindowProcPtr XYToWindow;
     SetWindowPixmapProcPtr SetWindowPixmap;
+    ChangeWindowAttributesProcPtr ChangeWindowAttributes;
     ResizeWindowProcPtr ResizeWindow;
 
     struct xorg_list output_list;
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index dc12b8e21..89106d0a3 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -243,20 +243,11 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window,
 }
 
 static Bool
-xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen,
-                                    ClientPtr client)
+window_is_wm_window(WindowPtr window)
 {
-    WindowPtr root = xwl_screen->screen->root;
-    OtherClients *others;
-
-    for (others = wOtherClients(root); others; others = others->next) {
-        if (SameClient(others, client)) {
-            if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
-                return TRUE;
-        }
-    }
+    struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
 
-    return FALSE;
+    return CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id;
 }
 
 static ClientPtr
@@ -270,7 +261,7 @@ xwl_window_get_owner(struct xwl_window *xwl_window)
      * decoration window. In that case return the client of the
      * first *and only* child of the toplevel (decoration) window.
      */
-    if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) {
+    if (window_is_wm_window(window)) {
         if (window->firstChild && window->firstChild == window->lastChild)
             return wClient(window->firstChild);
         else
@@ -356,9 +347,7 @@ xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
 Bool
 xwl_window_is_toplevel(WindowPtr window)
 {
-    struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
-
-    if (xwl_screen_client_is_window_manager(xwl_screen, wClient(window)))
+    if (window_is_wm_window(window))
         return FALSE;
 
     /* CSD and override-redirect toplevel windows */
@@ -660,6 +649,30 @@ xwl_window_set_window_pixmap(WindowPtr window,
             xwl_window_buffers_recycle(xwl_window);
 }
 
+Bool
+xwl_change_window_attributes(WindowPtr window, unsigned long mask)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    OtherClients *others;
+    Bool ret;
+
+    screen->ChangeWindowAttributes = xwl_screen->ChangeWindowAttributes;
+    ret = (*screen->ChangeWindowAttributes) (window, mask);
+    xwl_screen->ChangeWindowAttributes = screen->ChangeWindowAttributes;
+    screen->ChangeWindowAttributes = xwl_change_window_attributes;
+
+    if (window != screen->root || !(mask & CWEventMask))
+        return ret;
+
+    for (others = wOtherClients(window); others; others = others->next) {
+        if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
+            xwl_screen->wm_client_id = CLIENT_ID(others->resource);
+    }
+
+    return ret;
+}
+
 void
 xwl_resize_window(WindowPtr window,
                   int x, int y,
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index 873e191f2..526e08fb7 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -69,6 +69,7 @@ void xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
 void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap);
 Bool xwl_realize_window(WindowPtr window);
 Bool xwl_unrealize_window(WindowPtr window);
+Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask);
 void xwl_resize_window(WindowPtr window,
                        int x, int y,
                        unsigned int width, unsigned int height,


More information about the xorg-commit mailing list