diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-01-14 16:11:48 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-14 16:11:48 -0500 |
commit | 81102e8eacbf72ad0c5e81c935a957a8824a0922 (patch) | |
tree | f8b51dd1f5214966ad30b0bd7b561afa70dcb4dc /sway/commands | |
parent | Merge pull request #1048 from dkess/proper-output-wrapping (diff) | |
parent | Move awesome config to contrib/ (diff) | |
download | sway-81102e8eacbf72ad0c5e81c935a957a8824a0922.tar.gz sway-81102e8eacbf72ad0c5e81c935a957a8824a0922.tar.zst sway-81102e8eacbf72ad0c5e81c935a957a8824a0922.zip |
Merge pull request #1024 from willakat/master
Add Awesome/Monad style automatic layouts to Sway
Diffstat (limited to 'sway/commands')
-rw-r--r-- | sway/commands/focus.c | 4 | ||||
-rw-r--r-- | sway/commands/layout.c | 127 | ||||
-rw-r--r-- | sway/commands/move.c | 8 | ||||
-rw-r--r-- | sway/commands/resize.c | 313 | ||||
-rw-r--r-- | sway/commands/workspace_layout.c | 23 |
5 files changed, 270 insertions, 205 deletions
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) { | |||
46 | move_focus(MOVE_PARENT); | 46 | move_focus(MOVE_PARENT); |
47 | } else if (strcasecmp(argv[0], "child") == 0) { | 47 | } else if (strcasecmp(argv[0], "child") == 0) { |
48 | move_focus(MOVE_CHILD); | 48 | move_focus(MOVE_CHILD); |
49 | } else if (strcasecmp(argv[0], "next") == 0) { | ||
50 | move_focus(MOVE_NEXT); | ||
51 | } else if (strcasecmp(argv[0], "prev") == 0) { | ||
52 | move_focus(MOVE_PREV); | ||
49 | } else if (strcasecmp(argv[0], "mode_toggle") == 0) { | 53 | } else if (strcasecmp(argv[0], "mode_toggle") == 0) { |
50 | int i; | 54 | int i; |
51 | swayc_t *workspace = swayc_active_workspace(); | 55 | swayc_t *workspace = swayc_active_workspace(); |
diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 08336150..d04bb4dc 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c | |||
@@ -3,6 +3,11 @@ | |||
3 | #include "sway/container.h" | 3 | #include "sway/container.h" |
4 | #include "sway/layout.h" | 4 | #include "sway/layout.h" |
5 | 5 | ||
6 | /** | ||
7 | * handle "layout auto" command group | ||
8 | */ | ||
9 | static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv); | ||
10 | |||
6 | struct cmd_results *cmd_layout(int argc, char **argv) { | 11 | struct cmd_results *cmd_layout(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 12 | struct cmd_results *error = NULL; |
8 | if (config->reading) return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); | 13 | if (config->reading) return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); |
@@ -49,11 +54,14 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
49 | } else if (strcasecmp(argv[0], "splitv") == 0) { | 54 | } else if (strcasecmp(argv[0], "splitv") == 0) { |
50 | swayc_change_layout(parent, L_VERT); | 55 | swayc_change_layout(parent, L_VERT); |
51 | } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { | 56 | } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { |
52 | if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) { | 57 | if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE |
58 | || parent->workspace_layout == L_HORIZ)) { | ||
53 | swayc_change_layout(parent, L_VERT); | 59 | swayc_change_layout(parent, L_VERT); |
54 | } else { | 60 | } else { |
55 | swayc_change_layout(parent, L_HORIZ); | 61 | swayc_change_layout(parent, L_HORIZ); |
56 | } | 62 | } |
63 | } else if (strcasecmp(argv[0], "auto") == 0) { | ||
64 | return cmd_layout_auto(parent, argc, argv); | ||
57 | } | 65 | } |
58 | } | 66 | } |
59 | 67 | ||
@@ -64,3 +72,120 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
64 | 72 | ||
65 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 73 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
66 | } | 74 | } |
75 | |||
76 | static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv) { | ||
77 | // called after checking that argv[0] is auto, so just continue parsing from there | ||
78 | struct cmd_results *error = NULL; | ||
79 | const char *cmd_name = "layout auto"; | ||
80 | const char *set_inc_cmd_name = "layout auto [master|ncol] [set|inc]"; | ||
81 | const char *err_msg = "Allowed arguments are <right|left|top|bottom|next|prev|master|ncol>"; | ||
82 | |||
83 | bool need_layout_update = false; | ||
84 | enum swayc_layouts old_layout = container->layout; | ||
85 | enum swayc_layouts layout = old_layout; | ||
86 | |||
87 | if (strcasecmp(argv[1], "left") == 0) { | ||
88 | layout = L_AUTO_LEFT; | ||
89 | } else if (strcasecmp(argv[1], "right") == 0) { | ||
90 | layout = L_AUTO_RIGHT; | ||
91 | } else if (strcasecmp(argv[1], "top") == 0) { | ||
92 | layout = L_AUTO_TOP; | ||
93 | } else if (strcasecmp(argv[1], "bottom") == 0) { | ||
94 | layout = L_AUTO_BOTTOM; | ||
95 | } else if (strcasecmp(argv[1], "next") == 0) { | ||
96 | if (is_auto_layout(container->layout) && container->layout < L_AUTO_LAST) { | ||
97 | layout = container->layout + 1; | ||
98 | } else { | ||
99 | layout = L_AUTO_FIRST; | ||
100 | } | ||
101 | } else if (strcasecmp(argv[1], "prev") == 0) { | ||
102 | if (is_auto_layout(container->layout) && container->layout > L_AUTO_FIRST) { | ||
103 | layout = container->layout - 1; | ||
104 | } else { | ||
105 | layout = L_AUTO_LAST; | ||
106 | } | ||
107 | } else { | ||
108 | bool is_nmaster; | ||
109 | bool is_set; | ||
110 | if (strcasecmp(argv[1], "master") == 0) { | ||
111 | is_nmaster = true; | ||
112 | } else if (strcasecmp(argv[1], "ncol") == 0) { | ||
113 | is_nmaster = false; | ||
114 | } else { | ||
115 | return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command. %s", | ||
116 | cmd_name, err_msg); | ||
117 | } | ||
118 | if ((error = checkarg(argc, "auto <master|ncol>", EXPECTED_EQUAL_TO, 4))) { | ||
119 | return error; | ||
120 | } | ||
121 | if (strcasecmp(argv[2], "set") == 0) { | ||
122 | is_set = true; | ||
123 | } else if (strcasecmp(argv[2], "inc") == 0) { | ||
124 | is_set = false; | ||
125 | } else { | ||
126 | return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command. %s, " | ||
127 | "Argument must be on of <set|inc>", | ||
128 | set_inc_cmd_name); | ||
129 | } | ||
130 | char *end; | ||
131 | int n = (int)strtol(argv[3], &end, 10); | ||
132 | if (*end) { | ||
133 | return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " | ||
134 | "(argument must be an integer)", set_inc_cmd_name); | ||
135 | } | ||
136 | if (is_auto_layout(container->layout)) { | ||
137 | int inc = 0; /* difference between current master/ncol and requested value */ | ||
138 | if (is_nmaster) { | ||
139 | if (is_set) { | ||
140 | if (n < 0) { | ||
141 | return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " | ||
142 | "(master must be >= 0)", set_inc_cmd_name); | ||
143 | } | ||
144 | inc = n - (int)container->nb_master; | ||
145 | } else { /* inc command */ | ||
146 | if ((int)container->nb_master + n >= 0) { | ||
147 | inc = n; | ||
148 | } | ||
149 | } | ||
150 | if (inc) { | ||
151 | for (int i = container->nb_master; | ||
152 | i >= 0 && i < container->children->length | ||
153 | && i != (int)container->nb_master + inc;) { | ||
154 | ((swayc_t *)container->children->items[i])->height = -1; | ||
155 | ((swayc_t *)container->children->items[i])->width = -1; | ||
156 | i += inc > 0 ? 1 : -1; | ||
157 | } | ||
158 | container->nb_master += inc; | ||
159 | need_layout_update = true; | ||
160 | } | ||
161 | } else { /* ncol modification */ | ||
162 | if (is_set) { | ||
163 | if (n <= 0) { | ||
164 | return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command " | ||
165 | "(ncol must be > 0)", set_inc_cmd_name); | ||
166 | } | ||
167 | inc = n - (int)container->nb_slave_groups; | ||
168 | } else { /* inc command */ | ||
169 | if ((int)container->nb_slave_groups + n > 0) { | ||
170 | inc = n; | ||
171 | } | ||
172 | } | ||
173 | if (inc) { | ||
174 | container->nb_slave_groups += inc; | ||
175 | need_layout_update = true; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | if (layout != old_layout) { | ||
182 | swayc_change_layout(container, layout); | ||
183 | update_layout_geometry(container, old_layout); | ||
184 | need_layout_update = true; | ||
185 | } | ||
186 | if (need_layout_update) { | ||
187 | update_geometry(container); | ||
188 | arrange_windows(container, container->width, container->height); | ||
189 | } | ||
190 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
191 | } | ||
diff --git a/sway/commands/move.c b/sway/commands/move.c index 4819d9ef..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) { | |||
13 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { | 13 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { |
14 | return error; | 14 | return error; |
15 | } | 15 | } |
16 | const char* expected_syntax = "Expected 'move <left|right|up|down>' or " | 16 | const char* expected_syntax = "Expected 'move <left|right|up|down|next|prev|first>' or " |
17 | "'move <container|window> to workspace <name>' or " | 17 | "'move <container|window> to workspace <name>' or " |
18 | "'move <container|window|workspace> to output <name|direction>' or " | 18 | "'move <container|window|workspace> to output <name|direction>' or " |
19 | "'move position mouse'"; | 19 | "'move position mouse'"; |
@@ -27,6 +27,12 @@ struct cmd_results *cmd_move(int argc, char **argv) { | |||
27 | move_container(view, MOVE_UP); | 27 | move_container(view, MOVE_UP); |
28 | } else if (strcasecmp(argv[0], "down") == 0) { | 28 | } else if (strcasecmp(argv[0], "down") == 0) { |
29 | move_container(view, MOVE_DOWN); | 29 | move_container(view, MOVE_DOWN); |
30 | } else if (strcasecmp(argv[0], "next") == 0) { | ||
31 | move_container(view, MOVE_NEXT); | ||
32 | } else if (strcasecmp(argv[0], "prev") == 0) { | ||
33 | move_container(view, MOVE_PREV); | ||
34 | } else if (strcasecmp(argv[0], "first") == 0) { | ||
35 | move_container(view, MOVE_FIRST); | ||
30 | } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { | 36 | } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { |
31 | // "move container ... | 37 | // "move container ... |
32 | if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { | 38 | if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { |
diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 2c5b3f6b..28b20dc4 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c | |||
@@ -63,224 +63,135 @@ static bool resize_floating(int amount, bool use_width) { | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static bool resize_tiled(int amount, bool use_width) { | 65 | static bool resize_tiled(int amount, bool use_width) { |
66 | swayc_t *parent = get_focused_view(swayc_active_workspace()); | 66 | swayc_t *container = get_focused_view(swayc_active_workspace()); |
67 | swayc_t *focused = parent; | 67 | swayc_t *parent = container->parent; |
68 | swayc_t *sibling; | 68 | int idx_focused = 0; |
69 | if (!parent) { | 69 | bool use_major = false; |
70 | return true; | 70 | size_t nb_before = 0; |
71 | } | 71 | size_t nb_after = 0; |
72 | // Find the closest parent container which has siblings of the proper layout. | 72 | |
73 | // Then apply the resize to all of them. | 73 | // 1. Identify a container ancestor that will allow the focused child to grow in the requested |
74 | int i; | 74 | // direction. |
75 | if (use_width) { | 75 | while (container->parent) { |
76 | int lnumber = 0; | 76 | parent = container->parent; |
77 | int rnumber = 0; | 77 | if ((parent->children && parent->children->length > 1) |
78 | while (parent->parent) { | 78 | && (is_auto_layout(parent->layout) |
79 | if (parent->parent->layout == L_HORIZ && parent->parent->children) { | 79 | || (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) { |
80 | for (i = 0; i < parent->parent->children->length; i++) { | 80 | // check if container has siblings that can provide/absorb the space needed for |
81 | sibling = parent->parent->children->items[i]; | 81 | // the resize operation. |
82 | if (sibling->x != focused->x) { | 82 | use_major = use_width |
83 | if (sibling->x < parent->x) { | 83 | ? parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT |
84 | lnumber++; | 84 | : parent->layout == L_AUTO_TOP || parent->layout == L_AUTO_BOTTOM; |
85 | } else if (sibling->x > parent->x) { | 85 | // Note: use_major will be false for L_HORIZ and L_VERT |
86 | rnumber++; | 86 | |
87 | } | 87 | idx_focused = index_child(container); |
88 | } | 88 | if (idx_focused < 0) { |
89 | } | 89 | sway_log(L_ERROR, "Something weird is happening, child container not " |
90 | if (rnumber || lnumber) { | 90 | "present in its parent's children list."); |
91 | break; | 91 | continue; |
92 | } | ||
93 | } | 92 | } |
94 | parent = parent->parent; | 93 | if (use_major) { |
95 | } | 94 | nb_before = auto_group_index(parent, idx_focused); |
96 | if (parent == &root_container) { | 95 | nb_after = auto_group_count(parent) - nb_before - 1; |
97 | return true; | ||
98 | } | ||
99 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); | ||
100 | //TODO: Ensure rounding is done in such a way that there are NO pixel leaks | ||
101 | bool valid = true; | ||
102 | for (i = 0; i < parent->parent->children->length; i++) { | ||
103 | sibling = parent->parent->children->items[i]; | ||
104 | if (sibling->x != focused->x) { | ||
105 | if (sibling->x < parent->x) { | ||
106 | double pixels = -1 * amount; | ||
107 | pixels /= lnumber; | ||
108 | if (rnumber) { | ||
109 | if ((sibling->width + pixels/2) < min_sane_w) { | ||
110 | valid = false; | ||
111 | break; | ||
112 | } | ||
113 | } else { | ||
114 | if ((sibling->width + pixels) < min_sane_w) { | ||
115 | valid = false; | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | } else if (sibling->x > parent->x) { | ||
120 | double pixels = -1 * amount; | ||
121 | pixels /= rnumber; | ||
122 | if (lnumber) { | ||
123 | if ((sibling->width + pixels/2) < min_sane_w) { | ||
124 | valid = false; | ||
125 | break; | ||
126 | } | ||
127 | } else { | ||
128 | if ((sibling->width + pixels) < min_sane_w) { | ||
129 | valid = false; | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | } else { | 96 | } else { |
135 | double pixels = amount; | 97 | nb_before = idx_focused - auto_group_start_index(parent, idx_focused); |
136 | if (parent->width + pixels < min_sane_w) { | 98 | nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1; |
137 | valid = false; | 99 | sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d", |
138 | break; | 100 | idx_focused, |
139 | } | 101 | (int)auto_group_start_index(parent, idx_focused), |
102 | (int)auto_group_end_index(parent, idx_focused), | ||
103 | (int)nb_before, (int)nb_after); | ||
104 | |||
140 | } | 105 | } |
141 | } | 106 | if (nb_before || nb_after) { |
142 | if (valid) { | 107 | break; |
143 | for (i = 0; i < parent->parent->children->length; i++) { | ||
144 | sibling = parent->parent->children->items[i]; | ||
145 | if (sibling->x != focused->x) { | ||
146 | if (sibling->x < parent->x) { | ||
147 | double pixels = -1 * amount; | ||
148 | pixels /= lnumber; | ||
149 | if (rnumber) { | ||
150 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); | ||
151 | } else { | ||
152 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); | ||
153 | } | ||
154 | } else if (sibling->x > parent->x) { | ||
155 | double pixels = -1 * amount; | ||
156 | pixels /= rnumber; | ||
157 | if (lnumber) { | ||
158 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); | ||
159 | } else { | ||
160 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); | ||
161 | } | ||
162 | } | ||
163 | } else { | ||
164 | if (rnumber != 0 && lnumber != 0) { | ||
165 | double pixels = amount; | ||
166 | pixels /= 2; | ||
167 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); | ||
168 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); | ||
169 | } else if (rnumber) { | ||
170 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); | ||
171 | } else if (lnumber) { | ||
172 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); | ||
173 | } | ||
174 | } | ||
175 | } | 108 | } |
176 | // Recursive resize does not handle positions, let arrange_windows | ||
177 | // take care of that. | ||
178 | arrange_windows(swayc_active_workspace(), -1, -1); | ||
179 | } | 109 | } |
110 | container = parent; /* continue up the tree to the next ancestor */ | ||
111 | } | ||
112 | if (parent == &root_container) { | ||
180 | return true; | 113 | return true; |
181 | } else { | 114 | } |
182 | int tnumber = 0; | 115 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, " |
183 | int bnumber = 0; | 116 | "and %zu after conts", parent, nb_before, nb_after); |
184 | while (parent->parent) { | 117 | // 2. Ensure that the resize operation will not make one of the resized containers drop |
185 | if (parent->parent->layout == L_VERT) { | 118 | // below the "sane" size threshold. |
186 | for (i = 0; i < parent->parent->children->length; i++) { | 119 | bool valid = true; |
187 | sibling = parent->parent->children->items[i]; | 120 | swayc_t *focused = parent->children->items[idx_focused]; |
188 | if (sibling->y != focused->y) { | 121 | int start = use_major ? 0 : auto_group_start_index(parent, idx_focused); |
189 | if (sibling->y < parent->y) { | 122 | int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused); |
190 | bnumber++; | 123 | sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end); |
191 | } else if (sibling->y > parent->y) { | 124 | for (int i = start; i < end; ) { |
192 | tnumber++; | 125 | swayc_t *sibling = parent->children->items[i]; |
193 | } | 126 | double pixels = amount; |
194 | } | 127 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; |
195 | } | 128 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; |
196 | if (bnumber || tnumber) { | 129 | if (is_before || is_after) { |
197 | break; | 130 | pixels = -pixels; |
198 | } | 131 | pixels /= is_before ? nb_before : nb_after; |
132 | if (nb_after != 0 && nb_before != 0) { | ||
133 | pixels /= 2; | ||
199 | } | 134 | } |
200 | parent = parent->parent; | ||
201 | } | 135 | } |
202 | if (parent->parent == NULL || parent->parent->children == NULL) { | 136 | 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); |
203 | return true; | 137 | if (use_width ? |
138 | sibling->width + pixels < min_sane_w : | ||
139 | sibling->height + pixels < min_sane_h) { | ||
140 | valid = false; | ||
141 | sway_log(L_DEBUG, "Container size no longer sane"); | ||
142 | break; | ||
204 | } | 143 | } |
205 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); | 144 | i = use_major ? auto_group_end_index(parent, i) : (i + 1); |
206 | //TODO: Ensure rounding is done in such a way that there are NO pixel leaks | 145 | sway_log(L_DEBUG, "+++++ check %i", i); |
207 | bool valid = true; | 146 | } |
208 | for (i = 0; i < parent->parent->children->length; i++) { | 147 | // 3. Apply the size change |
209 | sibling = parent->parent->children->items[i]; | 148 | if (valid) { |
210 | if (sibling->y != focused->y) { | 149 | for (int i = start; i < end; ) { |
211 | if (sibling->y < parent->y) { | 150 | int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1); |
212 | double pixels = -1 * amount; | 151 | swayc_t *sibling = parent->children->items[i]; |
213 | pixels /= bnumber; | 152 | double pixels = amount; |
214 | if (tnumber) { | 153 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; |
215 | if ((sibling->height + pixels/2) < min_sane_h) { | 154 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; |
216 | valid = false; | 155 | if (is_before || is_after) { |
217 | break; | 156 | pixels = -pixels; |
218 | } | 157 | pixels /= is_before ? nb_before : nb_after; |
219 | } else { | 158 | if (nb_after != 0 && nb_before != 0) { |
220 | if ((sibling->height + pixels) < min_sane_h) { | 159 | pixels /= 2; |
221 | valid = false; | 160 | } |
222 | break; | 161 | sway_log(L_DEBUG, "%p: %s", sibling, is_before ? "before" : "after"); |
223 | } | 162 | if (use_major) { |
224 | } | 163 | for (int j = i; j < next_i; ++j) { |
225 | } else if (sibling->y > parent->y) { | 164 | recursive_resize(parent->children->items[j], pixels, |
226 | double pixels = -1 * amount; | 165 | use_width ? |
227 | pixels /= tnumber; | 166 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : |
228 | if (bnumber) { | 167 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); |
229 | if ((sibling->height + pixels/2) < min_sane_h) { | ||
230 | valid = false; | ||
231 | break; | ||
232 | } | ||
233 | } else { | ||
234 | if ((sibling->height + pixels) < min_sane_h) { | ||
235 | valid = false; | ||
236 | break; | ||
237 | } | ||
238 | } | 168 | } |
169 | } else { | ||
170 | recursive_resize(sibling, pixels, | ||
171 | use_width ? | ||
172 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : | ||
173 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); | ||
239 | } | 174 | } |
240 | } else { | 175 | } else { |
241 | double pixels = amount; | 176 | if (use_major) { |
242 | if (parent->height + pixels < min_sane_h) { | 177 | for (int j = i; j < next_i; ++j) { |
243 | valid = false; | 178 | recursive_resize(parent->children->items[j], pixels / 2, |
244 | break; | 179 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); |
245 | } | 180 | recursive_resize(parent->children->items[j], pixels / 2, |
246 | } | 181 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); |
247 | } | ||
248 | if (valid) { | ||
249 | for (i = 0; i < parent->parent->children->length; i++) { | ||
250 | sibling = parent->parent->children->items[i]; | ||
251 | if (sibling->y != focused->y) { | ||
252 | if (sibling->y < parent->y) { | ||
253 | double pixels = -1 * amount; | ||
254 | pixels /= bnumber; | ||
255 | if (tnumber) { | ||
256 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); | ||
257 | } else { | ||
258 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); | ||
259 | } | ||
260 | } else if (sibling->x > parent->x) { | ||
261 | double pixels = -1 * amount; | ||
262 | pixels /= tnumber; | ||
263 | if (bnumber) { | ||
264 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); | ||
265 | } else { | ||
266 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); | ||
267 | } | ||
268 | } | 182 | } |
269 | } else { | 183 | } else { |
270 | if (bnumber != 0 && tnumber != 0) { | 184 | recursive_resize(sibling, pixels / 2, |
271 | double pixels = amount/2; | 185 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); |
272 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); | 186 | recursive_resize(sibling, pixels / 2, |
273 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); | 187 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); |
274 | } else if (tnumber) { | ||
275 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); | ||
276 | } else if (bnumber) { | ||
277 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); | ||
278 | } | ||
279 | } | 188 | } |
280 | } | 189 | } |
281 | arrange_windows(swayc_active_workspace(), -1, -1); | 190 | i = next_i; |
282 | } | 191 | } |
283 | return true; | 192 | // Recursive resize does not handle positions, let arrange_windows |
193 | // take care of that. | ||
194 | arrange_windows(swayc_active_workspace(), -1, -1); | ||
284 | } | 195 | } |
285 | return true; | 196 | return true; |
286 | } | 197 | } |
diff --git a/sway/commands/workspace_layout.c b/sway/commands/workspace_layout.c index b7b4b033..c9305773 100644 --- a/sway/commands/workspace_layout.c +++ b/sway/commands/workspace_layout.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | struct cmd_results *cmd_workspace_layout(int argc, char **argv) { | 4 | struct cmd_results *cmd_workspace_layout(int argc, char **argv) { |
5 | struct cmd_results *error = NULL; | 5 | struct cmd_results *error = NULL; |
6 | if ((error = checkarg(argc, "workspace_layout", EXPECTED_EQUAL_TO, 1))) { | 6 | if ((error = checkarg(argc, "workspace_layout", EXPECTED_AT_LEAST, 1))) { |
7 | return error; | 7 | return error; |
8 | } | 8 | } |
9 | 9 | ||
@@ -13,8 +13,27 @@ struct cmd_results *cmd_workspace_layout(int argc, char **argv) { | |||
13 | config->default_layout = L_STACKED; | 13 | config->default_layout = L_STACKED; |
14 | } else if (strcasecmp(argv[0], "tabbed") == 0) { | 14 | } else if (strcasecmp(argv[0], "tabbed") == 0) { |
15 | config->default_layout = L_TABBED; | 15 | config->default_layout = L_TABBED; |
16 | } else if (strcasecmp(argv[0], "auto") == 0) { | ||
17 | if (argc == 1) { | ||
18 | config->default_layout = L_AUTO_FIRST; | ||
19 | } else { | ||
20 | if ((error = checkarg(argc, "workspace_layout auto", EXPECTED_EQUAL_TO, 2))) { | ||
21 | return error; | ||
22 | } | ||
23 | if (strcasecmp(argv[0], "left") == 0) { | ||
24 | config->default_layout = L_AUTO_LEFT; | ||
25 | } else if (strcasecmp(argv[0], "right") == 0) { | ||
26 | config->default_layout = L_AUTO_RIGHT; | ||
27 | } else if (strcasecmp(argv[0], "top") == 0) { | ||
28 | config->default_layout = L_AUTO_TOP; | ||
29 | } else if (strcasecmp(argv[0], "bottom") == 0) { | ||
30 | config->default_layout = L_AUTO_BOTTOM; | ||
31 | } else { | ||
32 | return cmd_results_new(CMD_INVALID, "workspace_layout auto", "Expected 'workspace_layout auto <left|right|top|bottom>'"); | ||
33 | } | ||
34 | } | ||
16 | } else { | 35 | } else { |
17 | return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed>'"); | 36 | return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed|auto|auto left|auto right|auto top|auto bottom>'"); |
18 | } | 37 | } |
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 38 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
20 | } | 39 | } |