xwayland: Ignore non-InputOutput children in window_get_client_toplevel

InputOnly windows aren't relevant here.

E.g. mutter-x11-frames uses GTK4, which creates a 1x1 InputOnly child
window, which previously prevented this code from working as intended.

v2: (Olivier Fourdan)
* Rename output_child -> input_output_child.
* Add comment in get_single_input_output_child explaining why we return
  NULL if input_output_child is already non-NULL.

Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2069>
This commit is contained in:
Michel Dänzer 2025-09-24 13:32:10 +02:00 committed by Marge Bot
parent 105b5f2402
commit 6f31791945

View file

@ -484,6 +484,25 @@ window_is_wm_window(WindowPtr window)
return *is_wm_window; return *is_wm_window;
} }
static WindowPtr
get_single_input_output_child(WindowPtr window)
{
WindowPtr iter, input_output_child = NULL;
for (iter = window->firstChild; iter; iter = iter->nextSib) {
if (iter->drawable.class != InputOutput)
continue;
/* We're looking for a single InputOutput child, bail if there are multiple */
if (input_output_child)
return NULL;
input_output_child = iter;
}
return input_output_child;
}
static WindowPtr static WindowPtr
window_get_client_toplevel(WindowPtr window) window_get_client_toplevel(WindowPtr window)
{ {
@ -492,14 +511,10 @@ window_get_client_toplevel(WindowPtr window)
/* If the toplevel window is owned by the window-manager, then the /* If the toplevel window is owned by the window-manager, then the
* actual client toplevel window has been reparented to some window-manager * actual client toplevel window has been reparented to some window-manager
* decoration/wrapper windows. In that case recurse by checking the client * decoration/wrapper windows. In that case recurse by checking the client
* of the first *and only* child of the decoration/wrapper window. * of the only InputOutput child of the decoration/wrapper window.
*/ */
while (window_is_wm_window(window)) { while (window && window_is_wm_window(window))
if (!window->firstChild || window->firstChild != window->lastChild) window = get_single_input_output_child(window);
return NULL; /* Should never happen, skip resolution emulation */
window = window->firstChild;
}
return window; return window;
} }