aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2015-08-25 16:12:37 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2015-08-25 16:12:37 -0400
commitfa6292ff24082f90886353844b45e99ec965daa5 (patch)
tree06f9219532f6f057410910dbfe43d3884acd90bc
parentMerge pull request #125 from Luminarys/master (diff)
parentfixed moving to other output and visibility (diff)
downloadsway-fa6292ff24082f90886353844b45e99ec965daa5.tar.gz
sway-fa6292ff24082f90886353844b45e99ec965daa5.tar.zst
sway-fa6292ff24082f90886353844b45e99ec965daa5.zip
Merge pull request #129 from minus7/workspaces
Implemented "move container to workspace"
-rw-r--r--include/container.h7
-rw-r--r--include/layout.h1
-rw-r--r--include/util.h9
-rw-r--r--include/workspace.h8
-rw-r--r--sway.5.txt8
-rw-r--r--sway/commands.c33
-rw-r--r--sway/container.c17
-rw-r--r--sway/focus.c11
-rw-r--r--sway/handlers.c3
-rw-r--r--sway/layout.c15
-rw-r--r--sway/util.c5
-rw-r--r--sway/workspace.c143
12 files changed, 170 insertions, 90 deletions
diff --git a/include/container.h b/include/container.h
index aadba5de..798a31a2 100644
--- a/include/container.h
+++ b/include/container.h
@@ -56,6 +56,10 @@ struct sway_container {
56 struct sway_container *focused; 56 struct sway_container *focused;
57}; 57};
58 58
59enum visibility_mask {
60 VISIBLE = 1
61};
62
59// Container Creation 63// Container Creation
60 64
61swayc_t *new_output(wlc_handle handle); 65swayc_t *new_output(wlc_handle handle);
@@ -106,4 +110,7 @@ void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *);
106void set_view_visibility(swayc_t *view, void *data); 110void set_view_visibility(swayc_t *view, void *data);
107void reset_gaps(swayc_t *view, void *data); 111void reset_gaps(swayc_t *view, void *data);
108 112
113
114void update_visibility(swayc_t *container);
115
109#endif 116#endif
diff --git a/include/layout.h b/include/layout.h
index 11bf1a28..8cc26ba8 100644
--- a/include/layout.h
+++ b/include/layout.h
@@ -22,6 +22,7 @@ swayc_t *remove_child(swayc_t *child);
22void swap_container(swayc_t *a, swayc_t *b); 22void swap_container(swayc_t *a, swayc_t *b);
23 23
24void move_container(swayc_t* container,swayc_t* root,enum movement_direction direction); 24void move_container(swayc_t* container,swayc_t* root,enum movement_direction direction);
25void move_container_to(swayc_t* container, swayc_t* destination);
25 26
26// Layout 27// Layout
27void update_geometry(swayc_t *view); 28void update_geometry(swayc_t *view);
diff --git a/include/util.h b/include/util.h
new file mode 100644
index 00000000..8e65e6d6
--- /dev/null
+++ b/include/util.h
@@ -0,0 +1,9 @@
1#ifndef _SWAY_UTIL_H
2#define _SWAY_UTIL_H
3
4/**
5 * Wrap i into the range [0, max[
6 */
7int wrap(int i, int max);
8
9#endif
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.5.txt b/sway.5.txt
index 15a465c1..9747fb79 100644
--- a/sway.5.txt
+++ b/sway.5.txt
@@ -80,6 +80,10 @@ Commands
80**move** <left|right|up|down>:: 80**move** <left|right|up|down>::
81 Moves the focused container _left_, _right_, _up_, or _down_. 81 Moves the focused container _left_, _right_, _up_, or _down_.
82 82
83**move** <container|window> to workspace <name>::
84 Moves the focused container to the workspace identified by _name_.
85 _name_ may be a special workspace name. See **workspace**.
86
83**output** <name> <resolution|res WIDTHxHEIGHT> <position|pos X,Y>:: 87**output** <name> <resolution|res WIDTHxHEIGHT> <position|pos X,Y>::
84 Configures the specified output. It will use the given resolution and be 88 Configures the specified output. It will use the given resolution and be
85 arranged at the given position in the layout tree. You may omit either of 89 arranged at the given position in the layout tree. You may omit either of
@@ -111,6 +115,10 @@ Commands
111**workspace** <name>:: 115**workspace** <name>::
112 Switches to the specified workspace. 116 Switches to the specified workspace.
113 117
118**workspace** <prev|next>::
119 Switches to the next workspace on the current output or on the next output
120 if currently on the last workspace.
121
114**workspace** <prev_on_output|next_on_output>:: 122**workspace** <prev_on_output|next_on_output>::
115 Switches to the next workspace on the current output. 123 Switches to the next workspace on the current output.
116 124
diff --git a/sway/commands.c b/sway/commands.c
index 21ff5c7f..74c19b5b 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -344,7 +344,7 @@ static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char *
344} 344}
345 345
346static bool cmd_move(struct sway_config *config, int argc, char **argv) { 346static bool cmd_move(struct sway_config *config, int argc, char **argv) {
347 if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 1)) { 347 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
348 return false; 348 return false;
349 } 349 }
350 350
@@ -358,6 +358,29 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {
358 move_container(view,&root_container,MOVE_UP); 358 move_container(view,&root_container,MOVE_UP);
359 } else if (strcasecmp(argv[0], "down") == 0) { 359 } else if (strcasecmp(argv[0], "down") == 0) {
360 move_container(view,&root_container,MOVE_DOWN); 360 move_container(view,&root_container,MOVE_DOWN);
361 } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) {
362 // "move container to workspace x"
363 if (!checkarg(argc, "move container/window", EXPECTED_EQUAL_TO, 4) ||
364 strcasecmp(argv[1], "to") != 0 ||
365 strcasecmp(argv[2], "workspace") != 0) {
366 return false;
367 }
368
369 if (view->type != C_CONTAINER && view->type != C_VIEW) {
370 return false;
371 }
372
373 const char *ws_name = argv[3];
374 if (argc == 5) {
375 // move "container to workspace number x"
376 ws_name = argv[4];
377 }
378
379 swayc_t *ws = workspace_by_name(ws_name);
380 if (ws == NULL) {
381 ws = workspace_create(ws_name);
382 }
383 move_container_to(view, ws);
361 } else { 384 } else {
362 return false; 385 return false;
363 } 386 }
@@ -645,23 +668,23 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
645 if (argc == 1) { 668 if (argc == 1) {
646 // Handle workspace next/prev 669 // Handle workspace next/prev
647 if (strcmp(argv[0], "next") == 0) { 670 if (strcmp(argv[0], "next") == 0) {
648 workspace_next(); 671 workspace_switch(workspace_next());
649 return true; 672 return true;
650 } 673 }
651 674
652 if (strcmp(argv[0], "prev") == 0) { 675 if (strcmp(argv[0], "prev") == 0) {
653 workspace_next(); 676 workspace_switch(workspace_prev());
654 return true; 677 return true;
655 } 678 }
656 679
657 // Handle workspace output_next/prev 680 // Handle workspace output_next/prev
658 if (strcmp(argv[0], "next_on_output") == 0) { 681 if (strcmp(argv[0], "next_on_output") == 0) {
659 workspace_output_next(); 682 workspace_switch(workspace_output_next());
660 return true; 683 return true;
661 } 684 }
662 685
663 if (strcmp(argv[0], "prev_on_output") == 0) { 686 if (strcmp(argv[0], "prev_on_output") == 0) {
664 workspace_output_prev(); 687 workspace_switch(workspace_output_prev());
665 return true; 688 return true;
666 } 689 }
667 690
diff --git a/sway/container.c b/sway/container.c
index d23cef8f..6fbfa360 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -520,16 +520,25 @@ void set_view_visibility(swayc_t *view, void *data) {
520 if (!ASSERT_NONNULL(view)) { 520 if (!ASSERT_NONNULL(view)) {
521 return; 521 return;
522 } 522 }
523 uint32_t *p = data; 523 bool visible = *(bool *)data;
524 if (view->type == C_VIEW) { 524 if (view->type == C_VIEW) {
525 wlc_view_set_mask(view->handle, *p); 525 wlc_view_set_output(view->handle, swayc_parent_by_type(view, C_OUTPUT)->handle);
526 if (*p == 2) { 526 wlc_view_set_mask(view->handle, visible ? VISIBLE : 0);
527 if (visible) {
527 wlc_view_bring_to_front(view->handle); 528 wlc_view_bring_to_front(view->handle);
528 } else { 529 } else {
529 wlc_view_send_to_back(view->handle); 530 wlc_view_send_to_back(view->handle);
530 } 531 }
531 } 532 }
532 view->visible = (*p == 2); 533 view->visible = visible;
534 sway_log(L_DEBUG, "Container %p is now %s", view, visible ? "visible" : "invisible");
535}
536
537void update_visibility(swayc_t *container) {
538 swayc_t *ws = swayc_active_workspace_for(container);
539 bool visible = (ws->parent->focused == ws);
540 sway_log(L_DEBUG, "Setting visibility of container %p to %s", container, visible ? "visible" : "invisible");
541 container_map(ws, set_view_visibility, &visible);
533} 542}
534 543
535void reset_gaps(swayc_t *view, void *data) { 544void reset_gaps(swayc_t *view, void *data) {
diff --git a/sway/focus.c b/sway/focus.c
index e369de30..1086f1a8 100644
--- a/sway/focus.c
+++ b/sway/focus.c
@@ -28,12 +28,11 @@ static void update_focus(swayc_t *c) {
28 if (parent->focused) { 28 if (parent->focused) {
29 swayc_t *ws = parent->focused; 29 swayc_t *ws = parent->focused;
30 // hide visibility of old workspace 30 // hide visibility of old workspace
31 uint32_t mask = 1; 31 bool visible = false;
32 container_map(ws, set_view_visibility, &mask); 32 container_map(ws, set_view_visibility, &visible);
33 // set visibility of new workspace 33 // set visibility of new workspace
34 mask = 2; 34 visible = true;
35 container_map(c, set_view_visibility, &mask); 35 container_map(c, set_view_visibility, &visible);
36 wlc_output_set_mask(parent->handle, 2);
37 destroy_workspace(ws); 36 destroy_workspace(ws);
38 } 37 }
39 break; 38 break;
@@ -45,8 +44,8 @@ static void update_focus(swayc_t *c) {
45 // for example, stacked and tabbing change stuff. 44 // for example, stacked and tabbing change stuff.
46 break; 45 break;
47 } 46 }
47 c->parent->focused = c;
48 } 48 }
49 c->parent->focused = c;
50} 49}
51 50
52bool move_focus(enum movement_direction direction) { 51bool move_focus(enum movement_direction direction) {
diff --git a/sway/handlers.c b/sway/handlers.c
index 3a4e31ae..af68b765 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -90,6 +90,9 @@ swayc_t *container_under_pointer(void) {
90static bool handle_output_created(wlc_handle output) { 90static bool handle_output_created(wlc_handle output) {
91 swayc_t *op = new_output(output); 91 swayc_t *op = new_output(output);
92 92
93 // Visibility mask to be able to make view invisible
94 wlc_output_set_mask(output, VISIBLE);
95
93 if (!op) { 96 if (!op) {
94 return false; 97 return false;
95 } 98 }
diff --git a/sway/layout.c b/sway/layout.c
index a37e137c..cd47037b 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -203,6 +203,21 @@ void move_container(swayc_t *container,swayc_t* root,enum movement_direction dir
203 203
204} 204}
205 205
206void move_container_to(swayc_t* container, swayc_t* destination) {
207 if (container->parent == destination) {
208 return;
209 }
210 destroy_container(remove_child(container));
211 set_focused_container(get_focused_view(&root_container));
212 if (container->is_floating) {
213 add_floating(destination, container);
214 } else {
215 add_child(destination, container);
216 }
217 update_visibility(container);
218 arrange_windows(&root_container, -1, -1);
219}
220
206void update_geometry(swayc_t *container) { 221void update_geometry(swayc_t *container) {
207 if (container->type != C_VIEW) { 222 if (container->type != C_VIEW) {
208 return; 223 return;
diff --git a/sway/util.c b/sway/util.c
new file mode 100644
index 00000000..9a59ddf9
--- /dev/null
+++ b/sway/util.c
@@ -0,0 +1,5 @@
1#include "util.h"
2
3int wrap(int i, int max) {
4 return ((i % max) + max) % max;
5}
diff --git a/sway/workspace.c b/sway/workspace.c
index 4c8bb62f..252526ce 100644
--- a/sway/workspace.c
+++ b/sway/workspace.c
@@ -11,6 +11,7 @@
11#include "config.h" 11#include "config.h"
12#include "stringop.h" 12#include "stringop.h"
13#include "focus.h" 13#include "focus.h"
14#include "util.h"
14 15
15char *workspace_next_name(void) { 16char *workspace_next_name(void) {
16 sway_log(L_DEBUG, "Workspace: Generating new name"); 17 sway_log(L_DEBUG, "Workspace: Generating new name");
@@ -84,95 +85,95 @@ static bool _workspace_by_name(swayc_t *view, void *data) {
84} 85}
85 86
86swayc_t *workspace_by_name(const char* name) { 87swayc_t *workspace_by_name(const char* name) {
87 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 }
88} 106}
89 107
90void workspace_output_next() { 108/**
91 // 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.
92 // if we're currently focused on the last workspace in the output, switch to the first 110 * Wraps around at the end and beginning.
93 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
94 int i; 118 int i;
95 for (i = 0; i < current_output->children->length - 1; i++) { 119 for (i = 0; i < output->children->length; i++) {
96 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { 120 if (output->children->items[i] == output->focused) {
97 workspace_switch(current_output->children->items[i + 1]); 121 return output->children->items[wrap(i + (next ? 1 : -1), output->children->length)];
98 return;
99 } 122 }
100 } 123 }
101 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;
102} 127}
103 128
104void workspace_next() { 129/**
105 // Get the index of the workspace in the current output, and change the view to index+1 workspace. 130 * Get the previous or next workspace. If the first/last workspace on an output is active,
106 // if we're currently focused on the last workspace in the output, change focus to there 131 * proceed to the previous/next output's previous/next workspace.
107 // and call workspace_output_next(), as long as another output actually exists 132 * If next is false, the previous workspace is returned, otherwise the next one is returned.
108 swayc_t *current_output = swayc_active_workspace()->parent; 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 }
138
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;
109 int i; 143 int i;
110 for (i = 0; i < current_output->children->length - 1; i++) { 144 for (i = start; i < end; i++) {
111 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { 145 if (current_output->children->items[i] == workspace) {
112 workspace_switch(current_output->children->items[i + 1]); 146 return current_output->children->items[i + offset];
113 return;
114 } 147 }
115 } 148 }
116 if (root_container.children->length > 1) { 149
117 for (i = 0; i < root_container.children->length - 1; i++) { 150 // Given workspace is the first/last on the output, jump to the previous/next output
118 if (root_container.children->items[i] == current_output) { 151 int num_outputs = root_container.children->length;
119 workspace_switch(((swayc_t *)root_container.children->items[i + 1])->focused); 152 for (i = 0; i < num_outputs; i++) {
120 workspace_output_next(); 153 if (root_container.children->items[i] == current_output) {
121 return; 154 swayc_t *next_output = root_container.children->items[wrap(i + offset, num_outputs)];
122 } 155 return workspace_output_prev_next_impl(next_output, next);
123 } 156 }
124 // If we're at the last output, then go to the first
125 workspace_switch(((swayc_t *)root_container.children->items[0])->focused);
126 workspace_output_next();
127 return;
128 } else {
129 workspace_switch(current_output->children->items[0]);
130 } 157 }
158
159 // Doesn't happen, at worst the for loop returns the previously active workspace on the active output
160 return NULL;
131} 161}
132 162
133void workspace_output_prev() { 163swayc_t *workspace_output_next() {
134 // 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);
135 // if we're currently focused on the first workspace in the output, do nothing and return false
136 swayc_t *current_output = swayc_active_workspace()->parent;
137 int i;
138 for (i = 1; i < current_output->children->length; i++) {
139 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) {
140 workspace_switch(current_output->children->items[i - 1]);
141 return;
142 }
143 }
144 workspace_switch(current_output->children->items[current_output->children->length - 1]);
145} 165}
146 166
147void workspace_prev() { 167swayc_t *workspace_next() {
148 // Get the index of the workspace in the current output, and change the view to index-1 workspace. 168 return workspace_prev_next_impl(swayc_active_workspace(), true);
149 // if we're currently focused on the last workspace in the output, change focus to there 169}
150 // and call workspace_output_next(), as long as another output actually exists
151 170
152 swayc_t *current_output = swayc_active_workspace()->parent; 171swayc_t *workspace_output_prev() {
153 int i; 172 return workspace_output_prev_next_impl(swayc_active_output(), false);
154 for (i = 1; i < current_output->children->length; i++) { 173}
155 if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) {
156 workspace_switch(current_output->children->items[i - 1]);
157 return;
158 }
159 }
160 if (root_container.children->length > 1) {
161 for (i = 1; i < root_container.children->length; i++) {
162 if (root_container.children->items[i] == current_output) {
163 workspace_switch(((swayc_t *)root_container.children->items[i - 1])->focused);
164 workspace_output_next();
165 return;
166 }
167 }
168 // If we're at the first output, then go to the last
169 workspace_switch(((swayc_t *)root_container.children->items[root_container.children->length-1])->focused);
170 workspace_output_next();
171 return;
172 } else {
173 workspace_switch(current_output->children->items[current_output->children->length - 1]);
174 }
175 174
175swayc_t *workspace_prev() {
176 return workspace_prev_next_impl(swayc_active_workspace(), false);
176} 177}
177 178
178void workspace_switch(swayc_t *workspace) { 179void workspace_switch(swayc_t *workspace) {