From 79e14f65e0a005b1ab47b294dd2368cb3d55cb33 Mon Sep 17 00:00:00 2001
From: Tony Crisci <tony@dubstepdish.com>
Date: Tue, 24 Oct 2017 14:37:18 -0400
Subject: 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;
 
-- 
cgit v1.2.3