From de86d65627e96cffe77f4abf11c4a0b982326ff9 Mon Sep 17 00:00:00 2001
From: Ryan Dwyer <ryandwyer1@gmail.com>
Date: Tue, 31 Jul 2018 18:41:30 +1000
Subject: Fix popups

Fixes the render and container_at order for popups.

Fixes #2210

For rendering:

* render_view_surfaces has been renamed to render_view_toplevels
* render_view_toplevels now uses output_surface_for_each_surface (which
is now public), as that function uses wlr_surface_for_each_surface which
doesn't descend into popups
* Views now have a for_each_popup iterator, which is used by the
renderer to render the focused view's popups
* When rendering a popup, toplevels (xdg subsurfaces) of that popup are
also rendered

For sending frame done, the logic has been updated to match the
rendering logic:

* send_frame_done_container no longer descends into popups
* for_each_popup is used to send frame done to the focused view's popups
and their child toplevels

For container_at:

* floating_container_at is now static, which means it had to be moved
higher in the file.
* container_at now considers popups for the focused view before checking
containers.
* tiling_container_at has been introduced, so that it doesn't call
container_at recursively (it would check popups recursively if it did)
---
 sway/tree/view.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'sway/tree/view.c')

diff --git a/sway/tree/view.c b/sway/tree/view.c
index 8f54cc11..c1207821 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -332,6 +332,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


From 7a59508da467a3b793e355e28ae67ce04633761c Mon Sep 17 00:00:00 2001
From: Ryan Dwyer <ryandwyer1@gmail.com>
Date: Tue, 31 Jul 2018 19:58:34 +1000
Subject: Close popups when changing focus

Also reverts the send frame done changes from the previous commit.
---
 include/sway/tree/view.h    |  3 +++
 sway/desktop/output.c       | 33 ++-------------------------------
 sway/desktop/xdg_shell.c    | 13 +++++++++++++
 sway/desktop/xdg_shell_v6.c | 13 +++++++++++++
 sway/input/seat.c           |  7 +++++++
 sway/tree/view.c            |  6 ++++++
 6 files changed, 44 insertions(+), 31 deletions(-)

(limited to 'sway/tree/view.c')

diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 9f6d36fe..e722ca5e 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -50,6 +50,7 @@ struct sway_view_impl {
 	void (*for_each_popup)(struct sway_view *view,
 		wlr_surface_iterator_func_t iterator, void *user_data);
 	void (*close)(struct sway_view *view);
+	void (*close_popups)(struct sway_view *view);
 	void (*destroy)(struct sway_view *view);
 };
 
@@ -248,6 +249,8 @@ void view_set_tiled(struct sway_view *view, bool tiled);
 
 void view_close(struct sway_view *view);
 
+void view_close_popups(struct sway_view *view);
+
 void view_damage_from(struct sway_view *view);
 
 /**
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 4c9d978c..66747a3f 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -312,9 +312,8 @@ static void send_frame_done_container_iterator(struct sway_container *con,
 		return;
 	}
 
-	// Toplevels only
-	output_surface_for_each_surface(data->output, con->sway_view->surface,
-		con->x, con->y, send_frame_done_iterator, data->when);
+	output_view_for_each_surface(data->output, con->sway_view,
+		send_frame_done_iterator, data->when);
 }
 
 static void send_frame_done_container(struct sway_output *output,
@@ -327,27 +326,6 @@ static void send_frame_done_container(struct sway_output *output,
 		send_frame_done_container_iterator, &data);
 }
 
-static void send_frame_done_popup_iterator(struct sway_output *output,
-		struct wlr_surface *surface, struct wlr_box *box, float rotation,
-		void *data) {
-	// Send frame done to this popup's surface
-	send_frame_done_iterator(output, surface, box, rotation, data);
-
-	// Send frame done to this popup's child toplevels
-	output_surface_for_each_surface(output, surface, box->x, box->y,
-			send_frame_done_iterator, data);
-}
-
-static void send_frame_done_popups(struct sway_output *output,
-		struct sway_view *view, struct timespec *when) {
-	struct send_frame_done_data data = {
-		.output = output,
-		.when = when,
-	};
-	output_view_for_each_popup(output, view,
-			send_frame_done_popup_iterator, &data);
-}
-
 static void send_frame_done(struct sway_output *output, struct timespec *when) {
 	if (output_has_opaque_overlay_layer_surface(output)) {
 		goto send_frame_overlay;
@@ -385,13 +363,6 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
 			&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
 	}
 
-	struct sway_seat *seat = input_manager_current_seat(input_manager);
-	struct sway_container *focus = seat_get_focus(seat);
-	if (focus && focus->type == C_VIEW) {
-		send_frame_done_popups(output, focus->sway_view, when);
-	}
-
-
 send_frame_overlay:
 	send_frame_done_layer(output,
 		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 9f94bd74..b364663d 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -197,6 +197,18 @@ static void _close(struct sway_view *view) {
 	}
 }
 
+static void close_popups_iterator(struct wlr_surface *surface,
+		int sx, int sy, void *data) {
+	struct wlr_xdg_surface *xdg_surface =
+		wlr_xdg_surface_from_wlr_surface(surface);
+	wlr_xdg_surface_send_close(xdg_surface);
+}
+
+static void close_popups(struct sway_view *view) {
+	wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface,
+			close_popups_iterator, NULL);
+}
+
 static void destroy(struct sway_view *view) {
 	struct sway_xdg_shell_view *xdg_shell_view =
 		xdg_shell_view_from_view(view);
@@ -217,6 +229,7 @@ static const struct sway_view_impl view_impl = {
 	.for_each_surface = for_each_surface,
 	.for_each_popup = for_each_popup,
 	.close = _close,
+	.close_popups = close_popups,
 	.destroy = destroy,
 };
 
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 4502c386..ffea03ad 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -194,6 +194,18 @@ static void _close(struct sway_view *view) {
 	}
 }
 
+static void close_popups_iterator(struct wlr_surface *surface,
+		int sx, int sy, void *data) {
+	struct wlr_xdg_surface_v6 *xdg_surface_v6 =
+		wlr_xdg_surface_v6_from_wlr_surface(surface);
+	wlr_xdg_surface_v6_send_close(xdg_surface_v6);
+}
+
+static void close_popups(struct sway_view *view) {
+	wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6,
+			close_popups_iterator, NULL);
+}
+
 static void destroy(struct sway_view *view) {
 	struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
 		xdg_shell_v6_view_from_view(view);
@@ -214,6 +226,7 @@ static const struct sway_view_impl view_impl = {
 	.for_each_surface = for_each_surface,
 	.for_each_popup = for_each_popup,
 	.close = _close,
+	.close_popups = close_popups,
 	.destroy = destroy,
 };
 
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 53a92989..8ed0dce2 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -737,6 +737,13 @@ void seat_set_focus_warp(struct sway_seat *seat,
 		}
 	}
 
+	// Close any popups on the old focus
+	if (last_focus && last_focus != container) {
+		if (last_focus->type == C_VIEW) {
+			view_close_popups(last_focus->sway_view);
+		}
+	}
+
 	if (last_focus) {
 		if (last_workspace) {
 			ipc_event_workspace(last_workspace, container, "focus");
diff --git a/sway/tree/view.c b/sway/tree/view.c
index c1207821..5d9b625f 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -302,6 +302,12 @@ void view_close(struct sway_view *view) {
 	}
 }
 
+void view_close_popups(struct sway_view *view) {
+	if (view->impl->close_popups) {
+		view->impl->close_popups(view);
+	}
+}
+
 void view_damage_from(struct sway_view *view) {
 	for (int i = 0; i < root_container.children->length; ++i) {
 		struct sway_container *cont = root_container.children->items[i];
-- 
cgit v1.2.3