From 1e7dd78cfda8ddd7c618c01973799aedcddfb72f Mon Sep 17 00:00:00 2001 Message-ID: <1e7dd78cfda8ddd7c618c01973799aedcddfb72f.1741276434.git.agx@sigxcpu.org> From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 4 Mar 2025 20:37:49 +0100 Subject: [PATCH] xwm: Handle NET_WM_WINDOW_OPACITY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lot of clients use it (e.g. both Qt and GTK) although it never made it into the spec at https://specifications.freedesktop.org/wm-spec/latest-single/ until recently https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/97 (cherry picked from commit e752e3ec06fc7c2b83079a5980218ae359b1c869) Signed-off-by: Guido Günther --- include/wlr/xwayland/xwayland.h | 2 ++ include/xwayland/xwm.h | 1 + xwayland/xwm.c | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/include/wlr/xwayland/xwayland.h b/include/wlr/xwayland/xwayland.h index 4b476a03..d0bbe993 100644 --- a/include/wlr/xwayland/xwayland.h +++ b/include/wlr/xwayland/xwayland.h @@ -119,6 +119,7 @@ struct wlr_xwayland_surface { int16_t x, y; uint16_t width, height; bool override_redirect; + float opacity; char *title; char *class; @@ -186,6 +187,7 @@ struct wlr_xwayland_surface { struct wl_signal set_strut_partial; struct wl_signal set_override_redirect; struct wl_signal set_geometry; + struct wl_signal set_opacity; /* can be used to set initial maximized/fullscreen geometry */ struct wl_signal map_request; struct wl_signal ping_timeout; diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 4386446d..43e36328 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -62,6 +62,7 @@ enum atom_name { NET_STARTUP_ID, NET_STARTUP_INFO, NET_STARTUP_INFO_BEGIN, + NET_WM_WINDOW_OPACITY, NET_WM_WINDOW_TYPE_NORMAL, NET_WM_WINDOW_TYPE_UTILITY, NET_WM_WINDOW_TYPE_TOOLTIP, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index b315fa0f..91ca596a 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -61,6 +61,7 @@ static const char *const atom_map[ATOM_LAST] = { [NET_STARTUP_ID] = "_NET_STARTUP_ID", [NET_STARTUP_INFO] = "_NET_STARTUP_INFO", [NET_STARTUP_INFO_BEGIN] = "_NET_STARTUP_INFO_BEGIN", + [NET_WM_WINDOW_OPACITY] = "_NET_WM_WINDOW_OPACITY", [NET_WM_WINDOW_TYPE_NORMAL] = "_NET_WM_WINDOW_TYPE_NORMAL", [NET_WM_WINDOW_TYPE_UTILITY] = "_NET_WM_WINDOW_TYPE_UTILITY", [NET_WM_WINDOW_TYPE_TOOLTIP] = "_NET_WM_WINDOW_TYPE_TOOLTIP", @@ -194,6 +195,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create( surface->width = width; surface->height = height; surface->override_redirect = override_redirect; + surface->opacity = 1.0; wl_list_init(&surface->children); wl_list_init(&surface->stack_link); wl_list_init(&surface->parent_link); @@ -219,6 +221,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_signal_init(&surface->events.set_strut_partial); wl_signal_init(&surface->events.set_override_redirect); wl_signal_init(&surface->events.set_geometry); + wl_signal_init(&surface->events.set_opacity); wl_signal_init(&surface->events.map_request); wl_signal_init(&surface->events.ping_timeout); @@ -485,6 +488,8 @@ static void xwayland_surface_destroy(struct wlr_xwayland_surface *xsurface) { wl_signal_emit_mutable(&xsurface->events.destroy, NULL); + assert(wl_list_empty(&xsurface->events.set_opacity.listener_list)); + if (xsurface == xsurface->xwm->focus_surface) { xwm_surface_activate(xsurface->xwm, NULL); } @@ -568,6 +573,22 @@ static void read_surface_startup_id(struct wlr_xwm *xwm, wl_signal_emit_mutable(&xsurface->events.set_startup_id, NULL); } +static void read_surface_opacity(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *xsurface, + xcb_get_property_reply_t *reply) { + if (reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && + xcb_get_property_value_length(reply) == + sizeof(uint32_t)) { + uint32_t *val = xcb_get_property_value(reply); + + xsurface->opacity = (double)*val / UINT32_MAX; + wl_signal_emit_mutable(&xsurface->events.set_opacity, NULL); + } else if (reply->type == XCB_ATOM_NONE) { + xsurface->opacity = 1.0; + wl_signal_emit_mutable(&xsurface->events.set_opacity, NULL); + } +} + static void read_surface_role(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { @@ -882,6 +903,8 @@ static void read_surface_property(struct wlr_xwm *xwm, read_surface_role(xwm, xsurface, reply); } else if (property == xwm->atoms[NET_STARTUP_ID]) { read_surface_startup_id(xwm, xsurface, reply); + } else if (property == xwm->atoms[NET_WM_WINDOW_OPACITY]) { + read_surface_opacity(xwm, xsurface, reply); } else if (wlr_log_get_verbosity() >= WLR_DEBUG) { char *prop_name = xwm_get_atom_name(xwm, property); wlr_log(WLR_DEBUG, "unhandled X11 property %" PRIu32 " (%s) for window %" PRIu32, -- 2.47.2