From 0a0fe18fd6126941b3518652c935da1d81249a19 Mon Sep 17 00:00:00 2001
From: Luminarys <kizunanohikari@gmail.com>
Date: Sun, 16 Aug 2015 14:50:01 -0500
Subject: [PATCH] Added in workspace next/prev and workspace output_next/prev

---
 include/workspace.h |  4 +++
 sway/commands.c     | 22 ++++++++++++
 sway/workspace.c    | 88 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+)

diff --git a/include/workspace.h b/include/workspace.h
index 59a6d526..8ce39bbd 100644
--- a/include/workspace.h
+++ b/include/workspace.h
@@ -11,6 +11,10 @@ char *workspace_next_name(void);
 swayc_t *workspace_create(const char*);
 swayc_t *workspace_find_by_name(const char*);
 void workspace_switch(swayc_t*);
+void workspace_output_next();
+void workspace_next();
+void workspace_output_prev();
+void workspace_prev();
 void layout_log(const swayc_t *c, int depth);
 
 #endif
diff --git a/sway/commands.c b/sway/commands.c
index 5cb661eb..91fadb86 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -342,6 +342,28 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
 		return false;
 	}
 
+	// Handle workspace next/prev
+	if (strcmp(argv[0], "next") == 0) {
+		workspace_next();
+		return true;
+	}
+
+	if (strcmp(argv[0], "prev") == 0) {
+		workspace_next();
+		return true;
+	}
+
+	// Handle workspace output_next/prev
+	if (strcmp(argv[0], "output_next") == 0) {
+		workspace_output_next();
+		return true;
+	}
+
+	if (strcmp(argv[0], "output_prev") == 0) {
+		workspace_output_prev();
+		return true;
+	}
+
 	swayc_t *workspace = workspace_find_by_name(argv[0]);
 	if (!workspace) {
 		workspace = workspace_create(argv[0]);
diff --git a/sway/workspace.c b/sway/workspace.c
index 49a1224f..a3238da6 100644
--- a/sway/workspace.c
+++ b/sway/workspace.c
@@ -93,6 +93,94 @@ swayc_t *workspace_find_by_name(const char* name) {
 	return find_container(&root_container, workspace_by_name, (void *) name);
 }
 
+void workspace_output_next() {
+	// Get the index of the workspace in the current output, and change the view to index+1 workspace.
+	// if we're currently focused on the last workspace in the output, switch to the first
+	swayc_t *current_output = active_workspace->parent;
+	int i;
+	for (i = 0; i < current_output->children->length - 1; i++) {
+		if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) {
+			workspace_switch(current_output->children->items[i + 1]);
+			return;
+		}
+	}
+	workspace_switch(current_output->children->items[0]);
+}
+
+void workspace_next() {
+	// Get the index of the workspace in the current output, and change the view to index+1 workspace.
+	// if we're currently focused on the last workspace in the output, change focus to there
+	// and call workspace_output_next(), as long as another output actually exists
+	swayc_t *current_output = active_workspace->parent;
+	int i;
+	for (i = 0; i < current_output->children->length - 1; i++) {
+		if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) {
+			workspace_switch(current_output->children->items[i + 1]);
+			return;
+		}
+	}
+	if (root_container.children->length > 1) {
+		for (i = 0; i < root_container.children->length - 1; i++) {
+			if (root_container.children->items[i] == current_output) {
+				workspace_switch(((swayc_t *)root_container.children->items[i + 1])->focused);
+				workspace_output_next();
+				return;
+			}
+		}
+		// If we're at the last output, then go to the first
+		workspace_switch(((swayc_t *)root_container.children->items[0])->focused);
+		workspace_output_next();
+		return;
+	} else {
+		workspace_switch(current_output->children->items[0]);
+	}
+}
+
+void workspace_output_prev() {
+	// Get the index of the workspace in the current output, and change the view to index+1 workspace
+	// if we're currently focused on the first workspace in the output, do nothing and return false
+	swayc_t *current_output = active_workspace->parent;
+	int i;
+	for (i = 1; i < current_output->children->length; i++) {
+		if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) {
+			workspace_switch(current_output->children->items[i - 1]);
+			return;
+		}
+	}
+	workspace_switch(current_output->children->items[current_output->children->length - 1]);
+}
+
+void workspace_prev() {
+	// Get the index of the workspace in the current output, and change the view to index-1 workspace.
+	// if we're currently focused on the last workspace in the output, change focus to there
+	// and call workspace_output_next(), as long as another output actually exists
+
+	swayc_t *current_output = active_workspace->parent;
+	int i;
+	for (i = 1; i < current_output->children->length; i++) {
+		if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) {
+			workspace_switch(current_output->children->items[i - 1]);
+			return;
+		}
+	}
+	if (root_container.children->length > 1) {
+		for (i = 1; i < root_container.children->length; i++) {
+			if (root_container.children->items[i] == current_output) {
+				workspace_switch(((swayc_t *)root_container.children->items[i - 1])->focused);
+				workspace_output_next();
+				return;
+			}
+		}
+		// If we're at the first output, then go to the last
+		workspace_switch(((swayc_t *)root_container.children->items[root_container.children->length-1])->focused);
+		workspace_output_next();
+		return;
+	} else {
+		workspace_switch(current_output->children->items[current_output->children->length - 1]);
+	}
+
+}
+
 void workspace_switch(swayc_t *workspace) {
 	swayc_t *ws_output = workspace->parent;
 	while (ws_output->type != C_OUTPUT) {