From 6214144735b6b85fa1e191be3afe33d6bea0faee Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 14 Feb 2024 22:54:33 -0500 Subject: [PATCH] xwayland: add wlr_xwayland_surface_has_window_type() The infrastructure to read _NET_WM_WINDOW_TYPE already exists in wlroots (it's used for example in wlr_xwayland_or_surface_wants_focus()). But the window type isn't easily accessible to the compositor because the atoms to compare against are private to xwm.c. labwc has recently gone to a fair amount of effort (including opening a whole new xcb connection) just to get the needed window type atoms: https://github.com/labwc/labwc/commit/a04b394e591163505b66706ff9ebcadb26871345 It seems much cleaner to add the remaining few (3) atoms to wlroots and implement a shared function which can be used by any wlroots compositor. v2: naming updates --- include/wlr/xwayland/xwayland.h | 29 +++++++++++++++++++++++++++++ include/xwayland/xwm.h | 3 +++ xwayland/xwm.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/include/wlr/xwayland/xwayland.h b/include/wlr/xwayland/xwayland.h index fb8bca08..c10ce4cd 100644 --- a/include/wlr/xwayland/xwayland.h +++ b/include/wlr/xwayland/xwayland.h @@ -92,6 +92,27 @@ enum wlr_xwayland_icccm_input_model { WLR_ICCCM_INPUT_MODEL_GLOBAL = 3, }; +/** + * The type of window (_NET_WM_WINDOW_TYPE). See: + * https://specifications.freedesktop.org/wm-spec/latest/ + */ +enum wlr_xwayland_net_wm_window_type { + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DESKTOP = 0, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DOCK, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_MENU, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_POPUP_MENU, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLTIP, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NOTIFICATION, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_COMBO, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DND, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NORMAL, +}; + /** * An Xwayland user interface component. It has an absolute position in * layout-local coordinates. @@ -293,6 +314,14 @@ void wlr_xwayland_surface_offer_focus(struct wlr_xwayland_surface *xsurface); void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface); +/** + * Returns true if the surface has the given window type. + * Note: a surface may have multiple window types set. + */ +bool wlr_xwayland_surface_has_window_type( + const struct wlr_xwayland_surface *xsurface, + enum wlr_xwayland_net_wm_window_type window_type); + /** Metric to guess if an OR window should "receive" focus * * In the pure X setups, window managers usually straight up ignore override diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 80d56e26..d3ecf560 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -74,6 +74,9 @@ enum atom_name { NET_WM_WINDOW_TYPE_NOTIFICATION, NET_WM_WINDOW_TYPE_SPLASH, NET_WM_WINDOW_TYPE_DESKTOP, + NET_WM_WINDOW_TYPE_DOCK, + NET_WM_WINDOW_TYPE_TOOLBAR, + NET_WM_WINDOW_TYPE_DIALOG, DND_SELECTION, DND_AWARE, DND_STATUS, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index d16185d4..6b85829d 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -73,6 +73,9 @@ static const char *const atom_map[ATOM_LAST] = { [NET_WM_WINDOW_TYPE_NOTIFICATION] = "_NET_WM_WINDOW_TYPE_NOTIFICATION", [NET_WM_WINDOW_TYPE_SPLASH] = "_NET_WM_WINDOW_TYPE_SPLASH", [NET_WM_WINDOW_TYPE_DESKTOP] = "_NET_WM_WINDOW_TYPE_DESKTOP", + [NET_WM_WINDOW_TYPE_DOCK] = "_NET_WM_WINDOW_TYPE_DOCK", + [NET_WM_WINDOW_TYPE_TOOLBAR] = "_NET_WM_WINDOW_TYPE_TOOLBAR", + [NET_WM_WINDOW_TYPE_DIALOG] = "_NET_WM_WINDOW_TYPE_DIALOG", [DND_SELECTION] = "XdndSelection", [DND_AWARE] = "XdndAware", [DND_STATUS] = "XdndStatus", @@ -2393,6 +2396,34 @@ void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { surface->pinging = true; } +bool wlr_xwayland_surface_has_window_type( + const struct wlr_xwayland_surface *xsurface, + enum wlr_xwayland_net_wm_window_type window_type) { + static const enum atom_name atom_names[] = { + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DESKTOP] = NET_WM_WINDOW_TYPE_DESKTOP, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DOCK] = NET_WM_WINDOW_TYPE_DOCK, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR] = NET_WM_WINDOW_TYPE_TOOLBAR, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_MENU] = NET_WM_WINDOW_TYPE_MENU, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY] = NET_WM_WINDOW_TYPE_UTILITY, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH] = NET_WM_WINDOW_TYPE_SPLASH, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG] = NET_WM_WINDOW_TYPE_DIALOG, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DROPDOWN_MENU] = NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_POPUP_MENU] = NET_WM_WINDOW_TYPE_POPUP_MENU, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLTIP] = NET_WM_WINDOW_TYPE_TOOLTIP, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NOTIFICATION] = NET_WM_WINDOW_TYPE_NOTIFICATION, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_COMBO] = NET_WM_WINDOW_TYPE_COMBO, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DND] = NET_WM_WINDOW_TYPE_DND, + [WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NORMAL] = NET_WM_WINDOW_TYPE_NORMAL, + }; + + if (window_type >= 0 && window_type < sizeof(atom_names) / sizeof(atom_names[0])) { + return xwm_atoms_contains(xsurface->xwm, xsurface->window_type, + xsurface->window_type_len, atom_names[window_type]); + } + + return false; +} + bool wlr_xwayland_surface_override_redirect_wants_focus( const struct wlr_xwayland_surface *xsurface) { static const enum atom_name needles[] = {