From ded89300c1dd541f59fe6e93c5c69d7fe7088244 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Jan 2020 11:08:00 +0100 Subject: [PATCH] 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 Acked-by: Olivier Fourdan Signed-off-by: Hans de Goede --- hw/xwayland/xwayland-screen.c | 3 +++ hw/xwayland/xwayland-screen.h | 2 ++ hw/xwayland/xwayland-window.c | 45 ++++++++++++++++++++++------------- hw/xwayland/xwayland-window.h | 1 + 4 files changed, 35 insertions(+), 16 deletions(-) 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; + struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); - for (others = wOtherClients(root); others; others = others->next) { - if (SameClient(others, client)) { - if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask)) - return TRUE; - } - } - - 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,