xwayland: Add heuristic for WM windows based on reparenting

If the WM client reparents a window, mark the new parent as a WM window.

This helps with current mutter, where decoration windows are created by
a separate mutter-x11-frames client instead of the WM client. There
might be other compositors doing something similar now or in the future.

v2:
* Skip the whole unwrap-and-call-down dance in xwl_reparent_window if
  xwl_screen->ReparentWindow is NULL.

Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2069>
This commit is contained in:
Michel Dänzer 2025-09-24 12:32:22 +02:00 committed by Marge Bot
parent 66984ab8ae
commit 105b5f2402
4 changed files with 41 additions and 1 deletions

View file

@ -1152,6 +1152,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->ConfigNotify = pScreen->ConfigNotify;
pScreen->ConfigNotify = xwl_config_notify;
xwl_screen->ReparentWindow = pScreen->ReparentWindow;
pScreen->ReparentWindow = xwl_reparent_window;
xwl_screen->ResizeWindow = pScreen->ResizeWindow;
pScreen->ResizeWindow = xwl_resize_window;

View file

@ -78,6 +78,7 @@ struct xwl_screen {
XYToWindowProcPtr XYToWindow;
SetWindowPixmapProcPtr SetWindowPixmap;
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
ReparentWindowProcPtr ReparentWindow;
ResizeWindowProcPtr ResizeWindow;
MoveWindowProcPtr MoveWindow;
SourceValidateProcPtr SourceValidate;

View file

@ -68,6 +68,7 @@
#define FRACTIONAL_SCALE_DENOMINATOR 120
static DevPrivateKeyRec xwl_window_private_key;
static DevPrivateKeyRec xwl_wm_window_private_key;
static DevPrivateKeyRec xwl_damage_private_key;
static const char *xwl_surface_tag = "xwl-surface";
@ -474,8 +475,13 @@ static Bool
window_is_wm_window(WindowPtr window)
{
struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
Bool *is_wm_window;
return CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id;
if (CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id)
return TRUE;
is_wm_window = dixLookupPrivate(&window->devPrivates, &xwl_wm_window_private_key);
return *is_wm_window;
}
static WindowPtr
@ -1844,6 +1850,31 @@ xwl_config_notify(WindowPtr window,
return ret;
}
void
xwl_reparent_window(WindowPtr window, WindowPtr prior_parent)
{
ScreenPtr screen = window->drawable.pScreen;
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
WindowPtr parent = window->parent;
Bool *is_wm_window;
if (xwl_screen->ReparentWindow) {
screen->ReparentWindow = xwl_screen->ReparentWindow;
screen->ReparentWindow(window, prior_parent);
xwl_screen->ReparentWindow = screen->ReparentWindow;
screen->ReparentWindow = xwl_reparent_window;
}
if (!parent->parent ||
GetCurrentClient()->index != xwl_screen->wm_client_id)
return;
/* If the WM client reparents a window, mark the new parent as a WM window */
is_wm_window = dixLookupPrivate(&parent->devPrivates,
&xwl_wm_window_private_key);
*is_wm_window = TRUE;
}
void
xwl_resize_window(WindowPtr window,
int x, int y,
@ -2068,6 +2099,10 @@ xwl_window_init(void)
if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
return FALSE;
if (!dixRegisterPrivateKey(&xwl_wm_window_private_key, PRIVATE_WINDOW,
sizeof(Bool)))
return FALSE;
if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
return FALSE;

View file

@ -138,6 +138,7 @@ int xwl_config_notify(WindowPtr window,
int x, int y,
int width, int height, int bw,
WindowPtr sib);
void xwl_reparent_window(WindowPtr window, WindowPtr prior_parent);
void xwl_resize_window(WindowPtr window,
int x, int y,
unsigned int width, unsigned int height,