From 97f7d47413967e2b6f405c4fa303850b7c56f57a Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Sat, 10 Dec 2016 16:44:43 +0100
Subject: Added Awesome/Monad type "auto" layouts

---
 include/sway/container.h | 17 +++++++++++++++++
 include/sway/layout.h    |  3 +++
 2 files changed, 20 insertions(+)

(limited to 'include')

diff --git a/include/sway/container.h b/include/sway/container.h
index 2bedd136..1d0fb265 100644
--- a/include/sway/container.h
+++ b/include/sway/container.h
@@ -37,6 +37,13 @@ enum swayc_layouts {
 	L_STACKED,
 	L_TABBED,
 	L_FLOATING,	/**< A psuedo-container, removed from the tree, to hold floating windows */
+
+	/* Awesome/Monad style auto layouts */
+	L_AUTO_LEFT,
+	L_AUTO_RIGHT,
+	L_AUTO_TOP,
+	L_AUTO_BOTTOM,
+
 	// Keep last
 	L_LAYOUTS,
 };
@@ -144,6 +151,16 @@ struct sway_container {
 	struct wlc_geometry title_bar_geometry;
 	struct wlc_geometry actual_geometry;
 	int border_thickness;
+
+	/**
+	 * Number of master views in auto layouts.
+	 */
+	uint32_t nb_master;
+
+	/**
+	 * Number of slave groups (e.g. columns) in auto layouts.
+	 */
+	uint32_t nb_slave_groups;
 };
 
 enum visibility_mask {
diff --git a/include/sway/layout.h b/include/sway/layout.h
index b982365c..38096947 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -75,4 +75,7 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
  */
 enum swayc_layouts default_layout(swayc_t *output);
 
+inline bool is_auto_layout(enum swayc_layouts layout) {
+	return (layout >= L_AUTO_LEFT) && (layout <= L_AUTO_BOTTOM);
+}
 #endif
-- 
cgit v1.2.3


From 0ff9fe9a7a18a5130b7c5e979ba980409f91b5f1 Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Thu, 22 Dec 2016 18:46:00 +0100
Subject: introduce next/prev as a direction for focus/move commands.

---
 include/sway/focus.h   |  5 ++--
 sway/commands/focus.c  |  4 ++++
 sway/commands/layout.c |  3 ++-
 sway/commands/move.c   |  6 ++++-
 sway/layout.c          | 65 +++++++++++++++++++++++++++++++++++++++++++-------
 sway/sway.5.txt        |  6 +++--
 6 files changed, 75 insertions(+), 14 deletions(-)

(limited to 'include')

diff --git a/include/sway/focus.h b/include/sway/focus.h
index b532edc2..30c9e108 100644
--- a/include/sway/focus.h
+++ b/include/sway/focus.h
@@ -6,7 +6,9 @@ enum movement_direction {
 	MOVE_UP,
 	MOVE_DOWN,
 	MOVE_PARENT,
-	MOVE_CHILD
+	MOVE_CHILD,
+	MOVE_NEXT,
+	MOVE_PREV
 };
 
 #include "container.h"
@@ -40,4 +42,3 @@ extern bool suspend_workspace_cleanup;
 bool move_focus(enum movement_direction direction);
 
 #endif
-
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 8442305f..0be442ca 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -46,6 +46,10 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
 		move_focus(MOVE_PARENT);
 	} else if (strcasecmp(argv[0], "child") == 0) {
 		move_focus(MOVE_CHILD);
+	} else if (strcasecmp(argv[0], "next") == 0) {
+		move_focus(MOVE_NEXT);
+	} else if (strcasecmp(argv[0], "prev") == 0) {
+		move_focus(MOVE_PREV);
 	} else if (strcasecmp(argv[0], "mode_toggle") == 0) {
 		int i;
 		swayc_t *workspace = swayc_active_workspace();
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 5e2e8efd..9e468c21 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -49,7 +49,8 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 		} else if (strcasecmp(argv[0], "splitv") == 0) {
 			swayc_change_layout(parent, L_VERT);
 		} else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) {
-			if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) {
+			if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE ||
+							  parent->workspace_layout == L_HORIZ)) {
 				swayc_change_layout(parent, L_VERT);
 			} else {
 				swayc_change_layout(parent, L_HORIZ);
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 4819d9ef..4f6bc76f 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -13,7 +13,7 @@ struct cmd_results *cmd_move(int argc, char **argv) {
 	if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
 		return error;
 	}
-	const char* expected_syntax = "Expected 'move <left|right|up|down>' or "
+	const char* expected_syntax = "Expected 'move <left|right|up|down|next|prev>' or "
 		"'move <container|window> to workspace <name>' or "
 		"'move <container|window|workspace> to output <name|direction>' or "
 		"'move position mouse'";
@@ -27,6 +27,10 @@ struct cmd_results *cmd_move(int argc, char **argv) {
 		move_container(view, MOVE_UP);
 	} else if (strcasecmp(argv[0], "down") == 0) {
 		move_container(view, MOVE_DOWN);
+	} else if (strcasecmp(argv[0], "next") == 0) {
+		move_container(view, MOVE_NEXT);
+	} else if (strcasecmp(argv[0], "prev") == 0) {
+		move_container(view, MOVE_PREV);
 	} else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) {
 		// "move container ...
 		if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) {
diff --git a/sway/layout.c b/sway/layout.c
index 0428ecf9..a8ad7ed5 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -251,7 +251,7 @@ void swap_geometry(swayc_t *a, swayc_t *b) {
 }
 
 void move_container(swayc_t *container, enum movement_direction dir) {
-	enum swayc_layouts layout;
+	enum swayc_layouts layout = L_NONE;
 	if (container->is_floating
 			|| (container->type != C_VIEW && container->type != C_CONTAINER)) {
 		return;
@@ -260,7 +260,7 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 		layout = L_VERT;
 	} else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
 		layout = L_HORIZ;
-	} else {
+	} else if (! (dir == MOVE_NEXT || dir == MOVE_PREV)) {
 		return;
 	}
 	swayc_t *parent = container->parent;
@@ -284,18 +284,51 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 				container,parent,child);
 		if (parent->layout == layout
 			|| (parent->layout == L_TABBED && layout == L_HORIZ)
-			|| (parent->layout == L_STACKED && layout == L_VERT)) {
+			|| (parent->layout == L_STACKED && layout == L_VERT)
+			|| is_auto_layout(parent->layout)) {
 			int diff;
 			// If it has ascended (parent has moved up), no container is removed
 			// so insert it at index, or index+1.
 			// if it has not, the moved container is removed, so it needs to be
 			// inserted at index-1, or index+1
 			if (ascended) {
-				diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1;
+				diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? 0 : 1;
 			} else {
-				diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1;
+				diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? -1 : 1;
+			}
+			int idx = index_child(child);
+			int desired = idx + diff;
+			if (dir == MOVE_NEXT || dir == MOVE_PREV) {
+				// Next/Prev always wrap.
+				if (desired < 0) {
+					desired += parent->children->length;
+				} else if (desired >= parent->children->length) {
+					desired = 0;
+				}
+				// if move command makes container change from master to slave
+				// (or the contrary), reset its geometry an the one of the replaced item.
+				if (parent->nb_master &&
+				    (uint_fast32_t) parent->children->length > parent->nb_master) {
+					swayc_t *swap_geom = NULL;
+					// if child is being promoted/demoted, it will swap geometry
+					// with the sibling being demoted/promoted.
+					if ((dir == MOVE_NEXT && desired == 0)
+					    || (dir == MOVE_PREV && (uint_fast32_t) desired == parent->nb_master - 1)) {
+						swap_geom = parent->children->items[parent->nb_master - 1];
+					} else if ((dir == MOVE_NEXT && (uint_fast32_t) desired == parent->nb_master)
+						   || (dir == MOVE_PREV && desired == parent->children->length - 1)) {
+						swap_geom = parent->children->items[parent->nb_master];
+					}
+					if (swap_geom) {
+						double h = child->height;
+						double w = child->width;
+						child->width = swap_geom->width;
+						child->height = swap_geom->height;
+						swap_geom->width = w;
+						swap_geom->height = h;
+					}
+				}
 			}
-			int desired = index_child(child) + diff;
 			// when it has ascended, legal insertion position is 0:len
 			// when it has not, legal insertion position is 0:len-1
 			if (desired >= 0 && desired - ascended < parent->children->length) {
@@ -308,7 +341,8 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 						// insert it next to focused container
 						if (parent->layout == layout
 							|| (parent->layout == L_TABBED && layout == L_HORIZ)
-							|| (parent->layout == L_STACKED && layout == L_VERT)) {
+							|| (parent->layout == L_STACKED && layout == L_VERT)
+							|| is_auto_layout(parent->layout)) {
 							desired = (diff < 0) * parent->children->length;
 						} else {
 							desired = index_child(child->focused) + 1;
@@ -325,7 +359,7 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 			}
 		}
 		// Change parent layout if we need to
-		if (parent->children->length == 1 && parent->layout != layout) {
+		if (parent->children->length == 1 && parent->layout != layout && layout != L_NONE) {
 			/* swayc_change_layout(parent, layout); */
 			parent->layout = layout;
 			continue;
@@ -1310,6 +1344,21 @@ swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_directio
 			return parent;
 		}
 	}
+
+	if (dir == MOVE_PREV || dir == MOVE_NEXT) {
+		int focused_idx = index_child(container);
+		if (focused_idx == -1) {
+			return NULL;
+		} else {
+			int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) %
+				      parent->children->length;
+			if (desired < 0) {
+				desired += parent->children->length;
+			}
+			return parent->children->items[desired];
+		}
+	}
+
 	// If moving to an adjacent output we need a starting position (since this
 	// output might border to multiple outputs).
 	struct wlc_point abs_pos;
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index 2fa5f32e..8f8302f0 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -92,8 +92,10 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**(
 	focused container. <n> can be a positive or negative integer. These commands
 	only have an effect if the focused container uses one of the "auto" layouts.
 
-**move** <left|right|up|down>::
-	Moves the focused container _left_, _right_, _up_, or _down_.
+**move** <left|right|up|down|next|prev>::
+	Moves the focused container _left_, _right_, _up_, or _down_. Moving
+	to _prev_ or _next_ swaps the container with its sibling in the same
+	container.
 
 **move** <container|window> to workspace <name>::
 	Moves the focused container to the workspace identified by _name_.
-- 
cgit v1.2.3


From a0aa8d9780c6c8b0138800e3b2c2c0053174a2c5 Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Thu, 29 Dec 2016 20:26:35 +0100
Subject: cleanup in auto layouts

- added L_AUTO_FIRST/LAST instead of using explicit layouts.
- when switching between auto layout that don't share the same major axis, invert the
  width/height of their child views to preserve their relative proportions.
---
 include/sway/container.h         |  3 +++
 include/sway/layout.h            |  2 +-
 sway/commands/layout.c           | 48 ++++++++++++++++++++++++++++++----------
 sway/commands/workspace_layout.c | 10 ++++++++-
 sway/container.c                 | 23 ++++++++++++++++---
 sway/sway.5.txt                  |  2 +-
 6 files changed, 70 insertions(+), 18 deletions(-)

(limited to 'include')

diff --git a/include/sway/container.h b/include/sway/container.h
index 1d0fb265..f0574b1b 100644
--- a/include/sway/container.h
+++ b/include/sway/container.h
@@ -44,6 +44,9 @@ enum swayc_layouts {
 	L_AUTO_TOP,
 	L_AUTO_BOTTOM,
 
+	L_AUTO_FIRST = L_AUTO_LEFT,
+	L_AUTO_LAST = L_AUTO_BOTTOM,
+
 	// Keep last
 	L_LAYOUTS,
 };
diff --git a/include/sway/layout.h b/include/sway/layout.h
index 38096947..a771a72e 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -76,6 +76,6 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
 enum swayc_layouts default_layout(swayc_t *output);
 
 inline bool is_auto_layout(enum swayc_layouts layout) {
-	return (layout >= L_AUTO_LEFT) && (layout <= L_AUTO_BOTTOM);
+	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
 }
 #endif
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 9e468c21..5426186e 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -56,24 +56,12 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 				swayc_change_layout(parent, L_HORIZ);
 			}
 		} else if (strcasecmp(argv[0], "auto_left") == 0) {
-			if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
-				parent = new_container(parent, L_AUTO_LEFT);
-			}
 			swayc_change_layout(parent, L_AUTO_LEFT);
 		} else if (strcasecmp(argv[0], "auto_right") == 0) {
-			if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
-				parent = new_container(parent, L_AUTO_RIGHT);
-			}
 			swayc_change_layout(parent, L_AUTO_RIGHT);
 		} else if (strcasecmp(argv[0], "auto_top") == 0) {
-			if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
-				parent = new_container(parent, L_AUTO_TOP);
-			}
 			swayc_change_layout(parent, L_AUTO_TOP);
 		} else if (strcasecmp(argv[0], "auto_bot") == 0) {
-			if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
-				parent = new_container(parent, L_AUTO_BOTTOM);
-			}
 			swayc_change_layout(parent, L_AUTO_BOTTOM);
 		} else if (strcasecmp(argv[0], "incnmaster") == 0)  {
 			if ((error = checkarg(argc, "layout incnmaster",
@@ -105,6 +93,42 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 			    ((int)container->parent->nb_slave_groups + inc >= 1)) {
 				container->parent->nb_slave_groups += inc;
 			}
+		} else if (strcasecmp(argv[0], "auto") == 0) {
+			if ((error = checkarg(argc, "auto", EXPECTED_EQUAL_TO, 2))) {
+				return error;
+			}
+			swayc_t *container = get_focused_view(swayc_active_workspace());
+			swayc_t *parent = container->parent;
+			enum swayc_layouts layout;
+			if (strcasecmp(argv[1], "next") == 0) {
+				if (is_auto_layout(parent->layout) && parent->layout < L_AUTO_LAST) {
+					layout = parent->layout + 1;
+				} else {
+					layout = L_AUTO_FIRST;
+				}
+			} else if (strcasecmp(argv[1], "prev") == 0) {
+				if (is_auto_layout(parent->layout) && parent->layout > L_AUTO_FIRST) {
+					layout = parent->layout - 1;
+				} else {
+					layout = L_AUTO_FIRST;
+				}
+			} else {
+				return cmd_results_new(CMD_FAILURE, "layout auto",
+						       "Must be one of <prev|next>.");
+			}
+			swayc_change_layout(parent, layout);
+		} else if (strcasecmp(argv[0], "promote") == 0) {
+			// swap first child in auto layout with currently focused child
+			swayc_t *container = get_focused_view(swayc_active_workspace());
+			swayc_t *parent = container->parent;
+			if (is_auto_layout(parent->layout)) {
+				int focused_idx = index_child(container);
+				swayc_t *first = parent->children->items[0];
+				if (focused_idx > 0) {
+					list_swap(parent->children, 0, focused_idx);
+					swap_geometry(first, container);
+				}
+			}
 		}
 	}
 
diff --git a/sway/commands/workspace_layout.c b/sway/commands/workspace_layout.c
index b7b4b033..3e0a12ce 100644
--- a/sway/commands/workspace_layout.c
+++ b/sway/commands/workspace_layout.c
@@ -13,8 +13,16 @@ struct cmd_results *cmd_workspace_layout(int argc, char **argv) {
 		config->default_layout = L_STACKED;
 	} else if (strcasecmp(argv[0], "tabbed") == 0) {
 		config->default_layout = L_TABBED;
+	} else if (strcasecmp(argv[0], "auto_left") == 0) {
+		config->default_layout = L_AUTO_LEFT;
+	} else if (strcasecmp(argv[0], "auto_right") == 0) {
+		config->default_layout = L_AUTO_RIGHT;
+	} else if (strcasecmp(argv[0], "auto_top") == 0) {
+		config->default_layout = L_AUTO_TOP;
+	} else if (strcasecmp(argv[0], "auto_bottom") == 0) {
+		config->default_layout = L_AUTO_BOTTOM;
 	} else {
-		return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed>'");
+		return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed|auto_left|auto_right|auto_top|auto_bottom>'");
 	}
 	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 }
diff --git a/sway/container.c b/sway/container.c
index d034115f..3bdc8b6c 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -962,11 +962,28 @@ swayc_t *swayc_tabbed_stacked_parent(swayc_t *con) {
 }
 
 swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) {
+	// if layout change modifies the auto layout's major axis, swap width and height
+	// to preserve current ratios.
+	if (is_auto_layout(layout) && is_auto_layout(container->layout)) {
+		enum swayc_layouts prev_major = (container->layout == L_AUTO_LEFT ||
+						 container->layout == L_AUTO_RIGHT)
+			? L_HORIZ : L_VERT;
+		enum swayc_layouts new_major = (layout == L_AUTO_LEFT || layout == L_AUTO_RIGHT)
+			? L_HORIZ : L_VERT;
+		if (new_major != prev_major) {
+			for (int i = 0; i < container->children->length; ++i) {
+				swayc_t *child = container->children->items[i];
+				double h = child->height;
+				child->height = child->width;
+				child->width = h;
+			}
+		}
+	}
 	if (container->type == C_WORKSPACE) {
 		container->workspace_layout = layout;
-    if (layout == L_HORIZ || layout == L_VERT) {
-      container->layout = layout;
-    }
+		if (layout == L_HORIZ || layout == L_VERT || is_auto_layout(layout)) {
+			container->layout = layout;
+		}
 	} else {
 		container->layout = layout;
 	}
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index 8f8302f0..c0c4bfb2 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -371,7 +371,7 @@ The default colors are:
 	switch to workspace 2, then invoke the "workspace 2" command again, you
 	will be returned to workspace 1. Defaults to _no_.
 
-**workspace_layout** <default|stacking|tabbed>::
+**workspace_layout** <default|stacking|tabbed|auto_left|auto_right|auto_top|auto_bottom>::
 	Specifies the start layout for new workspaces.
 
 **include** <path>::
-- 
cgit v1.2.3


From 1b87193c3d63c8d884b5a45451a000d9b930521e Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Thu, 29 Dec 2016 20:30:32 +0100
Subject: Added "layout promote" command.

---
 common/list.c   | 2 +-
 include/list.h  | 2 ++
 sway/sway.5.txt | 3 +++
 3 files changed, 6 insertions(+), 1 deletion(-)

(limited to 'include')

diff --git a/common/list.c b/common/list.c
index dd864a9b..39cc10e1 100644
--- a/common/list.c
+++ b/common/list.c
@@ -76,7 +76,7 @@ int list_seq_find(list_t *list, int compare(const void *item, const void *data),
 	return -1;
 }
 
-static void list_swap(list_t *list, int src, int dest) {
+void list_swap(list_t *list, int src, int dest) {
 	void *tmp = list->items[src];
 	list->items[src] = list->items[dest];
 	list->items[dest] = tmp;
diff --git a/include/list.h b/include/list.h
index f478b6bb..7eead4ac 100644
--- a/include/list.h
+++ b/include/list.h
@@ -22,4 +22,6 @@ void list_qsort(list_t *list, int compare(const void *left, const void *right));
 int list_seq_find(list_t *list, int compare(const void *item, const void *cmp_to), const void *cmp_to);
 // stable sort since qsort is not guaranteed to be stable
 void list_stable_sort(list_t *list, int compare(const void *a, const void *b));
+// swap two elements in a list
+void list_swap(list_t *list, int src, int dest);
 #endif
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index c0c4bfb2..b58fbe55 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -92,6 +92,9 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**(
 	focused container. <n> can be a positive or negative integer. These commands
 	only have an effect if the focused container uses one of the "auto" layouts.
 
+**layout** promote::
+	Swap the focused element with the first in the one of the auto layouts.
+
 **move** <left|right|up|down|next|prev>::
 	Moves the focused container _left_, _right_, _up_, or _down_. Moving
 	to _prev_ or _next_ swaps the container with its sibling in the same
-- 
cgit v1.2.3


From c01b89839874239bee7948fad004b19a19917432 Mon Sep 17 00:00:00 2001
From: Drew DeVault <sir@cmpwn.com>
Date: Sun, 1 Jan 2017 12:36:47 -0500
Subject: Fix inline is_auto_layout

---
 include/sway/layout.h | 5 ++---
 sway/layout.c         | 4 ++++
 2 files changed, 6 insertions(+), 3 deletions(-)

(limited to 'include')

diff --git a/include/sway/layout.h b/include/sway/layout.h
index a771a72e..d7fe748d 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -75,7 +75,6 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
  */
 enum swayc_layouts default_layout(swayc_t *output);
 
-inline bool is_auto_layout(enum swayc_layouts layout) {
-	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
-}
+bool is_auto_layout(enum swayc_layouts layout);
+
 #endif
diff --git a/sway/layout.c b/sway/layout.c
index 2de6da45..2195863e 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -1487,3 +1487,7 @@ enum swayc_layouts default_layout(swayc_t *output) {
 		return L_VERT;
 	}
 }
+
+bool is_auto_layout(enum swayc_layouts layout) {
+	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
+}
-- 
cgit v1.2.3


From a62048f15d9381e3040bd45965233e59a041eab7 Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Sun, 1 Jan 2017 19:53:53 +0100
Subject: changed "layout promote" command to "move first"

This is more consistent with other Sway semantics.
---
 include/sway/focus.h   |  3 ++-
 sway/commands/layout.c | 12 ------------
 sway/commands/move.c   |  4 +++-
 sway/layout.c          | 16 +++++++++++++++-
 sway/sway.5.txt        | 12 +++++-------
 5 files changed, 25 insertions(+), 22 deletions(-)

(limited to 'include')

diff --git a/include/sway/focus.h b/include/sway/focus.h
index 30c9e108..652cdccc 100644
--- a/include/sway/focus.h
+++ b/include/sway/focus.h
@@ -8,7 +8,8 @@ enum movement_direction {
 	MOVE_PARENT,
 	MOVE_CHILD,
 	MOVE_NEXT,
-	MOVE_PREV
+	MOVE_PREV,
+	MOVE_FIRST
 };
 
 #include "container.h"
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index d908b95c..2da65765 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -117,18 +117,6 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 						       "Must be one of <prev|next>.");
 			}
 			swayc_change_layout(parent, layout);
-		} else if (strcasecmp(argv[0], "promote") == 0) {
-			// swap first child in auto layout with currently focused child
-			swayc_t *container = get_focused_view(swayc_active_workspace());
-			swayc_t *parent = container->parent;
-			if (is_auto_layout(parent->layout)) {
-				int focused_idx = index_child(container);
-				swayc_t *first = parent->children->items[0];
-				if (focused_idx > 0) {
-					list_swap(parent->children, 0, focused_idx);
-					swap_geometry(first, container);
-				}
-			}
 		}
 	}
 
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 4f6bc76f..0b134494 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -13,7 +13,7 @@ struct cmd_results *cmd_move(int argc, char **argv) {
 	if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
 		return error;
 	}
-	const char* expected_syntax = "Expected 'move <left|right|up|down|next|prev>' or "
+	const char* expected_syntax = "Expected 'move <left|right|up|down|next|prev|first>' or "
 		"'move <container|window> to workspace <name>' or "
 		"'move <container|window|workspace> to output <name|direction>' or "
 		"'move position mouse'";
@@ -31,6 +31,8 @@ struct cmd_results *cmd_move(int argc, char **argv) {
 		move_container(view, MOVE_NEXT);
 	} else if (strcasecmp(argv[0], "prev") == 0) {
 		move_container(view, MOVE_PREV);
+	} else if (strcasecmp(argv[0], "first") == 0) {
+		move_container(view, MOVE_FIRST);
 	} else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) {
 		// "move container ...
 		if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) {
diff --git a/sway/layout.c b/sway/layout.c
index 2de6da45..6212ec75 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -252,6 +252,7 @@ void swap_geometry(swayc_t *a, swayc_t *b) {
 
 void move_container(swayc_t *container, enum movement_direction dir) {
 	enum swayc_layouts layout = L_NONE;
+	swayc_t *parent = container->parent;
 	if (container->is_floating
 			|| (container->type != C_VIEW && container->type != C_CONTAINER)) {
 		return;
@@ -260,10 +261,23 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 		layout = L_VERT;
 	} else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
 		layout = L_HORIZ;
+	} else if (dir == MOVE_FIRST) {
+		// swap first child in auto layout with currently focused child
+		if (is_auto_layout(parent->layout)) {
+			int focused_idx = index_child(container);
+			swayc_t *first = parent->children->items[0];
+			if (focused_idx > 0) {
+				list_swap(parent->children, 0, focused_idx);
+				swap_geometry(first, container);
+			}
+			arrange_windows(parent->parent, -1, -1);
+			ipc_event_window(container, "move");
+			set_focused_container_for(parent->parent, container);
+		}
+		return;
 	} else if (! (dir == MOVE_NEXT || dir == MOVE_PREV)) {
 		return;
 	}
-	swayc_t *parent = container->parent;
 	swayc_t *child = container;
 	bool ascended = false;
 
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index b58fbe55..eece4b5b 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -92,13 +92,11 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**(
 	focused container. <n> can be a positive or negative integer. These commands
 	only have an effect if the focused container uses one of the "auto" layouts.
 
-**layout** promote::
-	Swap the focused element with the first in the one of the auto layouts.
-
-**move** <left|right|up|down|next|prev>::
-	Moves the focused container _left_, _right_, _up_, or _down_. Moving
-	to _prev_ or _next_ swaps the container with its sibling in the same
-	container.
+**move** <left|right|up|down|next|prev|first>::
+	Moves the focused container _left_, _right_, _up_, or _down_. Moving to _prev_
+	or _next_ swaps the container with its sibling in the same container. Move
+	_first_ exchanges the focused element in an auto layout with the first
+	element, i.e. promotes  the focused element to master position.
 
 **move** <container|window> to workspace <name>::
 	Moves the focused container to the workspace identified by _name_.
-- 
cgit v1.2.3


From 97f70987d70315c683fd1e16c731b396679f6b96 Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Sun, 1 Jan 2017 21:52:49 +0100
Subject: [fix] cleanups suggested by Sway community

---
 README.md                |  5 ----
 include/sway/container.h |  4 +--
 include/sway/layout.h    |  4 +--
 sway/commands/layout.c   | 22 ++++++++++++---
 sway/commands/resize.c   | 70 ++++++++++++++++++++++++------------------------
 sway/layout.c            | 44 +++++++++++++++---------------
 6 files changed, 79 insertions(+), 70 deletions(-)

(limited to 'include')

diff --git a/README.md b/README.md
index 6e714cb9..6b038045 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
 # sway [![](https://api.travis-ci.org/SirCmpwn/sway.svg)](https://travis-ci.org/SirCmpwn/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
 
 "**S**irCmpwn's **Way**land compositor" is a **work in progress**
@@ -11,10 +10,6 @@ irc.freenode.net).
 
 [More screenshots](https://github.com/SirCmpwn/sway/wiki/Screenshots-of-Sway)
 
-This fork attempts to add
-[Awesome](http://awesomewm.org)/[Monad](http://xmonad.org) style auto layouts
-to Sway. For us lazies that just want things to happen automatically!
-
 ## Release Signatures
 
 Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
diff --git a/include/sway/container.h b/include/sway/container.h
index f0574b1b..ff65628c 100644
--- a/include/sway/container.h
+++ b/include/sway/container.h
@@ -158,12 +158,12 @@ struct sway_container {
 	/**
 	 * Number of master views in auto layouts.
 	 */
-	uint32_t nb_master;
+	size_t nb_master;
 
 	/**
 	 * Number of slave groups (e.g. columns) in auto layouts.
 	 */
-	uint32_t nb_slave_groups;
+	size_t nb_slave_groups;
 };
 
 enum visibility_mask {
diff --git a/include/sway/layout.h b/include/sway/layout.h
index a771a72e..8cc513d8 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -75,7 +75,5 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
  */
 enum swayc_layouts default_layout(swayc_t *output);
 
-inline bool is_auto_layout(enum swayc_layouts layout) {
-	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
-}
+bool is_auto_layout(enum swayc_layouts layout);
 #endif
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 2da65765..0cdac1b4 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -64,11 +64,18 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 		} else if (strcasecmp(argv[0], "auto_bot") == 0) {
 			swayc_change_layout(parent, L_AUTO_BOTTOM);
 		} else if (strcasecmp(argv[0], "incnmaster") == 0)  {
-			if ((error = checkarg(argc, "layout incnmaster",
+			const char *name = "layout incnmaster";
+			if ((error = checkarg(argc, name,
 					      EXPECTED_EQUAL_TO, 2))) {
 				return error;
 			}
-			int inc = (int) strtol(argv[1], NULL, 10);
+			char *end;
+			int inc = (int) strtol(argv[1], &end, 10);
+			if (*end) {
+				return cmd_results_new(CMD_INVALID, name, "Invalid %s command "
+						       "(argument must be an integer)", name);
+
+			}
 			swayc_t *container = get_focused_view(swayc_active_workspace());
 			if (container && inc &&
 			    is_auto_layout(container->parent->layout) &&
@@ -83,11 +90,18 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
 				container->parent->nb_master += inc;
 			}
 		} else if ((strcasecmp(argv[0], "incncol") == 0) && argc ==2) {
-			if ((error = checkarg(argc, "layout incncol",
+			const char *name = "layout incncol";
+			if ((error = checkarg(argc, name,
 					      EXPECTED_EQUAL_TO, 2))) {
 				return error;
 			}
-			int inc = (int) strtol(argv[1], NULL, 10);
+			char *end;
+			int inc = (int) strtol(argv[1], &end, 10);
+			if (*end) {
+				return cmd_results_new(CMD_INVALID, name, "Invalid %s command "
+						       "(argument must be an integer)", name);
+
+			}
 			swayc_t *container = get_focused_view(swayc_active_workspace());
 			if (container && inc && is_auto_layout(container->parent->layout) &&
 			    ((int)container->parent->nb_slave_groups + inc >= 1)) {
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 9a756e81..1c052286 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -66,7 +66,7 @@ static bool resize_floating(int amount, bool use_width) {
  * Return the number of children in the slave groups. This corresponds to the children
  * that are not members of the master group.
  */
-static inline uint_fast32_t slave_count(swayc_t *container) {
+static inline size_t auto_slave_count(swayc_t *container) {
 	return container->children->length - container->nb_master;
 
 }
@@ -75,13 +75,13 @@ static inline uint_fast32_t slave_count(swayc_t *container) {
  * given the index of a container's child, return the index of the first child of the group
  * which index is a member of.
  */
-static int group_start_index(swayc_t *container, int index) {
-	if ((index < 0) || (! is_auto_layout(container->layout)) ||
-	    ((uint_fast32_t) index < container->nb_master)) {
+static int auto_group_start_index(swayc_t *container, int index) {
+	if (index < 0 || ! is_auto_layout(container->layout)
+		|| (size_t) index < container->nb_master) {
 		return 0;
 	} else {
-		uint_fast32_t grp_sz = slave_count(container) / container->nb_slave_groups;
-		uint_fast32_t remainder = slave_count(container) % container->nb_slave_groups;
+		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
 		int start_idx;
 		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
 		if (index < idx2) {
@@ -98,16 +98,16 @@ static int group_start_index(swayc_t *container, int index) {
  * that follows the one which index is a member of.
  * This makes the function usable to walk through the groups in a container.
  */
-static int group_end_index(swayc_t *container, int index) {
+static int auto_group_end_index(swayc_t *container, int index) {
 	if (index < 0 || ! is_auto_layout(container->layout)) {
 		return container->children->length;
 	} else {
 		int nxt_idx;
-		if ((uint_fast32_t)index < container->nb_master) {
+		if ((size_t)index < container->nb_master) {
 			nxt_idx = container->nb_master;
 		} else {
-			uint_fast32_t grp_sz = slave_count(container) / container->nb_slave_groups;
-			uint_fast32_t remainder = slave_count(container) % container->nb_slave_groups;
+			size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+			size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
 			int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
 			if (index < idx2) {
 				nxt_idx = ((index - container->nb_master) / grp_sz + 1) * grp_sz + container->nb_master;
@@ -122,30 +122,30 @@ static int group_end_index(swayc_t *container, int index) {
 /**
  * Return the combined number of master and slave groups in the container.
  */
-static inline uint_fast32_t group_count(swayc_t *container) {
-	return MIN(container->nb_slave_groups, slave_count(container)) + (container->nb_master ? 1 : 0);
+static inline size_t auto_group_count(swayc_t *container) {
+	return MIN(container->nb_slave_groups, auto_slave_count(container)) + (container->nb_master ? 1 : 0);
 }
 
 /**
  * return the index of the Group containing <index>th child of <container>.
  * The index is the order of the group along the container's major axis (starting at 0).
  */
-static uint_fast32_t group_index(swayc_t *container, int index) {
+static size_t auto_group_index(swayc_t *container, int index) {
 	if (index < 0) {
 		return 0;
 	}
 	bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP);
-	int nb_slaves = slave_count(container);
-	if ((uint_fast32_t) index < container->nb_master) {
+	int nb_slaves = auto_slave_count(container);
+	if ((size_t) index < container->nb_master) {
 		if (master_first || nb_slaves <= 0) {
 			return 0;
 		} else {
 			return MIN(container->nb_slave_groups, nb_slaves);
 		}
 	} else {
-		uint_fast32_t grp_sz = slave_count(container) / container->nb_slave_groups;
-		uint_fast32_t remainder = slave_count(container) % container->nb_slave_groups;
-		uint_fast32_t grp_idx;
+		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
+		size_t grp_idx;
 		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
 		if (index < idx2) {
 			grp_idx = (index - container->nb_master) / grp_sz;
@@ -161,16 +161,16 @@ static bool resize_tiled(int amount, bool use_width) {
 	swayc_t *parent = container->parent;
 	int idx_focused = 0;
 	bool use_major = false;
-	uint_fast32_t nb_before = 0;
-	uint_fast32_t nb_after = 0;
+	size_t nb_before = 0;
+	size_t nb_after = 0;
 
 	// 1. Identify a container ancestor that will allow the focused child to grow in the requested
 	//    direction.
 	while (container->parent) {
 		parent = container->parent;
-		if ((parent->children && parent->children->length > 1) &&
-		    (is_auto_layout(parent->layout) || (use_width ? parent->layout == L_HORIZ :
-							parent->layout == L_VERT))) {
+		if ((parent->children && parent->children->length > 1)
+			&& (is_auto_layout(parent->layout)
+				|| (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) {
 			// check if container has siblings that can provide/absorb the space needed for
 			// the resize operation.
 			use_major = use_width
@@ -185,15 +185,15 @@ static bool resize_tiled(int amount, bool use_width) {
 				continue;
 			}
 			if (use_major) {
-				nb_before = group_index(parent, idx_focused);
-				nb_after = group_count(parent) - nb_before - 1;
+				nb_before = auto_group_index(parent, idx_focused);
+				nb_after = auto_group_count(parent) - nb_before - 1;
 			} else {
-				nb_before = idx_focused - group_start_index(parent, idx_focused);
-				nb_after = group_end_index(parent, idx_focused) - idx_focused - 1;
+				nb_before = idx_focused - auto_group_start_index(parent, idx_focused);
+				nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1;
 				sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d",
 					 idx_focused,
-					 (int)group_start_index(parent, idx_focused),
-					 (int)group_end_index(parent, idx_focused),
+					 (int)auto_group_start_index(parent, idx_focused),
+					 (int)auto_group_end_index(parent, idx_focused),
 					 (int)nb_before, (int)nb_after);
 
 			}
@@ -206,14 +206,14 @@ static bool resize_tiled(int amount, bool use_width) {
 	if (parent == &root_container) {
 		return true;
 	}
-	sway_log(L_DEBUG, "Found the proper parent: %p. It has %" PRIuFAST32 " before conts, and %"
-		 PRIuFAST32 " after conts", parent, nb_before, nb_after);
+	sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, "
+		 "and %zu after conts", parent, nb_before, nb_after);
 	// 2. Ensure that the resize operation will not make one of the resized containers drop
 	//    below the "sane" size threshold.
 	bool valid = true;
 	swayc_t *focused = parent->children->items[idx_focused];
-	int start = use_major ? 0 : group_start_index(parent, idx_focused);
-	int end = use_major ? parent->children->length : group_end_index(parent, idx_focused);
+	int start = use_major ? 0 : auto_group_start_index(parent, idx_focused);
+	int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused);
 	sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end);
 	for (int i = start; i < end; ) {
 		swayc_t *sibling = parent->children->items[i];
@@ -235,13 +235,13 @@ static bool resize_tiled(int amount, bool use_width) {
 			sway_log(L_DEBUG, "Container size no longer sane");
 			break;
 		}
-		i = use_major ? group_end_index(parent, i) : (i + 1);
+		i = use_major ? auto_group_end_index(parent, i) : (i + 1);
 		sway_log(L_DEBUG, "+++++ check %i", i);
 	}
 	// 3. Apply the size change
 	if (valid) {
 		for (int i = start; i < end; ) {
-			int next_i = use_major ? group_end_index(parent, i) : (i + 1);
+			int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1);
 			swayc_t *sibling = parent->children->items[i];
 			double pixels = amount;
 			bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y;
diff --git a/sway/layout.c b/sway/layout.c
index 6212ec75..faab9196 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -253,8 +253,7 @@ void swap_geometry(swayc_t *a, swayc_t *b) {
 void move_container(swayc_t *container, enum movement_direction dir) {
 	enum swayc_layouts layout = L_NONE;
 	swayc_t *parent = container->parent;
-	if (container->is_floating
-			|| (container->type != C_VIEW && container->type != C_CONTAINER)) {
+	if (container->is_floating || (container->type != C_VIEW && container->type != C_CONTAINER)) {
 		return;
 	}
 	if (dir == MOVE_UP || dir == MOVE_DOWN) {
@@ -323,14 +322,14 @@ void move_container(swayc_t *container, enum movement_direction dir) {
 				// if move command makes container change from master to slave
 				// (or the contrary), reset its geometry an the one of the replaced item.
 				if (parent->nb_master &&
-				    (uint_fast32_t) parent->children->length > parent->nb_master) {
+				    (size_t) parent->children->length > parent->nb_master) {
 					swayc_t *swap_geom = NULL;
 					// if child is being promoted/demoted, it will swap geometry
 					// with the sibling being demoted/promoted.
 					if ((dir == MOVE_NEXT && desired == 0)
-					    || (dir == MOVE_PREV && (uint_fast32_t) desired == parent->nb_master - 1)) {
+					    || (dir == MOVE_PREV && (size_t) desired == parent->nb_master - 1)) {
 						swap_geom = parent->children->items[parent->nb_master - 1];
-					} else if ((dir == MOVE_NEXT && (uint_fast32_t) desired == parent->nb_master)
+					} else if ((dir == MOVE_NEXT && (size_t) desired == parent->nb_master)
 						   || (dir == MOVE_PREV && desired == parent->children->length - 1)) {
 						swap_geom = parent->children->items[parent->nb_master];
 					}
@@ -822,20 +821,24 @@ void update_geometry(swayc_t *container) {
 	}
 }
 
+bool is_auto_layout(enum swayc_layouts layout) {
+	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
+}
+
 /**
  * Layout application prototypes
  */
 static void apply_horiz_layout(swayc_t *container, const double x,
-			       const double y, const double width,
-			       const double height, const int start,
-			       const int end);
+				const double y, const double width,
+				const double height, const int start,
+				const int end);
 static void apply_vert_layout(swayc_t *container, const double x,
-			      const double y, const double width,
-			      const double height, const int start,
-			      const int end);
+				const double y, const double width,
+				const double height, const int start,
+				const int end);
 static void apply_tabbed_or_stacked_layout(swayc_t *container, double x,
-					   double y, double width,
-					   double height);
+				double y, double width,
+				double height);
 
 static void apply_auto_layout(swayc_t *container, const double x, const double y,
 			      const double width, const double height,
@@ -1164,8 +1167,8 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 	//  a single slave group (containing slave 1 and 2). The master
 	//  group and slave group are layed out using L_VERT.
 
-	uint_fast32_t nb_slaves = container->children->length - container->nb_master;
-	uint_fast32_t nb_groups = (container->nb_master > 0 ? 1 : 0) +
+	size_t nb_slaves = container->children->length - container->nb_master;
+	size_t nb_groups = (container->nb_master > 0 ? 1 : 0) +
 		MIN(container->nb_slave_groups, nb_slaves);
 
 	// the target dimension of the container along the "major" axis, each
@@ -1186,9 +1189,9 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 	// height and width of next group to be laid out.
 	const double *group_h, *group_w;
 
-	switch(group_layout) {
+	switch (group_layout) {
 	default:
-		sway_log(L_ERROR, "Unknown layout type (%d) used in %s()",
+		sway_log(L_DEBUG, "Unknown layout type (%d) used in %s()",
 			 group_layout, __func__);
 		/* fall through */
 	case L_VERT:
@@ -1216,7 +1219,7 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 	 * layout. */
 	double old_group_dim[nb_groups];
 	double old_dim = 0;
-	uint_fast32_t group = 0;
+	size_t group = 0;
 	for (int i = 0; i < container->children->length;) {
 		swayc_t *child = container->children->items[i];
 		double *dim = group_layout == L_HORIZ ? &child->height : &child->width;
@@ -1252,7 +1255,7 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 
 	for (group = 0; group < nb_groups; ++group) {
 		// column to include next by increasing position.
-		uint_fast32_t layout_group = master_first ? group : (group + 1) % nb_groups;
+		size_t layout_group = master_first ? group : (group + 1) % nb_groups;
 
 		// adjusted size of the group
 		group_dim = old_group_dim[layout_group] * scale;
@@ -1270,8 +1273,7 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 		if (group == nb_groups - 1) {
 			group_dim = pos_maj + dim_maj - pos; // remaining width
 		}
-		sway_log(L_DEBUG, "Arranging container %p column %" PRIuFAST32
-				  ", children [%d,%d[ (%fx%f+%f,%f)",
+		sway_log(L_DEBUG, "Arranging container %p column %zu, children [%d,%d[ (%fx%f+%f,%f)",
 			 container, group, start, end, *group_w, *group_h, *group_x, *group_y);
 		switch (group_layout) {
 		default:
-- 
cgit v1.2.3


From bd415029ba72425c97647b55fce19213e7909cbc Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Sat, 7 Jan 2017 17:41:15 +0100
Subject: Moved auto_* layout functions from resize.c to layout.c

---
 include/sway/layout.h  |  4 +++
 sway/commands/resize.c | 98 ++------------------------------------------------
 sway/layout.c          | 93 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 96 deletions(-)

(limited to 'include')

diff --git a/include/sway/layout.h b/include/sway/layout.h
index d7fe748d..c51fece9 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -76,5 +76,9 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
 enum swayc_layouts default_layout(swayc_t *output);
 
 bool is_auto_layout(enum swayc_layouts layout);
+int auto_group_start_index(swayc_t *container, int index);
+int auto_group_end_index(swayc_t *container, int index);
+size_t auto_group_count(swayc_t *container);
+size_t auto_group_index(swayc_t *container, int index);
 
 #endif
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 1c052286..c391945f 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -62,100 +62,6 @@ static bool resize_floating(int amount, bool use_width) {
 	return false;
 }
 
-/**
- * Return the number of children in the slave groups. This corresponds to the children
- * that are not members of the master group.
- */
-static inline size_t auto_slave_count(swayc_t *container) {
-	return container->children->length - container->nb_master;
-
-}
-
-/**
- * given the index of a container's child, return the index of the first child of the group
- * which index is a member of.
- */
-static int auto_group_start_index(swayc_t *container, int index) {
-	if (index < 0 || ! is_auto_layout(container->layout)
-		|| (size_t) index < container->nb_master) {
-		return 0;
-	} else {
-		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
-		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
-		int start_idx;
-		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
-		if (index < idx2) {
-			start_idx = ((index - container->nb_master) / grp_sz) * grp_sz + container->nb_master;
-		} else {
-			start_idx = idx2 + ((index - idx2) / (grp_sz + 1)) * (grp_sz + 1);
-		}
-		return MIN(start_idx, container->children->length);
-	}
-}
-
-/**
- * given the index of a container's child, return the index of the first child of the group
- * that follows the one which index is a member of.
- * This makes the function usable to walk through the groups in a container.
- */
-static int auto_group_end_index(swayc_t *container, int index) {
-	if (index < 0 || ! is_auto_layout(container->layout)) {
-		return container->children->length;
-	} else {
-		int nxt_idx;
-		if ((size_t)index < container->nb_master) {
-			nxt_idx = container->nb_master;
-		} else {
-			size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
-			size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
-			int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
-			if (index < idx2) {
-				nxt_idx = ((index - container->nb_master) / grp_sz + 1) * grp_sz + container->nb_master;
-			} else {
-				nxt_idx = idx2 + ((index - idx2) / (grp_sz + 1) + 1) * (grp_sz + 1);
-			}
-		}
-		return MIN(nxt_idx, container->children->length);
-	}
-}
-
-/**
- * Return the combined number of master and slave groups in the container.
- */
-static inline size_t auto_group_count(swayc_t *container) {
-	return MIN(container->nb_slave_groups, auto_slave_count(container)) + (container->nb_master ? 1 : 0);
-}
-
-/**
- * return the index of the Group containing <index>th child of <container>.
- * The index is the order of the group along the container's major axis (starting at 0).
- */
-static size_t auto_group_index(swayc_t *container, int index) {
-	if (index < 0) {
-		return 0;
-	}
-	bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP);
-	int nb_slaves = auto_slave_count(container);
-	if ((size_t) index < container->nb_master) {
-		if (master_first || nb_slaves <= 0) {
-			return 0;
-		} else {
-			return MIN(container->nb_slave_groups, nb_slaves);
-		}
-	} else {
-		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
-		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
-		size_t grp_idx;
-		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
-		if (index < idx2) {
-			grp_idx = (index - container->nb_master) / grp_sz;
-		} else {
-			grp_idx = (container->nb_slave_groups - remainder) + (index - idx2) / (grp_sz + 1) ;
-		}
-		return grp_idx + (master_first ? 1 : 0);
-	}
-}
-
 static bool resize_tiled(int amount, bool use_width) {
 	swayc_t *container = get_focused_view(swayc_active_workspace());
 	swayc_t *parent = container->parent;
@@ -229,8 +135,8 @@ static bool resize_tiled(int amount, bool use_width) {
 		}
 		sway_log(L_DEBUG, "Check container %p: width %g vs %d, height %g vs %d", sibling, sibling->width + pixels, min_sane_w, sibling->height + pixels, min_sane_h);
 		if (use_width ?
-		    sibling->width + pixels < min_sane_w :
-		    sibling->height + pixels < min_sane_h) {
+			sibling->width + pixels < min_sane_w :
+			sibling->height + pixels < min_sane_h) {
 			valid = false;
 			sway_log(L_DEBUG, "Container size no longer sane");
 			break;
diff --git a/sway/layout.c b/sway/layout.c
index 377dad47..5f8da9e6 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -1503,3 +1503,96 @@ enum swayc_layouts default_layout(swayc_t *output) {
 bool is_auto_layout(enum swayc_layouts layout) {
 	return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
 }
+
+/**
+ * Return the number of children in the slave groups. This corresponds to the children
+ * that are not members of the master group.
+ */
+static inline size_t auto_slave_count(swayc_t *container) {
+	return container->children->length - container->nb_master;
+}
+
+/**
+ * given the index of a container's child, return the index of the first child of the group
+ * which index is a member of.
+ */
+int auto_group_start_index(swayc_t *container, int index) {
+	if (index < 0 || ! is_auto_layout(container->layout)
+		|| (size_t) index < container->nb_master) {
+		return 0;
+	} else {
+		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
+		int start_idx;
+		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
+		if (index < idx2) {
+			start_idx = ((index - container->nb_master) / grp_sz) * grp_sz + container->nb_master;
+		} else {
+			start_idx = idx2 + ((index - idx2) / (grp_sz + 1)) * (grp_sz + 1);
+		}
+		return MIN(start_idx, container->children->length);
+	}
+}
+
+/**
+ * given the index of a container's child, return the index of the first child of the group
+ * that follows the one which index is a member of.
+ * This makes the function usable to walk through the groups in a container.
+ */
+int auto_group_end_index(swayc_t *container, int index) {
+	if (index < 0 || ! is_auto_layout(container->layout)) {
+		return container->children->length;
+	} else {
+		int nxt_idx;
+		if ((size_t)index < container->nb_master) {
+			nxt_idx = container->nb_master;
+		} else {
+			size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+			size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
+			int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
+			if (index < idx2) {
+				nxt_idx = ((index - container->nb_master) / grp_sz + 1) * grp_sz + container->nb_master;
+			} else {
+				nxt_idx = idx2 + ((index - idx2) / (grp_sz + 1) + 1) * (grp_sz + 1);
+			}
+		}
+		return MIN(nxt_idx, container->children->length);
+	}
+}
+
+/**
+ * Return the combined number of master and slave groups in the container.
+ */
+size_t auto_group_count(swayc_t *container) {
+	return MIN(container->nb_slave_groups, auto_slave_count(container)) + (container->nb_master ? 1 : 0);
+}
+
+/**
+ * return the index of the Group containing <index>th child of <container>.
+ * The index is the order of the group along the container's major axis (starting at 0).
+ */
+size_t auto_group_index(swayc_t *container, int index) {
+	if (index < 0) {
+		return 0;
+	}
+	bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP);
+	int nb_slaves = auto_slave_count(container);
+	if ((size_t) index < container->nb_master) {
+		if (master_first || nb_slaves <= 0) {
+			return 0;
+		} else {
+			return MIN(container->nb_slave_groups, nb_slaves);
+		}
+	} else {
+		size_t grp_sz = auto_slave_count(container) / container->nb_slave_groups;
+		size_t remainder = auto_slave_count(container) % container->nb_slave_groups;
+		size_t grp_idx;
+		int idx2 = (container->nb_slave_groups - remainder) * grp_sz + container->nb_master;
+		if (index < idx2) {
+			grp_idx = (index - container->nb_master) / grp_sz;
+		} else {
+			grp_idx = (container->nb_slave_groups - remainder) + (index - idx2) / (grp_sz + 1) ;
+		}
+		return grp_idx + (master_first ? 1 : 0);
+	}
+}
-- 
cgit v1.2.3


From 1f47c58d63130b8de59cb81422a4339bc0273273 Mon Sep 17 00:00:00 2001
From: wil <william.barsse@gmail.com>
Date: Sat, 7 Jan 2017 20:26:46 +0100
Subject: simplification of apply_auto_layout

Achieved by introducing auto_group_bounds function that produces
the start/end indexes of a group inside an auto layot container.
---
 include/sway/layout.h |   9 +--
 sway/layout.c         | 158 ++++++++++++++++++++++++++++----------------------
 2 files changed, 95 insertions(+), 72 deletions(-)

(limited to 'include')

diff --git a/include/sway/layout.h b/include/sway/layout.h
index c51fece9..fbedcdb3 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -76,9 +76,10 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
 enum swayc_layouts default_layout(swayc_t *output);
 
 bool is_auto_layout(enum swayc_layouts layout);
-int auto_group_start_index(swayc_t *container, int index);
-int auto_group_end_index(swayc_t *container, int index);
-size_t auto_group_count(swayc_t *container);
-size_t auto_group_index(swayc_t *container, int index);
+int auto_group_start_index(const swayc_t *container, int index);
+int auto_group_end_index(const swayc_t *container, int index);
+size_t auto_group_count(const swayc_t *container);
+size_t auto_group_index(const swayc_t *container, int index);
+bool auto_group_bounds(const swayc_t *container, size_t group_index, int *start, int *end);
 
 #endif
diff --git a/sway/layout.c b/sway/layout.c
index 78673cf9..6a2af2a6 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -1164,9 +1164,7 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 	//  a single slave group (containing slave 1 and 2). The master
 	//  group and slave group are layed out using L_VERT.
 
-	size_t nb_slaves = container->children->length - container->nb_master;
-	size_t nb_groups = (container->nb_master > 0 ? 1 : 0) +
-		MIN(container->nb_slave_groups, nb_slaves);
+	size_t nb_groups = auto_group_count(container);
 
 	// the target dimension of the container along the "major" axis, each
 	// group in the container will be layed out using "group_layout" along
@@ -1216,74 +1214,53 @@ void apply_auto_layout(swayc_t *container, const double x, const double y,
 	 * layout. */
 	double old_group_dim[nb_groups];
 	double old_dim = 0;
-	size_t group = 0;
-	for (int i = 0; i < container->children->length;) {
-		swayc_t *child = container->children->items[i];
-		double *dim = group_layout == L_HORIZ ? &child->height : &child->width;
-		if (*dim <= 0) {
-			// New child with uninitialized dimension
-			*dim = dim_maj;
-			if (nb_groups > 1) {
-				// child gets a dimension proportional to existing groups,
-				// it will be later scaled based on to the available size
-				// in the major axis.
-				*dim /= (nb_groups - 1);
+	for (size_t group = 0; group < nb_groups; ++group) {
+		int idx;
+		if (auto_group_bounds(container, group, &idx, NULL)) {
+			swayc_t *child = container->children->items[idx];
+			double *dim = group_layout == L_HORIZ ? &child->height : &child->width;
+			if (*dim <= 0) {
+				// New child with uninitialized dimension
+				*dim = dim_maj;
+				if (nb_groups > 1) {
+					// child gets a dimension proportional to existing groups,
+					// it will be later scaled based on to the available size
+					// in the major axis.
+					*dim /= (nb_groups - 1);
+				}
 			}
+			old_dim += *dim;
+			old_group_dim[group] = *dim;
 		}
-		if (i == 0 && container->nb_master > 0) {
-			i += container->nb_master;
-		} else {
-			i += (nb_slaves - i + container->nb_master) / (nb_groups - group);
-		}
-		old_dim += *dim;
-		old_group_dim[group++] = *dim;
 	}
-
 	double scale = dim_maj / old_dim;
 
 	/* Apply layout to each group */
 	pos = pos_maj;
 
-	// first child in the current group
-	int start;
-
-	// index immediately after the last child in the current group
-	int end = 0;
-
-	for (group = 0; group < nb_groups; ++group) {
-		// column to include next by increasing position.
-		size_t layout_group = master_first ? group : (group + 1) % nb_groups;
-
-		// adjusted size of the group
-		group_dim = old_group_dim[layout_group] * scale;
-		if (container->nb_master > 0 && layout_group == 0) {
-			start = 0;
-			end = MIN(container->nb_master, container->children->length);
-		} else {
-			if (group == 0) {
-				start = container->nb_master;
-			} else {
-				start = end;
+	for (size_t group = 0; group < nb_groups; ++group) {
+		int start, end;	// index of first (inclusive) and last (exclusive) child in the group
+		if (auto_group_bounds(container, group, &start, &end)) {
+			// adjusted size of the group
+			group_dim = old_group_dim[group] * scale;
+			if (group == nb_groups - 1) {
+				group_dim = pos_maj + dim_maj - pos; // remaining width
+			}
+			sway_log(L_DEBUG, "Arranging container %p column %zu, children [%d,%d[ (%fx%f+%f,%f)",
+				 container, group, start, end, *group_w, *group_h, *group_x, *group_y);
+			switch (group_layout) {
+			default:
+			case L_VERT:
+				apply_vert_layout(container, *group_x, *group_y, *group_w, *group_h, start, end);
+				break;
+			case L_HORIZ:
+				apply_horiz_layout(container, *group_x, *group_y, *group_w, *group_h, start, end);
+				break;
 			}
-			end = start + (nb_slaves - start + container->nb_master) / (nb_groups - layout_group);
-		}
-		if (group == nb_groups - 1) {
-			group_dim = pos_maj + dim_maj - pos; // remaining width
-		}
-		sway_log(L_DEBUG, "Arranging container %p column %zu, children [%d,%d[ (%fx%f+%f,%f)",
-			 container, group, start, end, *group_w, *group_h, *group_x, *group_y);
-		switch (group_layout) {
-		default:
-		case L_VERT:
-			apply_vert_layout(container, *group_x, *group_y, *group_w, *group_h, start, end);
-			break;
-		case L_HORIZ:
-			apply_horiz_layout(container, *group_x, *group_y, *group_w, *group_h, start, end);
-			break;
-		}
 
-		/* update position for next group */
-		pos += group_dim;
+			/* update position for next group */
+			pos += group_dim;
+		}
 	}
 }
 
@@ -1508,7 +1485,7 @@ bool is_auto_layout(enum swayc_layouts layout) {
 /**
  * Return the number of master elements in a container
  */
-static inline size_t auto_master_count(swayc_t *container) {
+static inline size_t auto_master_count(const swayc_t *container) {
 	return MIN(container->nb_master, container->children->length);
 }
 
@@ -1516,21 +1493,21 @@ static inline size_t auto_master_count(swayc_t *container) {
  * Return the number of children in the slave groups. This corresponds to the children
  * that are not members of the master group.
  */
-static inline size_t auto_slave_count(swayc_t *container) {
+static inline size_t auto_slave_count(const swayc_t *container) {
 	return container->children->length - auto_master_count(container);
 }
 
 /**
  * Return the number of slave groups in the container.
  */
-size_t auto_slave_group_count(swayc_t *container) {
+size_t auto_slave_group_count(const swayc_t *container) {
 	return MIN(container->nb_slave_groups, auto_slave_count(container));
 }
 
 /**
  * Return the combined number of master and slave groups in the container.
  */
-size_t auto_group_count(swayc_t *container) {
+size_t auto_group_count(const swayc_t *container) {
 	return auto_slave_group_count(container) + (container->nb_master ? 1 : 0);
 }
 
@@ -1538,7 +1515,7 @@ size_t auto_group_count(swayc_t *container) {
  * given the index of a container's child, return the index of the first child of the group
  * which index is a member of.
  */
-int auto_group_start_index(swayc_t *container, int index) {
+int auto_group_start_index(const swayc_t *container, int index) {
 	if (index < 0 || ! is_auto_layout(container->layout)
 		|| (size_t) index < container->nb_master) {
 		return 0;
@@ -1563,7 +1540,7 @@ int auto_group_start_index(swayc_t *container, int index) {
  * that follows the one which index is a member of.
  * This makes the function usable to walk through the groups in a container.
  */
-int auto_group_end_index(swayc_t *container, int index) {
+int auto_group_end_index(const swayc_t *container, int index) {
 	if (index < 0 || ! is_auto_layout(container->layout)) {
 		return container->children->length;
 	} else {
@@ -1590,7 +1567,7 @@ int auto_group_end_index(swayc_t *container, int index) {
  * return the index of the Group containing <index>th child of <container>.
  * The index is the order of the group along the container's major axis (starting at 0).
  */
-size_t auto_group_index(swayc_t *container, int index) {
+size_t auto_group_index(const swayc_t *container, int index) {
 	if (index < 0) {
 		return 0;
 	}
@@ -1616,3 +1593,48 @@ size_t auto_group_index(swayc_t *container, int index) {
 		return grp_idx + (master_first ? 1 : 0);
 	}
 }
+
+/**
+ * Return the first index (inclusive) and last index (exclusive) of the elements of a group in
+ * an auto layout.
+ * If the bounds of the given group can be calculated, they are returned in the start/end
+ * parameters (int pointers) and the return value will be true.
+ * The indexes are passed by reference and can be NULL.
+ */
+bool auto_group_bounds(const swayc_t *container, size_t group_index, int *start, int *end) {
+	size_t nb_grp = auto_group_count(container);
+	if (group_index >= nb_grp) {
+		return false;
+	}
+	bool master_first = (container->layout == L_AUTO_LEFT || container->layout == L_AUTO_TOP);
+	size_t nb_master = auto_master_count(container);
+	size_t nb_slave_grp = auto_slave_group_count(container);
+	int g_start, g_end;
+	if (nb_master && (master_first ? group_index == 0 : group_index == nb_grp - 1)) {
+		g_start = 0;
+		g_end = nb_master;
+	} else {
+		size_t nb_slaves = auto_slave_count(container);
+		size_t grp_sz = nb_slaves / nb_slave_grp;
+		size_t remainder = nb_slaves % nb_slave_grp;
+		size_t g0 = master_first && container->nb_master ? 1 : 0;
+		size_t g1 = g0 + nb_slave_grp - remainder;
+		if (group_index < g1) {
+			g_start = container->nb_master + (group_index - g0) * grp_sz;
+			g_end = g_start + grp_sz;
+		} else {
+			size_t g2 = group_index - g1;
+			g_start = container->nb_master
+				+ (nb_slave_grp - remainder) * grp_sz
+				+ g2 * (grp_sz + 1);
+			g_end = g_start + grp_sz + 1;
+		}
+	}
+	if (start) {
+		*start = g_start;
+	}
+	if (end) {
+		*end = g_end;
+	}
+	return true;
+}
-- 
cgit v1.2.3