From 5175b6e94e9967314d9ec5269f686a38ece0a84b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 5 Mar 2025 22:34:41 +0100 Subject: [PATCH] xwayland/xwm: handle deleted properties X11 clients might delete window properties. In that case, reset our state to the initial value. --- xwayland/xwm.c | 101 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 4b085d040..5318cb1be 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -644,8 +644,8 @@ static void xwayland_surface_destroy(struct wlr_xwayland_surface *xsurface) { static void read_surface_class(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_STRING && - reply->type != xwm->atoms[UTF8_STRING]) { + if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] && + reply->type != XCB_ATOM_NONE) { return; } @@ -674,8 +674,8 @@ static void read_surface_class(struct wlr_xwm *xwm, static void read_surface_startup_id(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_STRING && - reply->type != xwm->atoms[UTF8_STRING]) { + if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] && + reply->type != XCB_ATOM_NONE) { return; } @@ -713,8 +713,8 @@ static void read_surface_opacity(struct wlr_xwm *xwm, static void read_surface_role(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_STRING && - reply->type != xwm->atoms[UTF8_STRING]) { + if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] && + reply->type != XCB_ATOM_NONE) { return; } @@ -734,13 +734,13 @@ static void read_surface_role(struct wlr_xwm *xwm, static void read_surface_title(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_STRING && - reply->type != xwm->atoms[UTF8_STRING]) { + if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] && + reply->type != XCB_ATOM_NONE) { return; } bool is_utf8 = reply->type == xwm->atoms[UTF8_STRING]; - if (!is_utf8 && xsurface->has_utf8_title) { + if (!is_utf8 && xsurface->has_utf8_title && reply->type != XCB_ATOM_NONE) { return; } @@ -774,13 +774,13 @@ static bool has_parent(struct wlr_xwayland_surface *parent, static void read_surface_parent(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - struct wlr_xwayland_surface *found_parent = NULL; - if (reply->type != XCB_ATOM_WINDOW) { + if (reply->type != XCB_ATOM_WINDOW && reply->type != XCB_ATOM_NONE) { return; } + struct wlr_xwayland_surface *found_parent = NULL; xcb_window_t *xid = xcb_get_property_value(reply); - if (xid != NULL) { + if (reply->type != XCB_ATOM_NONE && xid != NULL) { found_parent = lookup_surface(xwm, *xid); if (!has_parent(found_parent, xsurface)) { xsurface->parent = found_parent; @@ -792,7 +792,6 @@ static void read_surface_parent(struct wlr_xwm *xwm, xsurface->parent = NULL; } - wl_list_remove(&xsurface->parent_link); if (xsurface->parent != NULL) { wl_list_insert(&xsurface->parent->children, &xsurface->parent_link); @@ -806,7 +805,7 @@ static void read_surface_parent(struct wlr_xwm *xwm, static void read_surface_window_type(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_ATOM) { + if (reply->type != XCB_ATOM_ATOM && reply->type != XCB_ATOM_NONE) { return; } @@ -815,11 +814,15 @@ static void read_surface_window_type(struct wlr_xwm *xwm, size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; free(xsurface->window_type); - xsurface->window_type = malloc(atoms_size); - if (xsurface->window_type == NULL) { - return; + if (atoms_len > 0) { + xsurface->window_type = malloc(atoms_size); + if (xsurface->window_type == NULL) { + return; + } + memcpy(xsurface->window_type, atoms, atoms_size); + } else { + xsurface->window_type = NULL; } - memcpy(xsurface->window_type, atoms, atoms_size); xsurface->window_type_len = atoms_len; wl_signal_emit_mutable(&xsurface->events.set_window_type, NULL); @@ -828,7 +831,7 @@ static void read_surface_window_type(struct wlr_xwm *xwm, static void read_surface_protocols(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != XCB_ATOM_ATOM) { + if (reply->type != XCB_ATOM_ATOM && reply->type != XCB_ATOM_NONE) { return; } @@ -837,11 +840,15 @@ static void read_surface_protocols(struct wlr_xwm *xwm, size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; free(xsurface->protocols); - xsurface->protocols = malloc(atoms_size); - if (xsurface->protocols == NULL) { - return; + if (atoms_len > 0) { + xsurface->protocols = malloc(atoms_size); + if (xsurface->protocols == NULL) { + return; + } + memcpy(xsurface->protocols, atoms, atoms_size); + } else { + xsurface->protocols = NULL; } - memcpy(xsurface->protocols, atoms, atoms_size); xsurface->protocols_len = atoms_len; } @@ -850,21 +857,26 @@ static void read_surface_hints(struct wlr_xwm *xwm, xcb_get_property_reply_t *reply) { // According to the docs, reply->type == xwm->atoms[WM_HINTS] // In practice, reply->type == XCB_ATOM_ATOM - if (reply->value_len == 0) { + if (reply->type != xwm->atoms[WM_HINTS] && reply->type != XCB_ATOM_ATOM && + reply->type != XCB_ATOM_NONE) { return; } free(xsurface->hints); - xsurface->hints = calloc(1, sizeof(*xsurface->hints)); - if (xsurface->hints == NULL) { - return; - } - xcb_icccm_get_wm_hints_from_reply(xsurface->hints, reply); + if (reply->value_len > 0) { + xsurface->hints = calloc(1, sizeof(*xsurface->hints)); + if (xsurface->hints == NULL) { + return; + } + xcb_icccm_get_wm_hints_from_reply(xsurface->hints, reply); - if (!(xsurface->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) { - // The client didn't specify whether it wants input. - // Assume it does. - xsurface->hints->input = true; + if (!(xsurface->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) { + // The client didn't specify whether it wants input. + // Assume it does. + xsurface->hints->input = true; + } + } else { + xsurface->hints = NULL; } wl_signal_emit_mutable(&xsurface->events.set_hints, NULL); @@ -873,11 +885,17 @@ static void read_surface_hints(struct wlr_xwm *xwm, static void read_surface_normal_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->type != xwm->atoms[WM_SIZE_HINTS] || reply->value_len == 0) { + if (reply->type != xwm->atoms[WM_SIZE_HINTS] && reply->type != XCB_ATOM_NONE) { return; } free(xsurface->size_hints); + xsurface->size_hints = NULL; + + if (reply->value_len == 0) { + return; + } + xsurface->size_hints = calloc(1, sizeof(*xsurface->size_hints)); if (xsurface->size_hints == NULL) { return; @@ -919,6 +937,12 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { + if (reply->value_len == 0) { + xsurface->decorations = 0; + wl_signal_emit_mutable(&xsurface->events.set_decorations, NULL); + return; + } + if (reply->value_len < 5) { return; } @@ -944,13 +968,20 @@ static void read_surface_motif_hints(struct wlr_xwm *xwm, static void read_surface_strut_partial(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { + free(xsurface->strut_partial); + xsurface->strut_partial = NULL; + + if (reply->type == XCB_ATOM_NONE) { + wl_signal_emit_mutable(&xsurface->events.set_strut_partial, NULL); + return; + } + if (reply->type != XCB_ATOM_CARDINAL || reply->format != 32 || xcb_get_property_value_length(reply) != sizeof(xcb_ewmh_wm_strut_partial_t)) { return; } - free(xsurface->strut_partial); xsurface->strut_partial = calloc(1, sizeof(*xsurface->strut_partial)); if (xsurface->strut_partial == NULL) { return;