From 79e14f65e0a005b1ab47b294dd2368cb3d55cb33 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 24 Oct 2017 14:37:18 -0400 Subject: [PATCH] xwm: fix lists --- include/wlr/xwayland.h | 11 +++++-- xwayland/xwm.c | 73 +++++++++++++++++++++++++++++++----------- xwayland/xwm.h | 4 +-- 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 0398ff28..2cd1db92 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -25,7 +25,7 @@ struct wlr_xwayland { struct wl_event_source *sigusr1_source; struct wl_listener destroy_listener; struct wlr_xwm *xwm; - struct wl_list displayable_surfaces; + struct wl_list displayable_surfaces; // wlr_xwayland_surface::displayable_link struct { struct wl_signal new_surface; @@ -68,7 +68,14 @@ struct wlr_xwayland_surface { xcb_window_t window_id; struct wlr_xwm *xwm; uint32_t surface_id; - struct wl_list link; + + struct wl_list displayable_link; + // XXX: I think this is just a list of all the surfaces + struct wl_list new_link; + struct wl_list unpaired_link; + bool displayable; + bool unpaired; + struct wlr_surface *surface; int16_t x, y; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index f72f58b2..0839ae20 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -36,10 +36,32 @@ const char *atom_map[ATOM_LAST] = { /* General helpers */ // TODO: replace this with hash table? -static struct wlr_xwayland_surface *lookup_surface(struct wl_list *list, +static struct wlr_xwayland_surface *lookup_surface(struct wlr_xwm *xwm, xcb_window_t window_id) { struct wlr_xwayland_surface *surface; - wl_list_for_each(surface, list, link) { + wl_list_for_each(surface, &xwm->new_surfaces, new_link) { + if (surface->window_id == window_id) { + return surface; + } + } + return NULL; +} + +static struct wlr_xwayland_surface *lookup_displayable_surface(struct wlr_xwm *xwm, + xcb_window_t window_id) { + struct wlr_xwayland_surface *surface; + wl_list_for_each(surface, &xwm->xwayland->displayable_surfaces, displayable_link) { + if (surface->window_id == window_id) { + return surface; + } + } + return NULL; +} + +static struct wlr_xwayland_surface *lookup_unpaired_surface(struct wlr_xwm *xwm, + xcb_window_t window_id) { + struct wlr_xwayland_surface *surface; + wl_list_for_each(surface, &xwm->unpaired_surfaces, unpaired_link) { if (surface->window_id == window_id) { return surface; } @@ -50,9 +72,9 @@ static struct wlr_xwayland_surface *lookup_surface(struct wl_list *list, static struct wlr_xwayland_surface *lookup_surface_any(struct wlr_xwm *xwm, xcb_window_t window_id) { struct wlr_xwayland_surface *surface; - if ((surface = lookup_surface(&xwm->xwayland->displayable_surfaces, window_id)) || - (surface = lookup_surface(&xwm->unpaired_surfaces, window_id)) || - (surface = lookup_surface(&xwm->new_surfaces, window_id))) { + if ((surface = lookup_displayable_surface(xwm, window_id)) || + (surface = lookup_unpaired_surface(xwm, window_id)) || + (surface = lookup_surface(xwm, window_id))) { return surface; } return NULL; @@ -82,7 +104,7 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create( surface->width = width; surface->height = height; surface->override_redirect = override_redirect; - wl_list_insert(&xwm->new_surfaces, &surface->link); + wl_list_insert(&xwm->new_surfaces, &surface->new_link); surface->state = wlr_list_create(); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.request_configure); @@ -97,7 +119,19 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create( static void wlr_xwayland_surface_destroy(struct wlr_xwayland_surface *surface) { wl_signal_emit(&surface->events.destroy, surface); - wl_list_remove(&surface->link); + + wl_list_remove(&surface->new_link); + + if (surface->unpaired) { + wl_list_remove(&surface->unpaired_link); + surface->unpaired = false; + } + + if (surface->displayable) { + wl_list_remove(&surface->displayable_link); + surface->displayable = false; + } + for (size_t i = 0; i < surface->state->length; i++) { free(surface->state->items[i]); } @@ -470,9 +504,11 @@ static void map_shell_surface(struct wlr_xwm *xwm, read_surface_property(xwm, xsurface, props[i]); } - wl_list_remove(&xsurface->link); - wl_list_insert(&xwm->xwayland->displayable_surfaces, - &xsurface->link); + if (!xsurface->displayable) { + wl_list_insert(&xwm->xwayland->displayable_surfaces, + &xsurface->displayable_link); + xsurface->displayable = true; + } xsurface->surface_commit.notify = handle_surface_commit; wl_signal_add(&surface->events.commit, &xsurface->surface_commit); @@ -594,8 +630,7 @@ static void handle_client_message(struct wlr_xwm *xwm, wlr_log(L_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window); if (ev->type == xwm->atoms[WL_SURFACE_ID]) { - struct wlr_xwayland_surface *surface = lookup_surface( - &xwm->new_surfaces, ev->window); + struct wlr_xwayland_surface *surface = lookup_surface(xwm, ev->window); if (surface == NULL) { wlr_log(L_DEBUG, "client message WL_SURFACE_ID but no new window %u ?", ev->window); @@ -608,8 +643,10 @@ static void handle_client_message(struct wlr_xwm *xwm, if (resource) { map_shell_surface(xwm, surface, wl_resource_get_user_data(resource)); } else { - wl_list_remove(&surface->link); - wl_list_insert(&xwm->unpaired_surfaces, &surface->link); + if (!surface->unpaired) { + wl_list_insert(&xwm->unpaired_surfaces, &surface->unpaired_link); + surface->unpaired = true; + } } } else if (ev->type == xwm->atoms[NET_WM_STATE]) { struct wlr_xwayland_surface *surface = lookup_surface_any(xwm, @@ -687,7 +724,7 @@ static void handle_compositor_surface_create(struct wl_listener *listener, void uint32_t surface_id = wl_resource_get_id(surface->resource); struct wlr_xwayland_surface *xwayland_surface; - wl_list_for_each(xwayland_surface, &xwm->unpaired_surfaces, link) { + wl_list_for_each(xwayland_surface, &xwm->unpaired_surfaces, unpaired_link) { if (xwayland_surface->surface_id == surface_id) { map_shell_surface(xwm, xwayland_surface, surface); xcb_flush(xwm->xcb_conn); @@ -803,13 +840,13 @@ void xwm_destroy(struct wlr_xwm *xwm) { } struct wlr_xwayland_surface *surface, *tmp; wl_list_for_each_safe(surface, tmp, &xwm->xwayland->displayable_surfaces, - link) { + displayable_link) { wlr_xwayland_surface_destroy(surface); } - wl_list_for_each_safe(surface, tmp, &xwm->new_surfaces, link) { + wl_list_for_each_safe(surface, tmp, &xwm->new_surfaces, new_link) { wlr_xwayland_surface_destroy(surface); } - wl_list_for_each_safe(surface, tmp, &xwm->unpaired_surfaces, link) { + wl_list_for_each_safe(surface, tmp, &xwm->unpaired_surfaces, unpaired_link) { wlr_xwayland_surface_destroy(surface); } wl_list_remove(&xwm->compositor_surface_create.link); diff --git a/xwayland/xwm.h b/xwayland/xwm.h index b557a331..9ae084d2 100644 --- a/xwayland/xwm.h +++ b/xwayland/xwm.h @@ -44,8 +44,8 @@ struct wlr_xwm { struct wlr_xwayland_surface *focus_surface; - struct wl_list new_surfaces; - struct wl_list unpaired_surfaces; + struct wl_list new_surfaces; // wlr_xwayland_surface::new_link + struct wl_list unpaired_surfaces; // wlr_xwayland_surface::unpaired_link const xcb_query_extension_reply_t *xfixes;