From 8cedbfd448edf410a45c57addcee0e7304f11b86 Mon Sep 17 00:00:00 2001
From: Roman Gilg <subdiff@gmail.com>
Date: Fri, 3 Jan 2020 17:27:28 +0100
Subject: [PATCH xserver 16/24] 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@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit a69f7fbb54efc8ffad320c8afd23cb41fc9edc27)
---
 hw/xwayland/xwayland.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 320589dde..f42b80b90 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -580,19 +580,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 */
     }
@@ -613,7 +612,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;
 
@@ -692,8 +691,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
-- 
2.25.2

