xwayland/xwm: handle deleted properties

X11 clients might delete window properties. In that case, reset
our state to the initial value.
This commit is contained in:
Simon Ser 2025-03-05 22:34:41 +01:00
parent e752e3ec06
commit 5175b6e94e

View file

@ -644,8 +644,8 @@ static void xwayland_surface_destroy(struct wlr_xwayland_surface *xsurface) {
static void read_surface_class(struct wlr_xwm *xwm, static void read_surface_class(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_STRING && if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] &&
reply->type != xwm->atoms[UTF8_STRING]) { reply->type != XCB_ATOM_NONE) {
return; return;
} }
@ -674,8 +674,8 @@ static void read_surface_class(struct wlr_xwm *xwm,
static void read_surface_startup_id(struct wlr_xwm *xwm, static void read_surface_startup_id(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_STRING && if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] &&
reply->type != xwm->atoms[UTF8_STRING]) { reply->type != XCB_ATOM_NONE) {
return; return;
} }
@ -713,8 +713,8 @@ static void read_surface_opacity(struct wlr_xwm *xwm,
static void read_surface_role(struct wlr_xwm *xwm, static void read_surface_role(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_STRING && if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] &&
reply->type != xwm->atoms[UTF8_STRING]) { reply->type != XCB_ATOM_NONE) {
return; return;
} }
@ -734,13 +734,13 @@ static void read_surface_role(struct wlr_xwm *xwm,
static void read_surface_title(struct wlr_xwm *xwm, static void read_surface_title(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_STRING && if (reply->type != XCB_ATOM_STRING && reply->type != xwm->atoms[UTF8_STRING] &&
reply->type != xwm->atoms[UTF8_STRING]) { reply->type != XCB_ATOM_NONE) {
return; return;
} }
bool is_utf8 = reply->type == xwm->atoms[UTF8_STRING]; 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; return;
} }
@ -774,13 +774,13 @@ static bool has_parent(struct wlr_xwayland_surface *parent,
static void read_surface_parent(struct wlr_xwm *xwm, static void read_surface_parent(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
struct wlr_xwayland_surface *found_parent = NULL; if (reply->type != XCB_ATOM_WINDOW && reply->type != XCB_ATOM_NONE) {
if (reply->type != XCB_ATOM_WINDOW) {
return; return;
} }
struct wlr_xwayland_surface *found_parent = NULL;
xcb_window_t *xid = xcb_get_property_value(reply); 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); found_parent = lookup_surface(xwm, *xid);
if (!has_parent(found_parent, xsurface)) { if (!has_parent(found_parent, xsurface)) {
xsurface->parent = found_parent; xsurface->parent = found_parent;
@ -792,7 +792,6 @@ static void read_surface_parent(struct wlr_xwm *xwm,
xsurface->parent = NULL; xsurface->parent = NULL;
} }
wl_list_remove(&xsurface->parent_link); wl_list_remove(&xsurface->parent_link);
if (xsurface->parent != NULL) { if (xsurface->parent != NULL) {
wl_list_insert(&xsurface->parent->children, &xsurface->parent_link); 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, static void read_surface_window_type(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_ATOM) { if (reply->type != XCB_ATOM_ATOM && reply->type != XCB_ATOM_NONE) {
return; 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; size_t atoms_size = sizeof(xcb_atom_t) * atoms_len;
free(xsurface->window_type); free(xsurface->window_type);
xsurface->window_type = malloc(atoms_size); if (atoms_len > 0) {
if (xsurface->window_type == NULL) { xsurface->window_type = malloc(atoms_size);
return; 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; xsurface->window_type_len = atoms_len;
wl_signal_emit_mutable(&xsurface->events.set_window_type, NULL); 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, static void read_surface_protocols(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
if (reply->type != XCB_ATOM_ATOM) { if (reply->type != XCB_ATOM_ATOM && reply->type != XCB_ATOM_NONE) {
return; return;
} }
@ -837,11 +840,15 @@ static void read_surface_protocols(struct wlr_xwm *xwm,
size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; size_t atoms_size = sizeof(xcb_atom_t) * atoms_len;
free(xsurface->protocols); free(xsurface->protocols);
xsurface->protocols = malloc(atoms_size); if (atoms_len > 0) {
if (xsurface->protocols == NULL) { xsurface->protocols = malloc(atoms_size);
return; 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; xsurface->protocols_len = atoms_len;
} }
@ -850,21 +857,26 @@ static void read_surface_hints(struct wlr_xwm *xwm,
xcb_get_property_reply_t *reply) { xcb_get_property_reply_t *reply) {
// According to the docs, reply->type == xwm->atoms[WM_HINTS] // According to the docs, reply->type == xwm->atoms[WM_HINTS]
// In practice, reply->type == XCB_ATOM_ATOM // 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; return;
} }
free(xsurface->hints); free(xsurface->hints);
xsurface->hints = calloc(1, sizeof(*xsurface->hints)); if (reply->value_len > 0) {
if (xsurface->hints == NULL) { xsurface->hints = calloc(1, sizeof(*xsurface->hints));
return; if (xsurface->hints == NULL) {
} return;
xcb_icccm_get_wm_hints_from_reply(xsurface->hints, reply); }
xcb_icccm_get_wm_hints_from_reply(xsurface->hints, reply);
if (!(xsurface->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) { if (!(xsurface->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) {
// The client didn't specify whether it wants input. // The client didn't specify whether it wants input.
// Assume it does. // Assume it does.
xsurface->hints->input = true; xsurface->hints->input = true;
}
} else {
xsurface->hints = NULL;
} }
wl_signal_emit_mutable(&xsurface->events.set_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, static void read_surface_normal_hints(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { 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; return;
} }
free(xsurface->size_hints); free(xsurface->size_hints);
xsurface->size_hints = NULL;
if (reply->value_len == 0) {
return;
}
xsurface->size_hints = calloc(1, sizeof(*xsurface->size_hints)); xsurface->size_hints = calloc(1, sizeof(*xsurface->size_hints));
if (xsurface->size_hints == NULL) { if (xsurface->size_hints == NULL) {
return; 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, static void read_surface_motif_hints(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { 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) { if (reply->value_len < 5) {
return; 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, static void read_surface_strut_partial(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface, struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) { 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 || if (reply->type != XCB_ATOM_CARDINAL || reply->format != 32 ||
xcb_get_property_value_length(reply) != xcb_get_property_value_length(reply) !=
sizeof(xcb_ewmh_wm_strut_partial_t)) { sizeof(xcb_ewmh_wm_strut_partial_t)) {
return; return;
} }
free(xsurface->strut_partial);
xsurface->strut_partial = calloc(1, sizeof(*xsurface->strut_partial)); xsurface->strut_partial = calloc(1, sizeof(*xsurface->strut_partial));
if (xsurface->strut_partial == NULL) { if (xsurface->strut_partial == NULL) {
return; return;