diff --git a/include/view.h b/include/view.h index f551f854..e26cff32 100644 --- a/include/view.h +++ b/include/view.h @@ -84,8 +84,15 @@ enum view_wants_focus { VIEW_WANTS_FOCUS_OFFER, }; +/* + * Window types are based on the NET_WM constants from X11. See: + * https://specifications.freedesktop.org/wm-spec/1.4/ar01s05.html#id-1.6.7 + * + * The enum constants are intended to match wlr_xwayland_net_wm_window_type. + * Redefining the same constants here may seem redundant, but is necessary + * to make them available even in builds with xwayland support disabled. + */ enum window_type { - /* https://specifications.freedesktop.org/wm-spec/wm-spec-1.4.html#idm45649101374512 */ NET_WM_WINDOW_TYPE_DESKTOP = 0, NET_WM_WINDOW_TYPE_DOCK, NET_WM_WINDOW_TYPE_TOOLBAR, @@ -151,7 +158,8 @@ struct view_impl { /* returns true if view reserves space at screen edge */ bool (*has_strut_partial)(struct view *self); /* returns true if view declared itself a window type */ - bool (*contains_window_type)(struct view *view, int32_t window_type); + bool (*contains_window_type)(struct view *view, + enum window_type window_type); /* returns the client pid that this view belongs to */ pid_t (*get_pid)(struct view *view); }; diff --git a/include/xwayland.h b/include/xwayland.h index 3afea406..c202d37d 100644 --- a/include/xwayland.h +++ b/include/xwayland.h @@ -4,39 +4,12 @@ #include "config.h" #if HAVE_XWAYLAND -#include -#include -#include -#include "common/macros.h" #include "view.h" struct wlr_compositor; struct wlr_output; struct wlr_output_layout; -static const char * const atom_names[] = { - "_NET_WM_WINDOW_TYPE_DESKTOP", - "_NET_WM_WINDOW_TYPE_DOCK", - "_NET_WM_WINDOW_TYPE_TOOLBAR", - "_NET_WM_WINDOW_TYPE_MENU", - "_NET_WM_WINDOW_TYPE_UTILITY", - "_NET_WM_WINDOW_TYPE_SPLASH", - "_NET_WM_WINDOW_TYPE_DIALOG", - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", - "_NET_WM_WINDOW_TYPE_POPUP_MENU", - "_NET_WM_WINDOW_TYPE_TOOLTIP", - "_NET_WM_WINDOW_TYPE_NOTIFICATION", - "_NET_WM_WINDOW_TYPE_COMBO", - "_NET_WM_WINDOW_TYPE_DND", - "_NET_WM_WINDOW_TYPE_NORMAL", -}; - -static_assert( - ARRAY_SIZE(atom_names) == WINDOW_TYPE_LEN, - "Xwayland atoms out of sync"); - -extern xcb_atom_t atoms[WINDOW_TYPE_LEN]; - struct xwayland_unmanaged { struct server *server; struct wlr_xwayland_surface *xwayland_surface; diff --git a/src/xdg.c b/src/xdg.c index cebc5e39..656ee139 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -60,7 +60,8 @@ xdg_toplevel_view_get_size_hints(struct view *view) } static bool -xdg_toplevel_view_contains_window_type(struct view *view, int32_t window_type) +xdg_toplevel_view_contains_window_type(struct view *view, + enum window_type window_type) { assert(view); diff --git a/src/xwayland.c b/src/xwayland.c index c64dd3e8..ba386809 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -3,7 +3,6 @@ #include #include #include -#include "common/array.h" #include "common/macros.h" #include "common/mem.h" #include "config/rcxml.h" @@ -18,29 +17,49 @@ #include "workspaces.h" #include "xwayland.h" -xcb_atom_t atoms[WINDOW_TYPE_LEN] = {0}; - static void xwayland_view_unmap(struct view *view, bool client_request); static bool -xwayland_surface_contains_window_type( - struct wlr_xwayland_surface *surface, enum window_type window_type) +xwayland_view_contains_window_type(struct view *view, + enum window_type window_type) { - assert(surface); - for (size_t i = 0; i < surface->window_type_len; i++) { - if (surface->window_type[i] == atoms[window_type]) { - return true; - } - } - return false; -} + /* Compile-time check that the enum types match */ + static_assert(NET_WM_WINDOW_TYPE_DESKTOP == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DESKTOP + && NET_WM_WINDOW_TYPE_DOCK == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DOCK + && NET_WM_WINDOW_TYPE_TOOLBAR == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR + && NET_WM_WINDOW_TYPE_MENU == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_MENU + && NET_WM_WINDOW_TYPE_UTILITY == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY + && NET_WM_WINDOW_TYPE_SPLASH == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH + && NET_WM_WINDOW_TYPE_DIALOG == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG + && NET_WM_WINDOW_TYPE_DROPDOWN_MENU == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DROPDOWN_MENU + && NET_WM_WINDOW_TYPE_POPUP_MENU == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_POPUP_MENU + && NET_WM_WINDOW_TYPE_TOOLTIP == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLTIP + && NET_WM_WINDOW_TYPE_NOTIFICATION == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NOTIFICATION + && NET_WM_WINDOW_TYPE_COMBO == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_COMBO + && NET_WM_WINDOW_TYPE_DND == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DND + && NET_WM_WINDOW_TYPE_NORMAL == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NORMAL + && WINDOW_TYPE_LEN == + (int)WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NORMAL + 1, + "enum window_type does not match wlr_xwayland_net_wm_window_type"); -static bool -xwayland_view_contains_window_type(struct view *view, int32_t window_type) -{ assert(view); struct wlr_xwayland_surface *surface = xwayland_surface_from_view(view); - return xwayland_surface_contains_window_type(surface, window_type); + return wlr_xwayland_surface_has_window_type(surface, + (enum wlr_xwayland_net_wm_window_type)window_type); } static struct view_size_hints @@ -102,10 +121,10 @@ xwayland_view_wants_focus(struct view *view) * Alt-Tab switcher and be automatically focused when * they become topmost. */ - return (xwayland_surface_contains_window_type(xsurface, - NET_WM_WINDOW_TYPE_NORMAL) - || xwayland_surface_contains_window_type(xsurface, - NET_WM_WINDOW_TYPE_DIALOG)) ? + return (wlr_xwayland_surface_has_window_type(xsurface, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NORMAL) + || wlr_xwayland_surface_has_window_type(xsurface, + WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG)) ? VIEW_WANTS_FOCUS_ALWAYS : VIEW_WANTS_FOCUS_OFFER; /* @@ -1012,59 +1031,11 @@ handle_new_surface(struct wl_listener *listener, void *data) } } -static void -sync_atoms(xcb_connection_t *xcb_conn) -{ - assert(xcb_conn); - - wlr_log(WLR_DEBUG, "Syncing X11 atoms"); - xcb_intern_atom_cookie_t cookies[WINDOW_TYPE_LEN]; - - /* First request everything and then loop over the results to reduce latency */ - for (size_t i = 0; i < WINDOW_TYPE_LEN; i++) { - cookies[i] = xcb_intern_atom(xcb_conn, 0, - strlen(atom_names[i]), atom_names[i]); - } - - for (size_t i = 0; i < WINDOW_TYPE_LEN; i++) { - xcb_generic_error_t *err = NULL; - xcb_intern_atom_reply_t *reply = - xcb_intern_atom_reply(xcb_conn, cookies[i], &err); - if (reply) { - atoms[i] = reply->atom; - wlr_log(WLR_DEBUG, "Got X11 atom for %s: %u", - atom_names[i], reply->atom); - } - if (err) { - wlr_log(WLR_INFO, "Failed to get X11 atom for %s", - atom_names[i]); - } - free(reply); - free(err); - } -} - static void handle_server_ready(struct wl_listener *listener, void *data) { /* Fire an Xwayland startup script if one (or many) can be found */ session_run_script("xinitrc"); - - xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); - if (xcb_connection_has_error(xcb_conn)) { - wlr_log(WLR_ERROR, "Failed to create xcb connection"); - - /* Just clear all existing atoms */ - for (size_t i = 0; i < WINDOW_TYPE_LEN; i++) { - atoms[i] = XCB_ATOM_NONE; - } - return; - } - - wlr_log(WLR_DEBUG, "Connected to xwayland"); - sync_atoms(xcb_conn); - wlr_log(WLR_DEBUG, "Disconnecting from xwayland"); - xcb_disconnect(xcb_conn); } static void