diff options
Diffstat (limited to 'sway/commands.c')
-rw-r--r-- | sway/commands.c | 216 |
1 files changed, 165 insertions, 51 deletions
diff --git a/sway/commands.c b/sway/commands.c index 2ecfeb98..e39b781a 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <wlc/wlc.h> | 3 | #include <wlc/wlc.h> |
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | #include <stdlib.h> | 5 | #include <stdlib.h> |
6 | #include <errno.h> | ||
6 | #include <string.h> | 7 | #include <string.h> |
7 | #include <unistd.h> | 8 | #include <unistd.h> |
8 | #include <ctype.h> | 9 | #include <ctype.h> |
@@ -14,6 +15,7 @@ | |||
14 | #include "commands.h" | 15 | #include "commands.h" |
15 | #include "container.h" | 16 | #include "container.h" |
16 | #include "handlers.h" | 17 | #include "handlers.h" |
18 | #include "sway.h" | ||
17 | 19 | ||
18 | struct modifier_key { | 20 | struct modifier_key { |
19 | char *name; | 21 | char *name; |
@@ -75,6 +77,18 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) { | |||
75 | return false; | 77 | return false; |
76 | } | 78 | } |
77 | 79 | ||
80 | static int bindsym_sort(const void *_lbind, const void *_rbind) { | ||
81 | const struct sway_binding *lbind = *(void **)_lbind; | ||
82 | const struct sway_binding *rbind = *(void **)_rbind; | ||
83 | unsigned int lmod = 0, rmod = 0, i; | ||
84 | |||
85 | // Count how any modifiers are pressed | ||
86 | for (i = 0; i < 8 * sizeof(lbind->modifiers); ++i) { | ||
87 | lmod += lbind->modifiers & 1 << i; | ||
88 | rmod += rbind->modifiers & 1 << i; | ||
89 | } | ||
90 | return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); | ||
91 | } | ||
78 | 92 | ||
79 | static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { | 93 | static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { |
80 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) { | 94 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) { |
@@ -104,6 +118,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { | |||
104 | xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); | 118 | xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); |
105 | if (!sym) { | 119 | if (!sym) { |
106 | sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]); | 120 | sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]); |
121 | list_free(binding->keys); | ||
122 | free(binding->command); | ||
123 | free(binding); | ||
124 | list_free(split); | ||
107 | return false; | 125 | return false; |
108 | } | 126 | } |
109 | xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); | 127 | xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); |
@@ -113,7 +131,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { | |||
113 | list_free(split); | 131 | list_free(split); |
114 | 132 | ||
115 | // TODO: Check if there are other commands with this key binding | 133 | // TODO: Check if there are other commands with this key binding |
116 | list_add(config->current_mode->bindings, binding); | 134 | struct sway_mode *mode = config->current_mode; |
135 | list_add(mode->bindings, binding); | ||
136 | qsort(mode->bindings->items, mode->bindings->length, | ||
137 | sizeof(mode->bindings->items[0]), bindsym_sort); | ||
117 | 138 | ||
118 | sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); | 139 | sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); |
119 | return true; | 140 | return true; |
@@ -166,7 +187,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { | |||
166 | } | 187 | } |
167 | // Close all views | 188 | // Close all views |
168 | container_map(&root_container, kill_views, NULL); | 189 | container_map(&root_container, kill_views, NULL); |
169 | exit(0); | 190 | sway_terminate(); |
170 | return true; | 191 | return true; |
171 | } | 192 | } |
172 | 193 | ||
@@ -181,43 +202,28 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | |||
181 | if (view->type != C_VIEW) { | 202 | if (view->type != C_VIEW) { |
182 | return true; | 203 | return true; |
183 | } | 204 | } |
184 | int i; | ||
185 | // Change from nonfloating to floating | 205 | // Change from nonfloating to floating |
186 | if (!view->is_floating) { | 206 | if (!view->is_floating) { |
187 | view->is_floating = true; | 207 | // Remove view from its current location |
188 | for (i = 0; i < view->parent->children->length; i++) { | 208 | destroy_container(remove_child(view)); |
189 | if (view->parent->children->items[i] == view) { | 209 | |
190 | // Try to use desired geometry to set w/h | 210 | // and move it into workspace floating |
191 | if (view->desired_width != -1) { | 211 | add_floating(active_workspace,view); |
192 | view->width = view->desired_width; | 212 | view->x = (active_workspace->width - view->width)/2; |
193 | } | 213 | view->y = (active_workspace->height - view->height)/2; |
194 | if (view->desired_height != -1) { | 214 | if (view->desired_width != -1) { |
195 | view->height = view->desired_height; | 215 | view->width = view->desired_width; |
196 | } | 216 | } |
197 | 217 | if (view->desired_height != -1) { | |
198 | // Swap from the list of whatever container the view was in | 218 | view->height = view->desired_height; |
199 | // to the workspace->floating list | ||
200 | list_del(view->parent->children, i); | ||
201 | list_add(active_workspace->floating, view); | ||
202 | destroy_container(view->parent); | ||
203 | |||
204 | // Set the new position of the container and arrange windows | ||
205 | view->x = (active_workspace->width - view->width)/2; | ||
206 | view->y = (active_workspace->height - view->height)/2; | ||
207 | sway_log(L_INFO, "Setting container %p to floating at coordinates X:%d Y:%d, W:%d, H:%d", view, view->x, view->y, view->width, view->height); | ||
208 | // Change parent to active_workspace | ||
209 | view->parent = active_workspace; | ||
210 | arrange_windows(active_workspace, -1, -1); | ||
211 | return true; | ||
212 | } | ||
213 | } | 219 | } |
220 | arrange_windows(active_workspace, -1, -1); | ||
214 | } else { | 221 | } else { |
215 | // Delete the view from the floating list and unset its is_floating flag | 222 | // Delete the view from the floating list and unset its is_floating flag |
216 | // Using length-1 as the index is safe because the view must be the currently | 223 | // Using length-1 as the index is safe because the view must be the currently |
217 | // focused floating output | 224 | // focused floating output |
218 | list_del(active_workspace->floating, active_workspace->floating->length - 1); | 225 | remove_child(view); |
219 | view->is_floating = false; | 226 | view->is_floating = false; |
220 | active_workspace->focused = NULL; | ||
221 | // Get the properly focused container, and add in the view there | 227 | // Get the properly focused container, and add in the view there |
222 | swayc_t *focused = container_under_pointer(); | 228 | swayc_t *focused = container_under_pointer(); |
223 | // If focused is null, it's because the currently focused container is a workspace | 229 | // If focused is null, it's because the currently focused container is a workspace |
@@ -228,21 +234,20 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | |||
228 | 234 | ||
229 | sway_log(L_DEBUG, "Non-floating focused container is %p", focused); | 235 | sway_log(L_DEBUG, "Non-floating focused container is %p", focused); |
230 | 236 | ||
231 | //Case of focused workspace, just create as child of it | 237 | // Case of focused workspace, just create as child of it |
232 | if (focused->type == C_WORKSPACE) { | 238 | if (focused->type == C_WORKSPACE) { |
233 | add_child(focused, view); | 239 | add_child(focused, view); |
234 | } | 240 | } |
235 | //Regular case, create as sibling of current container | 241 | // Regular case, create as sibling of current container |
236 | else { | 242 | else { |
237 | add_sibling(focused, view); | 243 | add_sibling(focused, view); |
238 | } | 244 | } |
239 | // Refocus on the view once its been put back into the layout | 245 | // Refocus on the view once its been put back into the layout |
240 | set_focused_container(view); | 246 | view->width = view->height = 0; |
241 | arrange_windows(active_workspace, -1, -1); | 247 | arrange_windows(active_workspace, -1, -1); |
242 | return true; | ||
243 | } | 248 | } |
249 | set_focused_container(view); | ||
244 | } | 250 | } |
245 | |||
246 | return true; | 251 | return true; |
247 | } | 252 | } |
248 | 253 | ||
@@ -250,11 +255,29 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) | |||
250 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { | 255 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { |
251 | return false; | 256 | return false; |
252 | } | 257 | } |
253 | config->floating_mod = xkb_keysym_from_name(argv[0], XKB_KEYSYM_CASE_INSENSITIVE); | 258 | int i, j; |
259 | list_t *split = split_string(argv[0], "+"); | ||
260 | config->floating_mod = 0; | ||
261 | |||
262 | // set modifer keys | ||
263 | for (i = 0; i < split->length; ++i) { | ||
264 | for (j = 0; j < sizeof(modifiers) / sizeof(struct modifier_key); ++j) { | ||
265 | if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { | ||
266 | config->floating_mod |= modifiers[j].mod; | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | list_free(split); | ||
271 | if (!config->floating_mod) { | ||
272 | sway_log(L_ERROR, "bindsym - unknown keys %s", argv[0]); | ||
273 | return false; | ||
274 | } | ||
254 | return true; | 275 | return true; |
255 | } | 276 | } |
256 | 277 | ||
257 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { | 278 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { |
279 | static int floating_toggled_index = 0; | ||
280 | static int tiled_toggled_index = 0; | ||
258 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { | 281 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { |
259 | return false; | 282 | return false; |
260 | } | 283 | } |
@@ -268,7 +291,44 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) { | |||
268 | return move_focus(MOVE_DOWN); | 291 | return move_focus(MOVE_DOWN); |
269 | } else if (strcasecmp(argv[0], "parent") == 0) { | 292 | } else if (strcasecmp(argv[0], "parent") == 0) { |
270 | return move_focus(MOVE_PARENT); | 293 | return move_focus(MOVE_PARENT); |
294 | } else if (strcasecmp(argv[0], "mode_toggle") == 0) { | ||
295 | int i; | ||
296 | swayc_t *focused = get_focused_view(active_workspace); | ||
297 | if (focused->is_floating) { | ||
298 | if (active_workspace->children->length > 0) { | ||
299 | for (i = 0;i < active_workspace->floating->length; i++) { | ||
300 | if (active_workspace->floating->items[i] == focused) { | ||
301 | floating_toggled_index = i; | ||
302 | break; | ||
303 | } | ||
304 | } | ||
305 | if (active_workspace->children->length > tiled_toggled_index) { | ||
306 | set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index])); | ||
307 | } else { | ||
308 | set_focused_container(get_focused_view(active_workspace->children->items[0])); | ||
309 | tiled_toggled_index = 0; | ||
310 | } | ||
311 | } | ||
312 | } else { | ||
313 | if (active_workspace->floating->length > 0) { | ||
314 | for (i = 0;i < active_workspace->children->length; i++) { | ||
315 | if (active_workspace->children->items[i] == focused) { | ||
316 | tiled_toggled_index = i; | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | if (active_workspace->floating->length > floating_toggled_index) { | ||
321 | swayc_t *floating = active_workspace->floating->items[floating_toggled_index]; | ||
322 | set_focused_container(get_focused_view(floating)); | ||
323 | } else { | ||
324 | swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1]; | ||
325 | set_focused_container(get_focused_view(floating)); | ||
326 | tiled_toggled_index = active_workspace->floating->length - 1; | ||
327 | } | ||
328 | } | ||
329 | } | ||
271 | } | 330 | } |
331 | |||
272 | return true; | 332 | return true; |
273 | } | 333 | } |
274 | 334 | ||
@@ -282,7 +342,62 @@ static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char * | |||
282 | } | 342 | } |
283 | 343 | ||
284 | static bool cmd_move(struct sway_config *config, int argc, char **argv) { | 344 | static bool cmd_move(struct sway_config *config, int argc, char **argv) { |
285 | sway_log(L_DEBUG, "move cmd stub called");//Stubbed method until I get back. | 345 | if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 1)) { |
346 | return false; | ||
347 | } | ||
348 | |||
349 | swayc_t *view = get_focused_container(&root_container); | ||
350 | |||
351 | if (strcasecmp(argv[0], "left") == 0) { | ||
352 | move_container(view,&root_container,MOVE_LEFT); | ||
353 | } else if (strcasecmp(argv[0], "right") == 0) { | ||
354 | move_container(view,&root_container,MOVE_RIGHT); | ||
355 | } else if (strcasecmp(argv[0], "up") == 0) { | ||
356 | move_container(view,&root_container,MOVE_UP); | ||
357 | } else if (strcasecmp(argv[0], "down") == 0) { | ||
358 | move_container(view,&root_container,MOVE_DOWN); | ||
359 | } else | ||
360 | { | ||
361 | return false; | ||
362 | } | ||
363 | |||
364 | return true; | ||
365 | |||
366 | static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { | ||
367 | if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { | ||
368 | return false; | ||
369 | } | ||
370 | |||
371 | if (argc == 1) { | ||
372 | char *end; | ||
373 | int amount = (int)strtol(argv[0], &end, 10); | ||
374 | if (errno == ERANGE || amount == 0) { | ||
375 | errno = 0; | ||
376 | return false; | ||
377 | } | ||
378 | if (config->gaps_inner == 0) { | ||
379 | config->gaps_inner = amount; | ||
380 | } | ||
381 | if (config->gaps_outer == 0) { | ||
382 | config->gaps_outer = amount; | ||
383 | } | ||
384 | } else if (argc == 2) { | ||
385 | char *end; | ||
386 | int amount = (int)strtol(argv[1], &end, 10); | ||
387 | if (errno == ERANGE || amount == 0) { | ||
388 | errno = 0; | ||
389 | return false; | ||
390 | } | ||
391 | if (strcasecmp(argv[0], "inner") == 0) { | ||
392 | config->gaps_inner = amount; | ||
393 | } else if (strcasecmp(argv[0], "outer") == 0) { | ||
394 | config->gaps_outer = amount; | ||
395 | } else { | ||
396 | return false; | ||
397 | } | ||
398 | } else { | ||
399 | return false; | ||
400 | } | ||
286 | return true; | 401 | return true; |
287 | } | 402 | } |
288 | 403 | ||
@@ -297,7 +412,6 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) { | |||
297 | return false; | 412 | return false; |
298 | } | 413 | } |
299 | swayc_t *parent = get_focused_container(&root_container); | 414 | swayc_t *parent = get_focused_container(&root_container); |
300 | |||
301 | while (parent->type == C_VIEW) { | 415 | while (parent->type == C_VIEW) { |
302 | parent = parent->parent; | 416 | parent = parent->parent; |
303 | } | 417 | } |
@@ -322,7 +436,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) { | |||
322 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { | 436 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { |
323 | return false; | 437 | return false; |
324 | } | 438 | } |
325 | if (!load_config()) { | 439 | if (!load_config(NULL)) { // TODO: Use config given from -c |
326 | return false; | 440 | return false; |
327 | } | 441 | } |
328 | arrange_windows(&root_container, -1, -1); | 442 | arrange_windows(&root_container, -1, -1); |
@@ -413,17 +527,15 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { | |||
413 | return false; | 527 | return false; |
414 | } | 528 | } |
415 | 529 | ||
416 | swayc_t *container = get_focused_container(&root_container); | 530 | swayc_t *container = get_focused_view(&root_container); |
417 | bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; | 531 | bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; |
418 | wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); | 532 | wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); |
419 | //Resize workspace if going from fullscreen -> notfullscreen | 533 | // Resize workspace if going from fullscreen -> notfullscreen |
420 | //otherwise just resize container | 534 | // otherwise just resize container |
421 | if (current) { | 535 | if (current) { |
422 | while (container->type != C_WORKSPACE) { | 536 | container = swayc_parent_by_type(container, C_WORKSPACE); |
423 | container = container->parent; | ||
424 | } | ||
425 | } | 537 | } |
426 | //Only resize container when going into fullscreen | 538 | // Only resize container when going into fullscreen |
427 | arrange_windows(container, -1, -1); | 539 | arrange_windows(container, -1, -1); |
428 | 540 | ||
429 | return true; | 541 | return true; |
@@ -489,9 +601,11 @@ static struct cmd_handler handlers[] = { | |||
489 | { "focus", cmd_focus }, | 601 | { "focus", cmd_focus }, |
490 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 602 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
491 | { "fullscreen", cmd_fullscreen }, | 603 | { "fullscreen", cmd_fullscreen }, |
604 | { "gaps", cmd_gaps }, | ||
492 | { "kill", cmd_kill }, | 605 | { "kill", cmd_kill }, |
493 | { "layout", cmd_layout }, | 606 | { "layout", cmd_layout }, |
494 | { "log_colors", cmd_log_colors }, | 607 | { "log_colors", cmd_log_colors }, |
608 | { "move",cmd_move}, | ||
495 | { "reload", cmd_reload }, | 609 | { "reload", cmd_reload }, |
496 | { "set", cmd_set }, | 610 | { "set", cmd_set }, |
497 | { "split", cmd_split }, | 611 | { "split", cmd_split }, |
@@ -511,7 +625,7 @@ static char **split_directive(char *line, int *argc) { | |||
511 | if (!*line) return parts; | 625 | if (!*line) return parts; |
512 | 626 | ||
513 | int in_string = 0, in_character = 0; | 627 | int in_string = 0, in_character = 0; |
514 | int i, j; | 628 | int i, j, _; |
515 | for (i = 0, j = 0; line[i]; ++i) { | 629 | for (i = 0, j = 0; line[i]; ++i) { |
516 | if (line[i] == '\\') { | 630 | if (line[i] == '\\') { |
517 | ++i; | 631 | ++i; |
@@ -524,7 +638,7 @@ static char **split_directive(char *line, int *argc) { | |||
524 | char *item = malloc(i - j + 1); | 638 | char *item = malloc(i - j + 1); |
525 | strncpy(item, line + j, i - j); | 639 | strncpy(item, line + j, i - j); |
526 | item[i - j] = '\0'; | 640 | item[i - j] = '\0'; |
527 | strip_whitespace(item); | 641 | item = strip_whitespace(item, &_); |
528 | if (item[0] == '\0') { | 642 | if (item[0] == '\0') { |
529 | free(item); | 643 | free(item); |
530 | } else { | 644 | } else { |
@@ -542,7 +656,7 @@ static char **split_directive(char *line, int *argc) { | |||
542 | char *item = malloc(i - j + 1); | 656 | char *item = malloc(i - j + 1); |
543 | strncpy(item, line + j, i - j); | 657 | strncpy(item, line + j, i - j); |
544 | item[i - j] = '\0'; | 658 | item[i - j] = '\0'; |
545 | strip_whitespace(item); | 659 | item = strip_whitespace(item, &_); |
546 | if (*argc == capacity) { | 660 | if (*argc == capacity) { |
547 | capacity++; | 661 | capacity++; |
548 | parts = realloc(parts, sizeof(char *) * capacity); | 662 | parts = realloc(parts, sizeof(char *) * capacity); |
@@ -586,7 +700,7 @@ bool handle_command(struct sway_config *config, char *exec) { | |||
586 | char **argv = split_directive(exec + strlen(handler->command), &argc); | 700 | char **argv = split_directive(exec + strlen(handler->command), &argc); |
587 | int i; | 701 | int i; |
588 | 702 | ||
589 | //Perform var subs on all parts of the command | 703 | // Perform var subs on all parts of the command |
590 | for (i = 0; i < argc; ++i) { | 704 | for (i = 0; i < argc; ++i) { |
591 | argv[i] = do_var_replacement(config, argv[i]); | 705 | argv[i] = do_var_replacement(config, argv[i]); |
592 | } | 706 | } |