From 41e2331843686ef0b4c5b30d5e14ce59137f6c91 Mon Sep 17 00:00:00 2001 From: Consolatis <40171-Consolatis@users.noreply.gitlab.freedesktop.org> Date: Thu, 21 Nov 2024 22:49:47 +0100 Subject: [PATCH] xwm: add missing NET_WM_STATE states https://specifications.freedesktop.org/wm-spec/latest/ar01s05.html#id-1.6.8 --- include/wlr/xwayland/xwayland.h | 35 ++++++++ include/xwayland/xwm.h | 7 ++ xwayland/xwm.c | 155 +++++++++++++++++++++++++++++++- 3 files changed, 194 insertions(+), 3 deletions(-) diff --git a/include/wlr/xwayland/xwayland.h b/include/wlr/xwayland/xwayland.h index fcfa5be75..4238c1f07 100644 --- a/include/wlr/xwayland/xwayland.h +++ b/include/wlr/xwayland/xwayland.h @@ -178,6 +178,13 @@ struct wlr_xwayland_surface { bool maximized_vert, maximized_horz; bool minimized; bool withdrawn; + bool sticky; + bool shaded; + bool skip_taskbar; + bool skip_pager; + bool above; + bool below; + bool demands_attention; bool has_alpha; @@ -191,6 +198,13 @@ struct wlr_xwayland_surface { struct wl_signal request_fullscreen; struct wl_signal request_activate; struct wl_signal request_close; + struct wl_signal request_sticky; + struct wl_signal request_shaded; + struct wl_signal request_skip_taskbar; + struct wl_signal request_skip_pager; + struct wl_signal request_above; + struct wl_signal request_below; + struct wl_signal request_demands_attention; struct wl_signal associate; struct wl_signal dissociate; @@ -292,6 +306,27 @@ void wlr_xwayland_surface_set_maximized(struct wlr_xwayland_surface *surface, void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface, bool fullscreen); +void wlr_xwayland_surface_set_sticky( + struct wlr_xwayland_surface *surface, bool sticky); + +void wlr_xwayland_surface_set_shaded( + struct wlr_xwayland_surface *surface, bool shaded); + +void wlr_xwayland_surface_set_skip_taskbar( + struct wlr_xwayland_surface *surface, bool skip_taskbar); + +void wlr_xwayland_surface_set_skip_pager( + struct wlr_xwayland_surface *surface, bool skip_pager); + +void wlr_xwayland_surface_set_above( + struct wlr_xwayland_surface *surface, bool above); + +void wlr_xwayland_surface_set_below( + struct wlr_xwayland_surface *surface, bool below); + +void wlr_xwayland_surface_set_demands_attention( + struct wlr_xwayland_surface *surface, bool demands_attention); + void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, struct wlr_seat *seat); diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index dc304b567..2a31902ca 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -48,6 +48,13 @@ enum atom_name { NET_WM_STATE_MAXIMIZED_VERT, NET_WM_STATE_MAXIMIZED_HORZ, NET_WM_STATE_HIDDEN, + NET_WM_STATE_STICKY, + NET_WM_STATE_SHADED, + NET_WM_STATE_SKIP_TASKBAR, + NET_WM_STATE_SKIP_PAGER, + NET_WM_STATE_ABOVE, + NET_WM_STATE_BELOW, + NET_WM_STATE_DEMANDS_ATTENTION, NET_WM_PING, WM_CHANGE_STATE, WM_STATE, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index c651287b3..e77ad1a11 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -47,6 +47,13 @@ static const char *const atom_map[ATOM_LAST] = { [NET_WM_STATE_MAXIMIZED_VERT] = "_NET_WM_STATE_MAXIMIZED_VERT", [NET_WM_STATE_MAXIMIZED_HORZ] = "_NET_WM_STATE_MAXIMIZED_HORZ", [NET_WM_STATE_HIDDEN] = "_NET_WM_STATE_HIDDEN", + [NET_WM_STATE_STICKY] = "_NET_WM_STATE_STICKY", + [NET_WM_STATE_SHADED] = "_NET_WM_STATE_SHADED", + [NET_WM_STATE_SKIP_TASKBAR] = "_NET_WM_STATE_SKIP_TASKBAR", + [NET_WM_STATE_SKIP_PAGER] = "_NET_WM_STATE_SKIP_PAGER", + [NET_WM_STATE_ABOVE] = "_NET_WM_STATE_ABOVE", + [NET_WM_STATE_BELOW] = "_NET_WM_STATE_BELOW", + [NET_WM_STATE_DEMANDS_ATTENTION] = "_NET_WM_STATE_DEMANDS_ATTENTION", [NET_WM_PING] = "_NET_WM_PING", [WM_CHANGE_STATE] = "WM_CHANGE_STATE", [WM_STATE] = "WM_STATE", @@ -211,6 +218,13 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_signal_init(&surface->events.request_fullscreen); wl_signal_init(&surface->events.request_activate); wl_signal_init(&surface->events.request_close); + wl_signal_init(&surface->events.request_sticky); + wl_signal_init(&surface->events.request_shaded); + wl_signal_init(&surface->events.request_skip_taskbar); + wl_signal_init(&surface->events.request_skip_pager); + wl_signal_init(&surface->events.request_above); + wl_signal_init(&surface->events.request_below); + wl_signal_init(&surface->events.request_demands_attention); wl_signal_init(&surface->events.associate); wl_signal_init(&surface->events.dissociate); wl_signal_init(&surface->events.set_class); @@ -269,8 +283,7 @@ static void xwm_set_net_active_window(struct wlr_xwm *xwm, */ xcb_void_cookie_t xwm_send_event_with_size(xcb_connection_t *c, uint8_t propagate, xcb_window_t destination, - uint32_t event_mask, const void *event, uint32_t length) -{ + uint32_t event_mask, const void *event, uint32_t length) { if (length == 32) { return xcb_send_event(c, propagate, destination, event_mask, event); } else if (length < 32) { @@ -474,7 +487,7 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) { return; } - uint32_t property[6]; + uint32_t property[13]; size_t i = 0; if (xsurface->modal) { property[i++] = xwm->atoms[NET_WM_STATE_MODAL]; @@ -491,6 +504,27 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) { if (xsurface->minimized) { property[i++] = xwm->atoms[NET_WM_STATE_HIDDEN]; } + if (xsurface->sticky) { + property[i++] = xwm->atoms[NET_WM_STATE_STICKY]; + } + if (xsurface->shaded) { + property[i++] = xwm->atoms[NET_WM_STATE_SHADED]; + } + if (xsurface->skip_taskbar) { + property[i++] = xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]; + } + if (xsurface->skip_pager) { + property[i++] = xwm->atoms[NET_WM_STATE_SKIP_PAGER]; + } + if (xsurface->above) { + property[i++] = xwm->atoms[NET_WM_STATE_ABOVE]; + } + if (xsurface->below) { + property[i++] = xwm->atoms[NET_WM_STATE_BELOW]; + } + if (xsurface->demands_attention) { + property[i++] = xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]; + } if (xsurface == xwm->focus_surface) { property[i++] = xwm->atoms[NET_WM_STATE_FOCUSED]; } @@ -886,6 +920,20 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm, xsurface->maximized_horz = true; } else if (atom[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) { xsurface->minimized = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_STICKY]) { + xsurface->sticky = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SHADED]) { + xsurface->shaded = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { + xsurface->skip_taskbar = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { + xsurface->skip_pager = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_ABOVE]) { + xsurface->above = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_BELOW]) { + xsurface->below = true; + } else if (atom[i] == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { + xsurface->demands_attention = true; } } } @@ -1412,6 +1460,13 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, bool maximized_vert = xsurface->maximized_vert; bool maximized_horz = xsurface->maximized_horz; bool minimized = xsurface->minimized; + bool sticky = xsurface->sticky; + bool shaded = xsurface->shaded; + bool skip_taskbar = xsurface->skip_taskbar; + bool skip_pager = xsurface->skip_pager; + bool above = xsurface->above; + bool below = xsurface->below; + bool demands_attention = xsurface->demands_attention; uint32_t action = client_message->data.data32[0]; for (size_t i = 0; i < 2; ++i) { @@ -1428,6 +1483,20 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, changed = update_state(action, &xsurface->maximized_horz); } else if (property == xwm->atoms[NET_WM_STATE_HIDDEN]) { changed = update_state(action, &xsurface->minimized); + } else if (property == xwm->atoms[NET_WM_STATE_STICKY]) { + changed = update_state(action, &xsurface->sticky); + } else if (property == xwm->atoms[NET_WM_STATE_SHADED]) { + changed = update_state(action, &xsurface->shaded); + } else if (property == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { + changed = update_state(action, &xsurface->skip_taskbar); + } else if (property == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { + changed = update_state(action, &xsurface->skip_pager); + } else if (property == xwm->atoms[NET_WM_STATE_ABOVE]) { + changed = update_state(action, &xsurface->above); + } else if (property == xwm->atoms[NET_WM_STATE_BELOW]) { + changed = update_state(action, &xsurface->below); + } else if (property == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { + changed = update_state(action, &xsurface->demands_attention); } else if (property != XCB_ATOM_NONE && wlr_log_get_verbosity() >= WLR_DEBUG) { char *prop_name = xwm_get_atom_name(xwm, property); wlr_log(WLR_DEBUG, "Unhandled NET_WM_STATE property change " @@ -1458,6 +1527,34 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, }; wl_signal_emit_mutable(&xsurface->events.request_minimize, &minimize_event); } + + if (sticky != xsurface->sticky) { + wl_signal_emit_mutable(&xsurface->events.request_sticky, NULL); + } + + if (shaded != xsurface->shaded) { + wl_signal_emit_mutable(&xsurface->events.request_shaded, NULL); + } + + if (skip_taskbar != xsurface->skip_taskbar) { + wl_signal_emit_mutable(&xsurface->events.request_skip_taskbar, NULL); + } + + if (skip_pager != xsurface->skip_pager) { + wl_signal_emit_mutable(&xsurface->events.request_skip_pager, NULL); + } + + if (above != xsurface->above) { + wl_signal_emit_mutable(&xsurface->events.request_above, NULL); + } + + if (below != xsurface->below) { + wl_signal_emit_mutable(&xsurface->events.request_below, NULL); + } + + if (demands_attention != xsurface->demands_attention) { + wl_signal_emit_mutable(&xsurface->events.request_demands_attention, NULL); + } } static void xwm_handle_wm_protocols_message(struct wlr_xwm *xwm, @@ -2326,6 +2423,13 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT], xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ], xwm->atoms[NET_WM_STATE_HIDDEN], + xwm->atoms[NET_WM_STATE_STICKY], + xwm->atoms[NET_WM_STATE_SHADED], + xwm->atoms[NET_WM_STATE_SKIP_TASKBAR], + xwm->atoms[NET_WM_STATE_SKIP_PAGER], + xwm->atoms[NET_WM_STATE_ABOVE], + xwm->atoms[NET_WM_STATE_BELOW], + xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION], xwm->atoms[NET_CLIENT_LIST], xwm->atoms[NET_CLIENT_LIST_STACKING], }; @@ -2406,6 +2510,51 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface, xwm_schedule_flush(surface->xwm); } +void wlr_xwayland_surface_set_sticky(struct wlr_xwayland_surface *surface, bool sticky) { + surface->sticky = sticky; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_shaded(struct wlr_xwayland_surface *surface, bool shaded) { + surface->shaded = shaded; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_skip_taskbar(struct wlr_xwayland_surface *surface, + bool skip_taskbar) { + surface->skip_taskbar = skip_taskbar; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_skip_pager(struct wlr_xwayland_surface *surface, + bool skip_pager) { + surface->skip_pager = skip_pager; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_above(struct wlr_xwayland_surface *surface, bool above) { + surface->above = above; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_below(struct wlr_xwayland_surface *surface, bool below) { + surface->below = below; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + +void wlr_xwayland_surface_set_demands_attention(struct wlr_xwayland_surface *surface, + bool demands_attention) { + surface->demands_attention = demands_attention; + xsurface_set_net_wm_state(surface); + xwm_schedule_flush(surface->xwm); +} + bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms, size_t num_atoms, enum atom_name needle) { xcb_atom_t atom = xwm->atoms[needle];