summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/workspace.h8
-rw-r--r--sway/commands.c8
-rw-r--r--sway/workspace.c122
3 files changed, 74 insertions, 64 deletions
diff --git a/include/workspace.h b/include/workspace.h
index d447ac2d..a731068d 100644
--- a/include/workspace.h
+++ b/include/workspace.h
@@ -9,9 +9,9 @@ char *workspace_next_name(void);
9swayc_t *workspace_create(const char*); 9swayc_t *workspace_create(const char*);
10swayc_t *workspace_by_name(const char*); 10swayc_t *workspace_by_name(const char*);
11void workspace_switch(swayc_t*); 11void workspace_switch(swayc_t*);
12void workspace_output_next(); 12swayc_t *workspace_output_next();
13void workspace_next(); 13swayc_t *workspace_next();
14void workspace_output_prev(); 14swayc_t *workspace_output_prev();
15void workspace_prev(); 15swayc_t *workspace_prev();
16 16
17#endif 17#endif
diff --git a/sway/commands.c b/sway/commands.c
index 23339b9d..74c19b5b 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -668,23 +668,23 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
668 if (argc == 1) { 668 if (argc == 1) {
669 // Handle workspace next/prev 669 // Handle workspace next/prev
670 if (strcmp(argv[0], "next") == 0) { 670 if (strcmp(argv[0], "next") == 0) {
671 workspace_next(); 671 workspace_switch(workspace_next());
672 return true; 672 return true;
673 } 673 }
674 674
675 if (strcmp(argv[0], "prev") == 0) { 675 if (strcmp(argv[0], "prev") == 0) {
676 workspace_next(); 676 workspace_switch(workspace_prev());
677 return true; 677 return true;
678 } 678 }
679 679
680 // Handle workspace output_next/prev 680 // Handle workspace output_next/prev
681 if (strcmp(argv[0], "next_on_output") == 0) { 681 if (strcmp(argv[0], "next_on_output") == 0) {
682 workspace_output_next(); 682 workspace_switch(workspace_output_next());
683 return true; 683 return true;
684 } 684 }
685 685
686 if (strcmp(argv[0], "prev_on_output") == 0) { 686 if (strcmp(argv[0], "prev_on_output") == 0) {
687 workspace_output_prev(); 687 workspace_switch(workspace_output_prev());
688 return true; 688 return true;
689 } 689 }
690 690
diff --git a/sway/workspace.c b/sway/workspace.c
index ca9f5ef0..252526ce 100644
--- a/sway/workspace.c
+++ b/sway/workspace.c
@@ -85,85 +85,95 @@ static bool _workspace_by_name(swayc_t *view, void *data) {
85} 85}
86 86
87swayc_t *workspace_by_name(const char* name) { 87swayc_t *workspace_by_name(const char* name) {
88 return swayc_by_test(&root_container, _workspace_by_name, (void *) name); 88 if (strcmp(name, "prev") == 0) {
89 return workspace_prev();
90 }
91 else if (strcmp(name, "prev_on_output") == 0) {
92 return workspace_output_prev();
93 }
94 else if (strcmp(name, "next") == 0) {
95 return workspace_next();
96 }
97 else if (strcmp(name, "next_on_output") == 0) {
98 return workspace_output_next();
99 }
100 else if (strcmp(name, "current") == 0) {
101 return swayc_active_workspace();
102 }
103 else {
104 return swayc_by_test(&root_container, _workspace_by_name, (void *) name);
105 }
89} 106}
90 107
91void workspace_output_next() { 108/**
92 // Get the index of the workspace in the current output, and change the view to index+1 workspace. 109 * Get the previous or next workspace on the specified output.
93 // if we're currently focused on the last workspace in the output, switch to the first 110 * Wraps around at the end and beginning.
94 swayc_t *current_output = swayc_active_workspace()->parent; 111 * If next is false, the previous workspace is returned, otherwise the next one is returned.
112 */
113swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) {
114 if (!sway_assert(output->type == C_OUTPUT, "Argument must be an output, is %d", output->type)) {
115 return NULL;
116 }
117
95 int i; 118 int i;
96 for (i = 0; i < current_output->children->length - 1; i++) { 119 for (i = 0; i < output->children->length; i++) {
97 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { 120 if (output->children->items[i] == output->focused) {
98 workspace_switch(current_output->children->items[i + 1]); 121 return output->children->items[wrap(i + (next ? 1 : -1), output->children->length)];
99 return;
100 } 122 }
101 } 123 }
102 workspace_switch(current_output->children->items[0]); 124
125 // Doesn't happen, at worst the for loop returns the previously active workspace
126 return NULL;
103} 127}
104 128
105void workspace_next() { 129/**
106 // Get the index of the workspace in the current output, and change the focus to index+1 workspace. 130 * Get the previous or next workspace. If the first/last workspace on an output is active,
107 // if we're currently focused on the last workspace in the output, change focus to the next output 131 * proceed to the previous/next output's previous/next workspace.
108 // and call workspace_output_next() 132 * If next is false, the previous workspace is returned, otherwise the next one is returned.
133 */
134swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) {
135 if (!sway_assert(workspace->type == C_WORKSPACE, "Argument must be a workspace, is %d", workspace->type)) {
136 return NULL;
137 }
109 138
110 swayc_t *current_output = swayc_active_workspace()->parent; 139 swayc_t *current_output = workspace->parent;
140 int offset = next ? 1 : -1;
141 int start = next ? 0 : 1;
142 int end = next ? (current_output->children->length) - 1 : current_output->children->length;
111 int i; 143 int i;
112 for (i = 0; i < current_output->children->length - 1; i++) { 144 for (i = start; i < end; i++) {
113 if (current_output->children->items[i] == swayc_active_workspace()) { 145 if (current_output->children->items[i] == workspace) {
114 workspace_switch(current_output->children->items[i + 1]); 146 return current_output->children->items[i + offset];
115 return;
116 } 147 }
117 } 148 }
118 149
150 // Given workspace is the first/last on the output, jump to the previous/next output
119 int num_outputs = root_container.children->length; 151 int num_outputs = root_container.children->length;
120 for (i = 0; i < num_outputs; i++) { 152 for (i = 0; i < num_outputs; i++) {
121 if (root_container.children->items[i] == current_output) { 153 if (root_container.children->items[i] == current_output) {
122 swayc_t *next_output = root_container.children->items[wrap(++i, num_outputs)]; 154 swayc_t *next_output = root_container.children->items[wrap(i + offset, num_outputs)];
123 workspace_switch(next_output->focused); 155 return workspace_output_prev_next_impl(next_output, next);
124 workspace_output_next();
125 return;
126 } 156 }
127 } 157 }
158
159 // Doesn't happen, at worst the for loop returns the previously active workspace on the active output
160 return NULL;
128} 161}
129 162
130void workspace_output_prev() { 163swayc_t *workspace_output_next() {
131 // Get the index of the workspace in the current output, and change the view to index+1 workspace 164 return workspace_output_prev_next_impl(swayc_active_output(), true);
132 // if we're currently focused on the first workspace in the output, do nothing and return false
133 swayc_t *current_output = swayc_active_workspace()->parent;
134 int i;
135 for (i = 1; i < current_output->children->length; i++) {
136 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) {
137 workspace_switch(current_output->children->items[i - 1]);
138 return;
139 }
140 }
141 workspace_switch(current_output->children->items[current_output->children->length - 1]);
142} 165}
143 166
144void workspace_prev() { 167swayc_t *workspace_next() {
145 // Get the index of the workspace in the current output, and change the focus to index-1 workspace. 168 return workspace_prev_next_impl(swayc_active_workspace(), true);
146 // if we're currently focused on the first workspace in the output, change focus to the previous output 169}
147 // and call workspace_output_prev()
148 170
149 swayc_t *current_output = swayc_active_workspace()->parent; 171swayc_t *workspace_output_prev() {
150 int i; 172 return workspace_output_prev_next_impl(swayc_active_output(), false);
151 for (i = 1; i < current_output->children->length; i++) { 173}
152 if (current_output->children->items[i] == swayc_active_workspace()) {
153 workspace_switch(current_output->children->items[i - 1]);
154 return;
155 }
156 }
157 174
158 int num_outputs = root_container.children->length; 175swayc_t *workspace_prev() {
159 for (i = 0; i < num_outputs; i++) { 176 return workspace_prev_next_impl(swayc_active_workspace(), false);
160 if (root_container.children->items[i] == current_output) {
161 swayc_t *prev_output = root_container.children->items[wrap(--i, num_outputs)];
162 workspace_switch(prev_output->focused);
163 workspace_output_prev();
164 return;
165 }
166 }
167} 177}
168 178
169void workspace_switch(swayc_t *workspace) { 179void workspace_switch(swayc_t *workspace) {