diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-11-18 11:22:02 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2017-11-18 11:22:02 -0500 |
commit | 733993a651c71f7e2198d505960d6bbd31e0e107 (patch) | |
tree | e51732c5872b624e73355f9e5b3f762101f3cd0d /sway/commands/resize.c | |
parent | Initial (awful) pass on xdg shell support (diff) | |
download | sway-733993a651c71f7e2198d505960d6bbd31e0e107.tar.gz sway-733993a651c71f7e2198d505960d6bbd31e0e107.tar.zst sway-733993a651c71f7e2198d505960d6bbd31e0e107.zip |
Move everything to sway/old/
Diffstat (limited to 'sway/commands/resize.c')
-rw-r--r-- | sway/commands/resize.c | 375 |
1 files changed, 0 insertions, 375 deletions
diff --git a/sway/commands/resize.c b/sway/commands/resize.c deleted file mode 100644 index ef52bb07..00000000 --- a/sway/commands/resize.c +++ /dev/null | |||
@@ -1,375 +0,0 @@ | |||
1 | #include <errno.h> | ||
2 | #include <math.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <strings.h> | ||
7 | #include <wlc/wlc.h> | ||
8 | #include "sway/commands.h" | ||
9 | #include "sway/layout.h" | ||
10 | #include "sway/focus.h" | ||
11 | #include "sway/input_state.h" | ||
12 | #include "sway/handlers.h" | ||
13 | #include "log.h" | ||
14 | |||
15 | enum resize_dim_types { | ||
16 | RESIZE_DIM_PX, | ||
17 | RESIZE_DIM_PPT, | ||
18 | RESIZE_DIM_DEFAULT, | ||
19 | }; | ||
20 | |||
21 | static bool set_size_floating(int new_dimension, bool use_width) { | ||
22 | swayc_t *view = current_container; | ||
23 | if (view) { | ||
24 | if (use_width) { | ||
25 | int current_width = view->width; | ||
26 | view->desired_width = new_dimension; | ||
27 | floating_view_sane_size(view); | ||
28 | |||
29 | int new_x = view->x + (int)(((view->desired_width - current_width) / 2) * -1); | ||
30 | view->width = view->desired_width; | ||
31 | view->x = new_x; | ||
32 | |||
33 | update_geometry(view); | ||
34 | } else { | ||
35 | int current_height = view->height; | ||
36 | view->desired_height = new_dimension; | ||
37 | floating_view_sane_size(view); | ||
38 | |||
39 | int new_y = view->y + (int)(((view->desired_height - current_height) / 2) * -1); | ||
40 | view->height = view->desired_height; | ||
41 | view->y = new_y; | ||
42 | |||
43 | update_geometry(view); | ||
44 | } | ||
45 | |||
46 | return true; | ||
47 | } | ||
48 | |||
49 | return false; | ||
50 | } | ||
51 | |||
52 | static bool resize_floating(int amount, bool use_width) { | ||
53 | swayc_t *view = current_container; | ||
54 | |||
55 | if (view) { | ||
56 | if (use_width) { | ||
57 | return set_size_floating(view->width + amount, true); | ||
58 | } else { | ||
59 | return set_size_floating(view->height + amount, false); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | return false; | ||
64 | } | ||
65 | |||
66 | static bool resize_tiled(int amount, bool use_width) { | ||
67 | swayc_t *container = current_container; | ||
68 | swayc_t *parent = container->parent; | ||
69 | int idx_focused = 0; | ||
70 | bool use_major = false; | ||
71 | size_t nb_before = 0; | ||
72 | size_t nb_after = 0; | ||
73 | |||
74 | // 1. Identify a container ancestor that will allow the focused child to grow in the requested | ||
75 | // direction. | ||
76 | while (container->parent) { | ||
77 | parent = container->parent; | ||
78 | if ((parent->children && parent->children->length > 1) | ||
79 | && (is_auto_layout(parent->layout) | ||
80 | || (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) { | ||
81 | // check if container has siblings that can provide/absorb the space needed for | ||
82 | // the resize operation. | ||
83 | use_major = use_width | ||
84 | ? parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT | ||
85 | : parent->layout == L_AUTO_TOP || parent->layout == L_AUTO_BOTTOM; | ||
86 | // Note: use_major will be false for L_HORIZ and L_VERT | ||
87 | |||
88 | idx_focused = index_child(container); | ||
89 | if (idx_focused < 0) { | ||
90 | sway_log(L_ERROR, "Something weird is happening, child container not " | ||
91 | "present in its parent's children list."); | ||
92 | continue; | ||
93 | } | ||
94 | if (use_major) { | ||
95 | nb_before = auto_group_index(parent, idx_focused); | ||
96 | nb_after = auto_group_count(parent) - nb_before - 1; | ||
97 | } else { | ||
98 | nb_before = idx_focused - auto_group_start_index(parent, idx_focused); | ||
99 | nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1; | ||
100 | sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d", | ||
101 | idx_focused, | ||
102 | (int)auto_group_start_index(parent, idx_focused), | ||
103 | (int)auto_group_end_index(parent, idx_focused), | ||
104 | (int)nb_before, (int)nb_after); | ||
105 | |||
106 | } | ||
107 | if (nb_before || nb_after) { | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | container = parent; /* continue up the tree to the next ancestor */ | ||
112 | } | ||
113 | if (parent == &root_container) { | ||
114 | return true; | ||
115 | } | ||
116 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, " | ||
117 | "and %zu after conts", parent, nb_before, nb_after); | ||
118 | // 2. Ensure that the resize operation will not make one of the resized containers drop | ||
119 | // below the "sane" size threshold. | ||
120 | bool valid = true; | ||
121 | swayc_t *focused = parent->children->items[idx_focused]; | ||
122 | int start = use_major ? 0 : auto_group_start_index(parent, idx_focused); | ||
123 | int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused); | ||
124 | sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end); | ||
125 | for (int i = start; i < end; ) { | ||
126 | swayc_t *sibling = parent->children->items[i]; | ||
127 | double pixels = amount; | ||
128 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; | ||
129 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; | ||
130 | if (is_before || is_after) { | ||
131 | pixels = -pixels; | ||
132 | pixels /= is_before ? nb_before : nb_after; | ||
133 | if (nb_after != 0 && nb_before != 0) { | ||
134 | pixels /= 2; | ||
135 | } | ||
136 | } | ||
137 | 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); | ||
138 | if (use_width ? | ||
139 | sibling->width + pixels < min_sane_w : | ||
140 | sibling->height + pixels < min_sane_h) { | ||
141 | valid = false; | ||
142 | sway_log(L_DEBUG, "Container size no longer sane"); | ||
143 | break; | ||
144 | } | ||
145 | i = use_major ? auto_group_end_index(parent, i) : (i + 1); | ||
146 | sway_log(L_DEBUG, "+++++ check %i", i); | ||
147 | } | ||
148 | // 3. Apply the size change | ||
149 | if (valid) { | ||
150 | for (int i = start; i < end; ) { | ||
151 | int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1); | ||
152 | swayc_t *sibling = parent->children->items[i]; | ||
153 | double pixels = amount; | ||
154 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; | ||
155 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; | ||
156 | if (is_before || is_after) { | ||
157 | pixels = -pixels; | ||
158 | pixels /= is_before ? nb_before : nb_after; | ||
159 | if (nb_after != 0 && nb_before != 0) { | ||
160 | pixels /= 2; | ||
161 | } | ||
162 | sway_log(L_DEBUG, "%p: %s", sibling, is_before ? "before" : "after"); | ||
163 | if (use_major) { | ||
164 | for (int j = i; j < next_i; ++j) { | ||
165 | recursive_resize(parent->children->items[j], pixels, | ||
166 | use_width ? | ||
167 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : | ||
168 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); | ||
169 | } | ||
170 | } else { | ||
171 | recursive_resize(sibling, pixels, | ||
172 | use_width ? | ||
173 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : | ||
174 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); | ||
175 | } | ||
176 | } else { | ||
177 | if (use_major) { | ||
178 | for (int j = i; j < next_i; ++j) { | ||
179 | recursive_resize(parent->children->items[j], pixels / 2, | ||
180 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); | ||
181 | recursive_resize(parent->children->items[j], pixels / 2, | ||
182 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); | ||
183 | } | ||
184 | } else { | ||
185 | recursive_resize(sibling, pixels / 2, | ||
186 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); | ||
187 | recursive_resize(sibling, pixels / 2, | ||
188 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); | ||
189 | } | ||
190 | } | ||
191 | i = next_i; | ||
192 | } | ||
193 | // Recursive resize does not handle positions, let arrange_windows | ||
194 | // take care of that. | ||
195 | arrange_windows(swayc_active_workspace(), -1, -1); | ||
196 | } | ||
197 | return true; | ||
198 | } | ||
199 | |||
200 | static bool set_size_tiled(int amount, bool use_width) { | ||
201 | int desired; | ||
202 | swayc_t *focused = current_container; | ||
203 | |||
204 | if (use_width) { | ||
205 | desired = amount - focused->width; | ||
206 | } else { | ||
207 | desired = amount - focused->height; | ||
208 | } | ||
209 | |||
210 | return resize_tiled(desired, use_width); | ||
211 | } | ||
212 | |||
213 | static bool set_size(int dimension, bool use_width) { | ||
214 | swayc_t *focused = current_container; | ||
215 | |||
216 | if (focused) { | ||
217 | if (focused->is_floating) { | ||
218 | return set_size_floating(dimension, use_width); | ||
219 | } else { | ||
220 | return set_size_tiled(dimension, use_width); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | return false; | ||
225 | } | ||
226 | |||
227 | static bool resize(int dimension, bool use_width, enum resize_dim_types dim_type) { | ||
228 | swayc_t *focused = current_container; | ||
229 | |||
230 | // translate "10 ppt" (10%) to appropriate # of pixels in case we need it | ||
231 | float ppt_dim = (float)dimension / 100; | ||
232 | |||
233 | if (use_width) { | ||
234 | ppt_dim = focused->width * ppt_dim; | ||
235 | } else { | ||
236 | ppt_dim = focused->height * ppt_dim; | ||
237 | } | ||
238 | |||
239 | if (focused) { | ||
240 | if (focused->is_floating) { | ||
241 | // floating view resize dimensions should default to px, so only | ||
242 | // use ppt if specified | ||
243 | if (dim_type == RESIZE_DIM_PPT) { | ||
244 | dimension = (int)ppt_dim; | ||
245 | } | ||
246 | |||
247 | return resize_floating(dimension, use_width); | ||
248 | } else { | ||
249 | // tiled view resize dimensions should default to ppt, so only use | ||
250 | // px if specified | ||
251 | if (dim_type != RESIZE_DIM_PX) { | ||
252 | dimension = (int)ppt_dim; | ||
253 | } | ||
254 | |||
255 | return resize_tiled(dimension, use_width); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return false; | ||
260 | } | ||
261 | |||
262 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { | ||
263 | struct cmd_results *error = NULL; | ||
264 | if ((error = checkarg(argc, "resize set", EXPECTED_AT_LEAST, 2))) { | ||
265 | return error; | ||
266 | } | ||
267 | |||
268 | if (strcasecmp(argv[0], "width") == 0 || strcasecmp(argv[0], "height") == 0) { | ||
269 | // handle `reset set width 100 px height 100 px` syntax, also allows | ||
270 | // specifying only one dimension for a `resize set` | ||
271 | int cmd_num = 0; | ||
272 | int dim; | ||
273 | |||
274 | while ((cmd_num + 1) < argc) { | ||
275 | dim = (int)strtol(argv[cmd_num + 1], NULL, 10); | ||
276 | if (errno == ERANGE || dim == 0) { | ||
277 | errno = 0; | ||
278 | return cmd_results_new(CMD_INVALID, "resize set", | ||
279 | "Expected 'resize set <width|height> <amount> [px] [<width|height> <amount> [px]]'"); | ||
280 | } | ||
281 | |||
282 | if (strcasecmp(argv[cmd_num], "width") == 0) { | ||
283 | set_size(dim, true); | ||
284 | } else if (strcasecmp(argv[cmd_num], "height") == 0) { | ||
285 | set_size(dim, false); | ||
286 | } else { | ||
287 | return cmd_results_new(CMD_INVALID, "resize set", | ||
288 | "Expected 'resize set <width|height> <amount> [px] [<width|height> <amount> [px]]'"); | ||
289 | } | ||
290 | |||
291 | cmd_num += 2; | ||
292 | |||
293 | if (cmd_num < argc && strcasecmp(argv[cmd_num], "px") == 0) { | ||
294 | // if this was `resize set width 400 px height 300 px`, disregard the `px` arg | ||
295 | cmd_num++; | ||
296 | } | ||
297 | } | ||
298 | } else { | ||
299 | // handle `reset set 100 px 100 px` syntax | ||
300 | int width = (int)strtol(argv[0], NULL, 10); | ||
301 | if (errno == ERANGE || width == 0) { | ||
302 | errno = 0; | ||
303 | return cmd_results_new(CMD_INVALID, "resize set", | ||
304 | "Expected 'resize set <width> [px] <height> [px]'"); | ||
305 | } | ||
306 | |||
307 | int height_arg = 1; | ||
308 | if (strcasecmp(argv[1], "px") == 0) { | ||
309 | height_arg = 2; | ||
310 | } | ||
311 | |||
312 | int height = (int)strtol(argv[height_arg], NULL, 10); | ||
313 | if (errno == ERANGE || height == 0) { | ||
314 | errno = 0; | ||
315 | return cmd_results_new(CMD_INVALID, "resize set", | ||
316 | "Expected 'resize set <width> [px] <height> [px]'"); | ||
317 | } | ||
318 | |||
319 | set_size(width, true); | ||
320 | set_size(height, false); | ||
321 | } | ||
322 | |||
323 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
324 | } | ||
325 | |||
326 | struct cmd_results *cmd_resize(int argc, char **argv) { | ||
327 | struct cmd_results *error = NULL; | ||
328 | if (config->reading) return cmd_results_new(CMD_FAILURE, "resize", "Can't be used in config file."); | ||
329 | if (!config->active) return cmd_results_new(CMD_FAILURE, "resize", "Can only be used when sway is running."); | ||
330 | |||
331 | if (strcasecmp(argv[0], "set") == 0) { | ||
332 | return cmd_resize_set(argc - 1, &argv[1]); | ||
333 | } | ||
334 | |||
335 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { | ||
336 | return error; | ||
337 | } | ||
338 | |||
339 | int dim_arg = argc - 1; | ||
340 | |||
341 | enum resize_dim_types dim_type = RESIZE_DIM_DEFAULT; | ||
342 | if (strcasecmp(argv[dim_arg], "ppt") == 0) { | ||
343 | dim_type = RESIZE_DIM_PPT; | ||
344 | dim_arg--; | ||
345 | } else if (strcasecmp(argv[dim_arg], "px") == 0) { | ||
346 | dim_type = RESIZE_DIM_PX; | ||
347 | dim_arg--; | ||
348 | } | ||
349 | |||
350 | int amount = (int)strtol(argv[dim_arg], NULL, 10); | ||
351 | if (errno == ERANGE || amount == 0) { | ||
352 | errno = 0; | ||
353 | amount = 10; // this is the default resize dimension used by i3 for both px and ppt | ||
354 | sway_log(L_DEBUG, "Tried to get resize dimension out of '%s' but failed; setting dimension to default %d", | ||
355 | argv[dim_arg], amount); | ||
356 | } | ||
357 | |||
358 | bool use_width = false; | ||
359 | if (strcasecmp(argv[1], "width") == 0) { | ||
360 | use_width = true; | ||
361 | } else if (strcasecmp(argv[1], "height") != 0) { | ||
362 | return cmd_results_new(CMD_INVALID, "resize", | ||
363 | "Expected 'resize <shrink|grow> <width|height> [<amount>] [px|ppt]'"); | ||
364 | } | ||
365 | |||
366 | if (strcasecmp(argv[0], "shrink") == 0) { | ||
367 | amount *= -1; | ||
368 | } else if (strcasecmp(argv[0], "grow") != 0) { | ||
369 | return cmd_results_new(CMD_INVALID, "resize", | ||
370 | "Expected 'resize <shrink|grow> <width|height> [<amount>] [px|ppt]'"); | ||
371 | } | ||
372 | |||
373 | resize(amount, use_width, dim_type); | ||
374 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
375 | } | ||