From 48bc15e758c37e73f3eb6ae76f4ad758148dbfb1 Mon Sep 17 00:00:00 2001
From: Ryan Dwyer <ryandwyer1@gmail.com>
Date: Sun, 16 Sep 2018 14:04:25 +1000
Subject: [PATCH 1/2] Make seat_get_active_child ignore floating children

seat_get_active_child is used to get the active tiling child in a few
places, such as outputs getting their active workspace and
tabbed/stacked containers getting their visible child. When a workspace
uses a tabbed or stacked layout and contains a focused floating view,
calling seat_get_active_child on the workspace would incorrectly return
the floating view. This changes it so it will return the tiling child.

This fixes the following bug:

* Create layout T[view view] then float one of the views
* Attempt to click the tiling view to give it focus - it wouldn't work
because seat_get_active_child would return the floating view
---
 sway/input/seat.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sway/input/seat.c b/sway/input/seat.c
index ab5047b2..6d02970d 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -888,9 +888,17 @@ struct sway_node *seat_get_active_child(struct sway_seat *seat,
 	struct sway_seat_node *current;
 	wl_list_for_each(current, &seat->focus_stack, link) {
 		struct sway_node *node = current->node;
-		if (node_get_parent(node) == parent) {
-			return node;
+		if (node_get_parent(node) != parent) {
+			continue;
 		}
+		if (parent->type == N_WORKSPACE) {
+			// Only consider tiling children
+			struct sway_workspace *ws = parent->sway_workspace;
+			if (list_find(ws->tiling, node->sway_container) == -1) {
+				continue;
+			}
+		}
+		return node;
 	}
 	return NULL;
 }

From f6e218a64371b02afdf6b7812a52d70b13635ef3 Mon Sep 17 00:00:00 2001
From: Ryan Dwyer <ryandwyer1@gmail.com>
Date: Sun, 16 Sep 2018 22:01:54 +1000
Subject: [PATCH 2/2] Rename seat_get_active_child to
 seat_get_active_tiling_child

Also renames container to con in one function to prevent ugly line
wrapping.
---
 include/sway/input/seat.h  |  2 +-
 sway/commands/focus.c      |  2 +-
 sway/commands/move.c       |  2 +-
 sway/desktop/output.c      |  2 +-
 sway/desktop/transaction.c |  3 ++-
 sway/input/seat.c          |  2 +-
 sway/tree/container.c      |  4 ++--
 sway/tree/view.c           | 14 +++++++-------
 8 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h
index 7b756ef3..ebb0cd43 100644
--- a/include/sway/input/seat.h
+++ b/include/sway/input/seat.h
@@ -155,7 +155,7 @@ struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat,
 /**
  * Return the immediate child of container which was most recently focused.
  */
-struct sway_node *seat_get_active_child(struct sway_seat *seat,
+struct sway_node *seat_get_active_tiling_child(struct sway_seat *seat,
 		struct sway_node *parent);
 
 /**
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index d63077e6..44adb95b 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -261,7 +261,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
 	}
 
 	if (direction == MOVE_CHILD) {
-		struct sway_node *focus = seat_get_active_child(seat, node);
+		struct sway_node *focus = seat_get_active_tiling_child(seat, node);
 		if (focus) {
 			seat_set_focus(seat, focus);
 			cursor_send_pointer_motion(seat->cursor, 0, true);
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 8f0ef230..42b305d1 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -149,7 +149,7 @@ static void container_move_to_container_from_direction(
 	}
 
 	wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)");
-	struct sway_node *focus_inactive = seat_get_active_child(
+	struct sway_node *focus_inactive = seat_get_active_tiling_child(
 			config->handler_context.seat, &destination->node);
 	if (!focus_inactive || focus_inactive == &destination->node) {
 		// The container has no children
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index a5db15cd..cfb5a710 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -232,7 +232,7 @@ static void scale_box(struct wlr_box *box, float scale) {
 
 struct sway_workspace *output_get_active_workspace(struct sway_output *output) {
 	struct sway_seat *seat = input_manager_current_seat(input_manager);
-	struct sway_node *focus = seat_get_active_child(seat, &output->node);
+	struct sway_node *focus = seat_get_active_tiling_child(seat, &output->node);
 	if (!focus) {
 		return output->workspaces->items[0];
 	}
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index b4eec933..d747e279 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -176,7 +176,8 @@ static void copy_container_state(struct sway_container *container,
 	state->focused = seat_get_focus(seat) == &container->node;
 
 	if (!container->view) {
-		struct sway_node *focus = seat_get_active_child(seat, &container->node);
+		struct sway_node *focus =
+			seat_get_active_tiling_child(seat, &container->node);
 		state->focused_inactive_child = focus ? focus->sway_container : NULL;
 	}
 }
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 6d02970d..49fe46ba 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -880,7 +880,7 @@ struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat,
 	return NULL;
 }
 
-struct sway_node *seat_get_active_child(struct sway_seat *seat,
+struct sway_node *seat_get_active_tiling_child(struct sway_seat *seat,
 		struct sway_node *parent) {
 	if (node_is_view(parent)) {
 		return parent;
diff --git a/sway/tree/container.c b/sway/tree/container.c
index f906449a..47687744 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -220,7 +220,7 @@ static struct sway_container *container_at_tabbed(struct sway_node *parent,
 	}
 
 	// Surfaces
-	struct sway_node *current = seat_get_active_child(seat, parent);
+	struct sway_node *current = seat_get_active_tiling_child(seat, parent);
 	return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL;
 }
 
@@ -248,7 +248,7 @@ static struct sway_container *container_at_stacked(struct sway_node *parent,
 	}
 
 	// Surfaces
-	struct sway_node *current = seat_get_active_child(seat, parent);
+	struct sway_node *current = seat_get_active_tiling_child(seat, parent);
 	return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL;
 }
 
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 78f85de2..e4e1c161 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -1001,17 +1001,17 @@ bool view_is_visible(struct sway_view *view) {
 	bool is_sticky = container_is_floating(floater) && floater->is_sticky;
 	// Check view isn't in a tabbed or stacked container on an inactive tab
 	struct sway_seat *seat = input_manager_current_seat(input_manager);
-	struct sway_container *container = view->container;
-	while (container) {
-		enum sway_container_layout layout = container_parent_layout(container);
+	struct sway_container *con = view->container;
+	while (con) {
+		enum sway_container_layout layout = container_parent_layout(con);
 		if (layout == L_TABBED || layout == L_STACKED) {
-			struct sway_node *parent = container->parent ?
-				&container->parent->node : &container->workspace->node;
-			if (seat_get_active_child(seat, parent) != &container->node) {
+			struct sway_node *parent = con->parent ?
+				&con->parent->node : &con->workspace->node;
+			if (seat_get_active_tiling_child(seat, parent) != &con->node) {
 				return false;
 			}
 		}
-		container = container->parent;
+		con = con->parent;
 	}
 	// Check view isn't hidden by another fullscreen view
 	if (workspace->fullscreen &&