From 8392eae40f17e550338b8b7058d8e9c1a6ad4f78 Mon Sep 17 00:00:00 2001
From: Ryan Dwyer <ryandwyer1@gmail.com>
Date: Thu, 2 Aug 2018 23:30:26 +1000
Subject: Revert "Revert "Fix popups""

This reverts commit 9aa258d33a9baa42895214da7e82f4568fcb8f76.

Reverting the revert, so that popups can be fixed.
---
 sway/tree/container.c | 134 ++++++++++++++++++++++++++++++++++++--------------
 sway/tree/view.c      |  10 ++++
 2 files changed, 106 insertions(+), 38 deletions(-)

(limited to 'sway/tree')

diff --git a/sway/tree/container.c b/sway/tree/container.c
index b6ff4d30..b980c5e9 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -569,10 +569,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc,
 		*sx = _sx;
 		*sy = _sy;
 		*surface = _surface;
+		return swayc;
 	}
-	return swayc;
+	return NULL;
 }
 
+static struct sway_container *tiling_container_at(
+		struct sway_container *con, double lx, double ly,
+		struct wlr_surface **surface, double *sx, double *sy);
+
 /**
  * container_at for a container with layout L_TABBED.
  */
@@ -599,7 +604,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent,
 	// Surfaces
 	struct sway_container *current = seat_get_active_child(seat, parent);
 
-	return container_at(current, lx, ly, surface, sx, sy);
+	return tiling_container_at(current, lx, ly, surface, sx, sy);
 }
 
 /**
@@ -624,7 +629,7 @@ static struct sway_container *container_at_stacked(
 	// Surfaces
 	struct sway_container *current = seat_get_active_child(seat, parent);
 
-	return container_at(current, lx, ly, surface, sx, sy);
+	return tiling_container_at(current, lx, ly, surface, sx, sy);
 }
 
 /**
@@ -642,45 +647,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
 			.height = child->height,
 		};
 		if (wlr_box_contains_point(&box, lx, ly)) {
-			return container_at(child, lx, ly, surface, sx, sy);
+			return tiling_container_at(child, lx, ly, surface, sx, sy);
 		}
 	}
 	return NULL;
 }
 
-struct sway_container *container_at(struct sway_container *parent,
-		double lx, double ly,
-		struct wlr_surface **surface, double *sx, double *sy) {
-	if (!sway_assert(parent->type >= C_WORKSPACE,
-				"Expected workspace or deeper")) {
-		return NULL;
-	}
-	if (parent->type == C_VIEW) {
-		return container_at_view(parent, lx, ly, surface, sx, sy);
-	}
-	if (!parent->children->length) {
-		return NULL;
-	}
-
-	switch (parent->layout) {
-	case L_HORIZ:
-	case L_VERT:
-		return container_at_linear(parent, lx, ly, surface, sx, sy);
-	case L_TABBED:
-		return container_at_tabbed(parent, lx, ly, surface, sx, sy);
-	case L_STACKED:
-		return container_at_stacked(parent, lx, ly, surface, sx, sy);
-	case L_FLOATING:
-		sway_assert(false, "Didn't expect to see floating here");
-		return NULL;
-	case L_NONE:
-		return NULL;
-	}
-
-	return NULL;
-}
-
-struct sway_container *floating_container_at(double lx, double ly,
+static struct sway_container *floating_container_at(double lx, double ly,
 		struct wlr_surface **surface, double *sx, double *sy) {
 	for (int i = 0; i < root_container.children->length; ++i) {
 		struct sway_container *output = root_container.children->items[i];
@@ -702,7 +675,8 @@ struct sway_container *floating_container_at(double lx, double ly,
 					.height = floater->height,
 				};
 				if (wlr_box_contains_point(&box, lx, ly)) {
-					return container_at(floater, lx, ly, surface, sx, sy);
+					return tiling_container_at(floater, lx, ly,
+							surface, sx, sy);
 				}
 			}
 		}
@@ -710,6 +684,90 @@ struct sway_container *floating_container_at(double lx, double ly,
 	return NULL;
 }
 
+static struct sway_container *tiling_container_at(
+		struct sway_container *con, double lx, double ly,
+		struct wlr_surface **surface, double *sx, double *sy) {
+	if (con->type == C_VIEW) {
+		return container_at_view(con, lx, ly, surface, sx, sy);
+	}
+	if (!con->children->length) {
+		return NULL;
+	}
+
+	switch (con->layout) {
+	case L_HORIZ:
+	case L_VERT:
+		return container_at_linear(con, lx, ly, surface, sx, sy);
+	case L_TABBED:
+		return container_at_tabbed(con, lx, ly, surface, sx, sy);
+	case L_STACKED:
+		return container_at_stacked(con, lx, ly, surface, sx, sy);
+	case L_FLOATING:
+		sway_assert(false, "Didn't expect to see floating here");
+		return NULL;
+	case L_NONE:
+		return NULL;
+	}
+	return NULL;
+}
+
+static bool surface_is_popup(struct wlr_surface *surface) {
+	if (wlr_surface_is_xdg_surface(surface)) {
+		struct wlr_xdg_surface *xdg_surface =
+			wlr_xdg_surface_from_wlr_surface(surface);
+		while (xdg_surface) {
+			if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
+				return true;
+			}
+			xdg_surface = xdg_surface->toplevel->parent;
+		}
+		return false;
+	}
+
+	if (wlr_surface_is_xdg_surface_v6(surface)) {
+		struct wlr_xdg_surface_v6 *xdg_surface_v6 =
+			wlr_xdg_surface_v6_from_wlr_surface(surface);
+		while (xdg_surface_v6) {
+			if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
+				return true;
+			}
+			xdg_surface_v6 = xdg_surface_v6->toplevel->parent;
+		}
+		return false;
+	}
+
+	return false;
+}
+
+struct sway_container *container_at(struct sway_container *workspace,
+		double lx, double ly,
+		struct wlr_surface **surface, double *sx, double *sy) {
+	if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
+		return NULL;
+	}
+	struct sway_container *c;
+	// Focused view's popups
+	struct sway_seat *seat = input_manager_current_seat(input_manager);
+	struct sway_container *focus =
+		seat_get_focus_inactive(seat, &root_container);
+	if (focus && focus->type == C_VIEW) {
+		container_at_view(focus, lx, ly, surface, sx, sy);
+		if (*surface && surface_is_popup(*surface)) {
+			return focus;
+		}
+		*surface = NULL;
+	}
+	// Floating
+	if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
+		return c;
+	}
+	// Tiling
+	if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
+		return c;
+	}
+	return NULL;
+}
+
 void container_for_each_descendant_dfs(struct sway_container *container,
 		void (*f)(struct sway_container *container, void *data),
 		void *data) {
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 27a6a8bd..97318daa 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -339,6 +339,16 @@ void view_for_each_surface(struct sway_view *view,
 	}
 }
 
+void view_for_each_popup(struct sway_view *view,
+		wlr_surface_iterator_func_t iterator, void *user_data) {
+	if (!view->surface) {
+		return;
+	}
+	if (view->impl->for_each_popup) {
+		view->impl->for_each_popup(view, iterator, user_data);
+	}
+}
+
 static void view_subsurface_create(struct sway_view *view,
 	struct wlr_subsurface *subsurface);
 
-- 
cgit v1.2.3