xwm: add loop detection for read_surface_parent

Implement a simple loop detection while trying to retrieve the parent
for a TRANSIENT_FOR window.

Fixes swaywm/sway#4624
This commit is contained in:
Rouven Czerwinski 2020-09-19 11:36:33 +02:00 committed by Simon Ser
parent 87836dcb55
commit 5012121d33

View file

@ -467,20 +467,41 @@ static void read_surface_title(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&xsurface->events.set_title, xsurface); wlr_signal_emit_safe(&xsurface->events.set_title, xsurface);
} }
static bool has_parent(struct wlr_xwayland_surface *parent,
struct wlr_xwayland_surface *child) {
while (parent) {
if (child == parent) {
return true;
}
parent = parent->parent;
}
return false;
}
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) { if (reply->type != XCB_ATOM_WINDOW) {
return; return;
} }
xcb_window_t *xid = xcb_get_property_value(reply); xcb_window_t *xid = xcb_get_property_value(reply);
if (xid != NULL) { if (xid != NULL) {
xsurface->parent = lookup_surface(xwm, *xid); found_parent = lookup_surface(xwm, *xid);
if (!has_parent(found_parent, xsurface)) {
xsurface->parent = found_parent;
} else {
wlr_log(WLR_INFO, "%p with %p would create a loop", xsurface,
found_parent);
}
} else { } else {
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);