summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/commands.h15
-rw-r--r--include/config.h1
-rw-r--r--sway/commands.c501
-rw-r--r--sway/config.c6
-rw-r--r--sway/handlers.c2
-rw-r--r--sway/stringop.c2
-rw-r--r--sway/workspace.c21
7 files changed, 297 insertions, 251 deletions
diff --git a/include/commands.h b/include/commands.h
index 0a38ce43..5c87be51 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -5,17 +5,16 @@
5 5
6struct cmd_handler { 6struct cmd_handler {
7 char *command; 7 char *command;
8 bool (*handle)(int argc, char **argv); 8 enum cmd_status {
9 enum { 9 CMD_SUCCESS,
10 CMD_COMPOSITOR_READY, 10 CMD_FAILURE,
11 CMD_KEYBIND, 11 CMD_DEFER,
12 CMD_ANYTIME 12 } (*handle)(int argc, char **argv);
13 } config_type;
14}; 13};
15 14
16bool handle_command(char *command); 15enum cmd_status handle_command(char *command);
17// Handles commands during config 16// Handles commands during config
18bool config_command(char *command); 17enum cmd_status config_command(char *command);
19 18
20void remove_view_from_scratchpad(); 19void remove_view_from_scratchpad();
21 20
diff --git a/include/config.h b/include/config.h
index 4070c9ef..676218c8 100644
--- a/include/config.h
+++ b/include/config.h
@@ -52,6 +52,7 @@ struct sway_config {
52 bool active; 52 bool active;
53 bool failed; 53 bool failed;
54 bool reloading; 54 bool reloading;
55 bool reading;
55 bool auto_back_and_forth; 56 bool auto_back_and_forth;
56 57
57 int gaps_inner; 58 int gaps_inner;
diff --git a/sway/commands.c b/sway/commands.c
index 09ee91e8..e79746ae 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -18,15 +18,13 @@
18#include "sway.h" 18#include "sway.h"
19#include "resize.h" 19#include "resize.h"
20 20
21struct modifier_key {
22 char *name;
23 uint32_t mod;
24};
25
26swayc_t *sp_view; 21swayc_t *sp_view;
27int sp_index = 0; 22int sp_index = 0;
28 23
29static struct modifier_key modifiers[] = { 24static struct modifier_key {
25 char *name;
26 uint32_t mod;
27} modifiers[] = {
30 { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, 28 { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT },
31 { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, 29 { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS },
32 { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, 30 { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL },
@@ -46,14 +44,14 @@ enum expected_args {
46 EXPECTED_EQUAL_TO 44 EXPECTED_EQUAL_TO
47}; 45};
48 46
49static bool checkarg(int argc, char *name, enum expected_args type, int val) { 47static bool checkarg(int argc, const char *name, enum expected_args type, int val) {
50 switch (type) { 48 switch (type) {
51 case EXPECTED_MORE_THAN: 49 case EXPECTED_MORE_THAN:
52 if (argc > val) { 50 if (argc > val) {
53 return true; 51 return true;
54 } 52 }
55 sway_log(L_ERROR, "Invalid %s command." 53 sway_log(L_ERROR, "Invalid %s command."
56 "(expected more than %d argument%s, got %d", 54 "(expected more than %d argument%s, got %d)",
57 name, val, (char*[2]){"s", ""}[argc==1], argc); 55 name, val, (char*[2]){"s", ""}[argc==1], argc);
58 break; 56 break;
59 case EXPECTED_AT_LEAST: 57 case EXPECTED_AT_LEAST:
@@ -61,7 +59,7 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) {
61 return true; 59 return true;
62 } 60 }
63 sway_log(L_ERROR, "Invalid %s command." 61 sway_log(L_ERROR, "Invalid %s command."
64 "(expected at least %d argument%s, got %d", 62 "(expected at least %d argument%s, got %d)",
65 name, val, (char*[2]){"s", ""}[argc==1], argc); 63 name, val, (char*[2]){"s", ""}[argc==1], argc);
66 break; 64 break;
67 case EXPECTED_LESS_THAN: 65 case EXPECTED_LESS_THAN:
@@ -69,7 +67,7 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) {
69 return true; 67 return true;
70 }; 68 };
71 sway_log(L_ERROR, "Invalid %s command." 69 sway_log(L_ERROR, "Invalid %s command."
72 "(expected less than %d argument%s, got %d", 70 "(expected less than %d argument%s, got %d)",
73 name, val, (char*[2]){"s", ""}[argc==1], argc); 71 name, val, (char*[2]){"s", ""}[argc==1], argc);
74 break; 72 break;
75 case EXPECTED_EQUAL_TO: 73 case EXPECTED_EQUAL_TO:
@@ -77,7 +75,7 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) {
77 return true; 75 return true;
78 }; 76 };
79 sway_log(L_ERROR, "Invalid %s command." 77 sway_log(L_ERROR, "Invalid %s command."
80 "(expected %d arguments, got %d", name, val, argc); 78 "(expected %d arguments, got %d)", name, val, argc);
81 break; 79 break;
82 } 80 }
83 return false; 81 return false;
@@ -96,9 +94,10 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) {
96 return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); 94 return (rbind->keys->length + rmod) - (lbind->keys->length + lmod);
97} 95}
98 96
99static bool cmd_bindsym(int argc, char **argv) { 97static enum cmd_status cmd_bindsym(int argc, char **argv) {
100 if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) { 98 if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)
101 return false; 99 || !config->reading) {
100 return CMD_FAILURE;
102 }; 101 };
103 102
104 struct sway_binding *binding = malloc(sizeof(struct sway_binding)); 103 struct sway_binding *binding = malloc(sizeof(struct sway_binding));
@@ -128,7 +127,7 @@ static bool cmd_bindsym(int argc, char **argv) {
128 free(binding->command); 127 free(binding->command);
129 free(binding); 128 free(binding);
130 list_free(split); 129 list_free(split);
131 return false; 130 return CMD_FAILURE;
132 } 131 }
133 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); 132 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
134 *key = sym; 133 *key = sym;
@@ -142,19 +141,22 @@ static bool cmd_bindsym(int argc, char **argv) {
142 list_sort(mode->bindings, bindsym_sort); 141 list_sort(mode->bindings, bindsym_sort);
143 142
144 sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); 143 sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command);
145 return true; 144 return CMD_SUCCESS;
146} 145}
147 146
148static bool cmd_exec_always(int argc, char **argv) { 147static enum cmd_status cmd_exec_always(int argc, char **argv) {
149 if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { 148 if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) {
150 return false; 149 return CMD_FAILURE;
150 }
151 if (!config->active) {
152 return CMD_DEFER;
151 } 153 }
152 154
153 pid_t pid = fork(); 155 pid_t pid = fork();
154 /* Failed to fork */ 156 /* Failed to fork */
155 if (pid < 0) { 157 if (pid < 0) {
156 sway_log(L_ERROR, "exec command failed, sway did not fork"); 158 sway_log(L_ERROR, "exec command failed, sway did not fork");
157 return false; 159 return CMD_FAILURE;
158 } 160 }
159 /* Child process */ 161 /* Child process */
160 if (pid == 0) { 162 if (pid == 0) {
@@ -167,15 +169,18 @@ static bool cmd_exec_always(int argc, char **argv) {
167 exit(-1); 169 exit(-1);
168 } 170 }
169 /* Parent */ 171 /* Parent */
170 return true; 172 return CMD_SUCCESS;
171} 173}
172 174
173static bool cmd_exec(int argc, char **argv) { 175static enum cmd_status cmd_exec(int argc, char **argv) {
176 if (!config->active) {
177 return CMD_DEFER;
178 }
174 if (config->reloading) { 179 if (config->reloading) {
175 char *args = join_args(argv, argc); 180 char *args = join_args(argv, argc);
176 sway_log(L_DEBUG, "Ignoring exec %s due to reload", args); 181 sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args);
177 free(args); 182 free(args);
178 return true; 183 return CMD_SUCCESS;
179 } 184 }
180 return cmd_exec_always(argc, argv); 185 return cmd_exec_always(argc, argv);
181} 186}
@@ -186,26 +191,28 @@ static void kill_views(swayc_t *container, void *data) {
186 } 191 }
187} 192}
188 193
189static bool cmd_exit(int argc, char **argv) { 194static enum cmd_status cmd_exit(int argc, char **argv) {
190 if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) { 195 if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)
191 return false; 196 || config->reading || !config->active) {
197 return CMD_FAILURE;
192 } 198 }
193 // Close all views 199 // Close all views
194 container_map(&root_container, kill_views, NULL); 200 container_map(&root_container, kill_views, NULL);
195 sway_terminate(); 201 sway_terminate();
196 return true; 202 return CMD_SUCCESS;
197} 203}
198 204
199static bool cmd_floating(int argc, char **argv) { 205static enum cmd_status cmd_floating(int argc, char **argv) {
200 if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) { 206 if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)
201 return false; 207 || config->reading || !config->active) {
208 return CMD_FAILURE;
202 } 209 }
203 210
204 if (strcasecmp(argv[0], "toggle") == 0) { 211 if (strcasecmp(argv[0], "toggle") == 0) {
205 swayc_t *view = get_focused_container(&root_container); 212 swayc_t *view = get_focused_container(&root_container);
206 // Prevent running floating commands on things like workspaces 213 // Prevent running floating commands on things like workspaces
207 if (view->type != C_VIEW) { 214 if (view->type != C_VIEW) {
208 return true; 215 return CMD_SUCCESS;
209 } 216 }
210 // Change from nonfloating to floating 217 // Change from nonfloating to floating
211 if (!view->is_floating) { 218 if (!view->is_floating) {
@@ -254,12 +261,13 @@ static bool cmd_floating(int argc, char **argv) {
254 } 261 }
255 set_focused_container(view); 262 set_focused_container(view);
256 } 263 }
257 return true; 264 return CMD_SUCCESS;
258} 265}
259 266
260static bool cmd_floating_mod(int argc, char **argv) { 267static enum cmd_status cmd_floating_mod(int argc, char **argv) {
261 if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { 268 if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)
262 return false; 269 || !config->reading) {
270 return CMD_FAILURE;
263 } 271 }
264 int i, j; 272 int i, j;
265 list_t *split = split_string(argv[0], "+"); 273 list_t *split = split_string(argv[0], "+");
@@ -276,27 +284,28 @@ static bool cmd_floating_mod(int argc, char **argv) {
276 free_flat_list(split); 284 free_flat_list(split);
277 if (!config->floating_mod) { 285 if (!config->floating_mod) {
278 sway_log(L_ERROR, "bindsym - unknown keys %s", argv[0]); 286 sway_log(L_ERROR, "bindsym - unknown keys %s", argv[0]);
279 return false; 287 return CMD_FAILURE;
280 } 288 }
281 return true; 289 return CMD_SUCCESS;
282} 290}
283 291
284static bool cmd_focus(int argc, char **argv) { 292static enum cmd_status cmd_focus(int argc, char **argv) {
285 static int floating_toggled_index = 0; 293 static int floating_toggled_index = 0;
286 static int tiled_toggled_index = 0; 294 static int tiled_toggled_index = 0;
287 if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { 295 if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)
288 return false; 296 || config->reading || !config->active) {
297 return CMD_FAILURE;
289 } 298 }
290 if (strcasecmp(argv[0], "left") == 0) { 299 if (strcasecmp(argv[0], "left") == 0) {
291 return move_focus(MOVE_LEFT); 300 move_focus(MOVE_LEFT);
292 } else if (strcasecmp(argv[0], "right") == 0) { 301 } else if (strcasecmp(argv[0], "right") == 0) {
293 return move_focus(MOVE_RIGHT); 302 move_focus(MOVE_RIGHT);
294 } else if (strcasecmp(argv[0], "up") == 0) { 303 } else if (strcasecmp(argv[0], "up") == 0) {
295 return move_focus(MOVE_UP); 304 move_focus(MOVE_UP);
296 } else if (strcasecmp(argv[0], "down") == 0) { 305 } else if (strcasecmp(argv[0], "down") == 0) {
297 return move_focus(MOVE_DOWN); 306 move_focus(MOVE_DOWN);
298 } else if (strcasecmp(argv[0], "parent") == 0) { 307 } else if (strcasecmp(argv[0], "parent") == 0) {
299 return move_focus(MOVE_PARENT); 308 move_focus(MOVE_PARENT);
300 } else if (strcasecmp(argv[0], "mode_toggle") == 0) { 309 } else if (strcasecmp(argv[0], "mode_toggle") == 0) {
301 int i; 310 int i;
302 swayc_t *workspace = swayc_active_workspace(); 311 swayc_t *workspace = swayc_active_workspace();
@@ -335,17 +344,16 @@ static bool cmd_focus(int argc, char **argv) {
335 } 344 }
336 } 345 }
337 } 346 }
338 347 return CMD_SUCCESS;
339 return true;
340} 348}
341 349
342static bool cmd_focus_follows_mouse(int argc, char **argv) { 350static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) {
343 if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { 351 if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) {
344 return false; 352 return CMD_FAILURE;
345 } 353 }
346 354
347 config->focus_follows_mouse = !strcasecmp(argv[0], "yes"); 355 config->focus_follows_mouse = !strcasecmp(argv[0], "yes");
348 return true; 356 return CMD_SUCCESS;
349} 357}
350 358
351static void hide_view_in_scratchpad(swayc_t *sp_view) { 359static void hide_view_in_scratchpad(swayc_t *sp_view) {
@@ -364,12 +372,16 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) {
364 set_focused_container(container_under_pointer()); 372 set_focused_container(container_under_pointer());
365} 373}
366 374
367static bool cmd_mode(int argc, char **argv) { 375static enum cmd_status cmd_mode(int argc, char **argv) {
368 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { 376 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
369 return false; 377 return CMD_FAILURE;
370 } 378 }
371 bool mode_make = strcmp(argv[argc-1], "{") == 0; 379 bool mode_make = !strcmp(argv[argc-1], "{");
372 const char *mode_name = join_args(argv, argc - mode_make); 380 if (mode_make && !config->reading) {
381 return CMD_FAILURE;
382 }
383
384 char *mode_name = join_args(argv, argc - mode_make);
373 struct sway_mode *mode = NULL; 385 struct sway_mode *mode = NULL;
374 // Find mode 386 // Find mode
375 int i, len = config->modes->length; 387 int i, len = config->modes->length;
@@ -389,17 +401,20 @@ static bool cmd_mode(int argc, char **argv) {
389 } 401 }
390 if (!mode) { 402 if (!mode) {
391 sway_log(L_ERROR, "Unknown mode `%s'", mode_name); 403 sway_log(L_ERROR, "Unknown mode `%s'", mode_name);
392 return false; 404 free(mode_name);
405 return CMD_FAILURE;
393 } 406 }
394 sway_log(L_DEBUG, "Switching to mode `%s'",mode->name); 407 sway_log(L_DEBUG, "Switching to mode `%s'",mode->name);
408 free(mode_name);
395 // Set current mode 409 // Set current mode
396 config->current_mode = mode; 410 config->current_mode = mode;
397 return true; 411 return CMD_SUCCESS;
398} 412}
399 413
400static bool cmd_move(int argc, char **argv) { 414static enum cmd_status cmd_move(int argc, char **argv) {
401 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { 415 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)
402 return false; 416 || config->reading || !config->active) {
417 return CMD_FAILURE;
403 } 418 }
404 419
405 swayc_t *view = get_focused_container(&root_container); 420 swayc_t *view = get_focused_container(&root_container);
@@ -414,14 +429,14 @@ static bool cmd_move(int argc, char **argv) {
414 move_container(view, MOVE_DOWN); 429 move_container(view, MOVE_DOWN);
415 } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { 430 } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) {
416 // "move container to workspace x" 431 // "move container to workspace x"
417 if (!checkarg(argc, "move container/window", EXPECTED_EQUAL_TO, 4) || 432 if (!checkarg(argc, "move container/window", EXPECTED_EQUAL_TO, 4)
418 strcasecmp(argv[1], "to") != 0 || 433 || strcasecmp(argv[1], "to") != 0
419 strcasecmp(argv[2], "workspace") != 0) { 434 || strcasecmp(argv[2], "workspace") != 0) {
420 return false; 435 return CMD_FAILURE;
421 } 436 }
422 437
423 if (view->type != C_CONTAINER && view->type != C_VIEW) { 438 if (view->type != C_CONTAINER && view->type != C_VIEW) {
424 return false; 439 return CMD_FAILURE;
425 } 440 }
426 441
427 const char *ws_name = argv[3]; 442 const char *ws_name = argv[3];
@@ -437,7 +452,7 @@ static bool cmd_move(int argc, char **argv) {
437 move_container_to(view, get_focused_container(ws)); 452 move_container_to(view, get_focused_container(ws));
438 } else if (strcasecmp(argv[0], "scratchpad") == 0) { 453 } else if (strcasecmp(argv[0], "scratchpad") == 0) {
439 if (view->type != C_CONTAINER && view->type != C_VIEW) { 454 if (view->type != C_CONTAINER && view->type != C_VIEW) {
440 return false; 455 return CMD_FAILURE;
441 } 456 }
442 swayc_t *view = get_focused_container(&root_container); 457 swayc_t *view = get_focused_container(&root_container);
443 int i; 458 int i;
@@ -445,7 +460,7 @@ static bool cmd_move(int argc, char **argv) {
445 if (scratchpad->items[i] == view) { 460 if (scratchpad->items[i] == view) {
446 hide_view_in_scratchpad(view); 461 hide_view_in_scratchpad(view);
447 sp_view = NULL; 462 sp_view = NULL;
448 return true; 463 return CMD_SUCCESS;
449 } 464 }
450 } 465 }
451 list_add(scratchpad, view); 466 list_add(scratchpad, view);
@@ -462,12 +477,16 @@ static bool cmd_move(int argc, char **argv) {
462 } 477 }
463 set_focused_container(focused); 478 set_focused_container(focused);
464 } else { 479 } else {
465 return false; 480 return CMD_FAILURE;
466 } 481 }
467 return true; 482 return CMD_SUCCESS;
468} 483}
469 484
470static bool cmd_orientation(int argc, char **argv) { 485static enum cmd_status cmd_orientation(int argc, char **argv) {
486 if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)
487 || !config->reading) {
488 return CMD_FAILURE;
489 }
471 if (strcasecmp(argv[0], "horizontal") == 0) { 490 if (strcasecmp(argv[0], "horizontal") == 0) {
472 config->default_orientation = L_HORIZ; 491 config->default_orientation = L_HORIZ;
473 } else if (strcasecmp(argv[0], "vertical") == 0) { 492 } else if (strcasecmp(argv[0], "vertical") == 0) {
@@ -475,14 +494,14 @@ static bool cmd_orientation(int argc, char **argv) {
475 } else if (strcasecmp(argv[0], "auto") == 0) { 494 } else if (strcasecmp(argv[0], "auto") == 0) {
476 // Do nothing 495 // Do nothing
477 } else { 496 } else {
478 return false; 497 return CMD_FAILURE;
479 } 498 }
480 return true; 499 return CMD_SUCCESS;
481} 500}
482 501
483static bool cmd_output(int argc, char **argv) { 502static enum cmd_status cmd_output(int argc, char **argv) {
484 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { 503 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
485 return false; 504 return CMD_FAILURE;
486 } 505 }
487 506
488 struct output_config *output = calloc(1, sizeof(struct output_config)); 507 struct output_config *output = calloc(1, sizeof(struct output_config));
@@ -542,12 +561,12 @@ static bool cmd_output(int argc, char **argv) {
542 sway_log(L_DEBUG, "Configured output %s to %d x %d @ %d, %d", 561 sway_log(L_DEBUG, "Configured output %s to %d x %d @ %d, %d",
543 output->name, output->width, output->height, output->x, output->y); 562 output->name, output->width, output->height, output->x, output->y);
544 563
545 return true; 564 return CMD_SUCCESS;
546} 565}
547 566
548static bool cmd_gaps(int argc, char **argv) { 567static enum cmd_status cmd_gaps(int argc, char **argv) {
549 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { 568 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
550 return false; 569 return CMD_FAILURE;
551 } 570 }
552 const char *amount_str = argv[0]; 571 const char *amount_str = argv[0];
553 // gaps amount 572 // gaps amount
@@ -555,7 +574,7 @@ static bool cmd_gaps(int argc, char **argv) {
555 int amount = (int)strtol(amount_str, NULL, 10); 574 int amount = (int)strtol(amount_str, NULL, 10);
556 if (errno == ERANGE || amount == 0) { 575 if (errno == ERANGE || amount == 0) {
557 errno = 0; 576 errno = 0;
558 return false; 577 return CMD_FAILURE;
559 } 578 }
560 if (config->gaps_inner == 0) { 579 if (config->gaps_inner == 0) {
561 config->gaps_inner = amount; 580 config->gaps_inner = amount;
@@ -563,14 +582,14 @@ static bool cmd_gaps(int argc, char **argv) {
563 if (config->gaps_outer == 0) { 582 if (config->gaps_outer == 0) {
564 config->gaps_outer = amount; 583 config->gaps_outer = amount;
565 } 584 }
566 return true; 585 return CMD_SUCCESS;
567 } 586 }
568 // gaps inner|outer n 587 // gaps inner|outer n
569 else if (argc >= 2 && isdigit((amount_str = argv[1])[0])) { 588 else if (argc >= 2 && isdigit((amount_str = argv[1])[0])) {
570 int amount = (int)strtol(amount_str, NULL, 10); 589 int amount = (int)strtol(amount_str, NULL, 10);
571 if (errno == ERANGE || amount == 0) { 590 if (errno == ERANGE || amount == 0) {
572 errno = 0; 591 errno = 0;
573 return false; 592 return CMD_FAILURE;
574 } 593 }
575 const char *target_str = argv[0]; 594 const char *target_str = argv[0];
576 if (strcasecmp(target_str, "inner") == 0) { 595 if (strcasecmp(target_str, "inner") == 0) {
@@ -578,11 +597,11 @@ static bool cmd_gaps(int argc, char **argv) {
578 } else if (strcasecmp(target_str, "outer") == 0) { 597 } else if (strcasecmp(target_str, "outer") == 0) {
579 config->gaps_outer = amount; 598 config->gaps_outer = amount;
580 } 599 }
581 return true; 600 return CMD_SUCCESS;
582 } 601 }
583 // gaps inner|outer current|all set|plus|minus n 602 // gaps inner|outer current|all set|plus|minus n
584 if (argc < 4) { 603 if (argc < 4 || config->reading) {
585 return false; 604 return CMD_FAILURE;
586 } 605 }
587 // gaps inner|outer ... 606 // gaps inner|outer ...
588 const char *inout_str = argv[0]; 607 const char *inout_str = argv[0];
@@ -592,7 +611,7 @@ static bool cmd_gaps(int argc, char **argv) {
592 } else if (strcasecmp(inout_str, "outer") == 0) { 611 } else if (strcasecmp(inout_str, "outer") == 0) {
593 inout = OUTER; 612 inout = OUTER;
594 } else { 613 } else {
595 return false; 614 return CMD_FAILURE;
596 } 615 }
597 616
598 // gaps ... current|all ... 617 // gaps ... current|all ...
@@ -610,7 +629,7 @@ static bool cmd_gaps(int argc, char **argv) {
610 target = WORKSPACE; 629 target = WORKSPACE;
611 } 630 }
612 } else { 631 } else {
613 return false; 632 return CMD_FAILURE;
614 } 633 }
615 634
616 // gaps ... n 635 // gaps ... n
@@ -618,7 +637,7 @@ static bool cmd_gaps(int argc, char **argv) {
618 int amount = (int)strtol(amount_str, NULL, 10); 637 int amount = (int)strtol(amount_str, NULL, 10);
619 if (errno == ERANGE || amount == 0) { 638 if (errno == ERANGE || amount == 0) {
620 errno = 0; 639 errno = 0;
621 return false; 640 return CMD_FAILURE;
622 } 641 }
623 642
624 // gaps ... set|plus|minus ... 643 // gaps ... set|plus|minus ...
@@ -632,18 +651,18 @@ static bool cmd_gaps(int argc, char **argv) {
632 method = ADD; 651 method = ADD;
633 amount *= -1; 652 amount *= -1;
634 } else { 653 } else {
635 return false; 654 return CMD_FAILURE;
636 } 655 }
637 656
638 if (target == CURRENT) { 657 if (target == CURRENT) {
639 swayc_t *cont; 658 swayc_t *cont;
640 if (inout == OUTER) { 659 if (inout == OUTER) {
641 if ((cont = swayc_active_workspace()) == NULL) { 660 if ((cont = swayc_active_workspace()) == NULL) {
642 return false; 661 return CMD_FAILURE;
643 } 662 }
644 } else { 663 } else {
645 if ((cont = get_focused_view(&root_container))->type != C_VIEW) { 664 if ((cont = get_focused_view(&root_container))->type != C_VIEW) {
646 return false; 665 return CMD_FAILURE;
647 } 666 }
648 } 667 }
649 cont->gaps = swayc_gap(cont); 668 cont->gaps = swayc_gap(cont);
@@ -673,7 +692,7 @@ static bool cmd_gaps(int argc, char **argv) {
673 swayc_t *top; 692 swayc_t *top;
674 if (target == WORKSPACE) { 693 if (target == WORKSPACE) {
675 if ((top = swayc_active_workspace()) == NULL) { 694 if ((top = swayc_active_workspace()) == NULL) {
676 return false; 695 return CMD_FAILURE;
677 } 696 }
678 } else { 697 } else {
679 top = &root_container; 698 top = &root_container;
@@ -684,18 +703,22 @@ static bool cmd_gaps(int argc, char **argv) {
684 arrange_windows(top, -1, -1); 703 arrange_windows(top, -1, -1);
685 } 704 }
686 705
687 return true; 706 return CMD_SUCCESS;
688} 707}
689 708
690static bool cmd_kill(int argc, char **argv) { 709static enum cmd_status cmd_kill(int argc, char **argv) {
710 if (config->reading || !config->active) {
711 return CMD_FAILURE;
712 }
691 swayc_t *view = get_focused_container(&root_container); 713 swayc_t *view = get_focused_container(&root_container);
692 wlc_view_close(view->handle); 714 wlc_view_close(view->handle);
693 return true; 715 return CMD_SUCCESS;
694} 716}
695 717
696static bool cmd_layout(int argc, char **argv) { 718static enum cmd_status cmd_layout(int argc, char **argv) {
697 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) { 719 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)
698 return false; 720 || config->reading || !config->active) {
721 return CMD_FAILURE;
699 } 722 }
700 swayc_t *parent = get_focused_container(&root_container); 723 swayc_t *parent = get_focused_container(&root_container);
701 while (parent->type == C_VIEW) { 724 while (parent->type == C_VIEW) {
@@ -715,33 +738,33 @@ static bool cmd_layout(int argc, char **argv) {
715 } 738 }
716 arrange_windows(parent, parent->width, parent->height); 739 arrange_windows(parent, parent->width, parent->height);
717 740
718 return true; 741 return CMD_SUCCESS;
719} 742}
720 743
721static bool cmd_reload(int argc, char **argv) { 744static enum cmd_status cmd_reload(int argc, char **argv) {
722 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { 745 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)
723 return false; 746 || config->reading
724 } 747 || !load_config(NULL)) {
725 if (!load_config(NULL)) { // TODO: Use config given from -c 748 return CMD_FAILURE;
726 return false;
727 } 749 }
728 arrange_windows(&root_container, -1, -1); 750 arrange_windows(&root_container, -1, -1);
729 return true; 751 return CMD_SUCCESS;
730} 752}
731 753
732static bool cmd_resize(int argc, char **argv) { 754static enum cmd_status cmd_resize(int argc, char **argv) {
733 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) { 755 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)
734 return false; 756 || config->reading || !config->active) {
757 return CMD_FAILURE;
735 } 758 }
736 char *end; 759 char *end;
737 int amount = (int)strtol(argv[2], &end, 10); 760 int amount = (int)strtol(argv[2], &end, 10);
738 if (errno == ERANGE || amount == 0) { 761 if (errno == ERANGE || amount == 0) {
739 errno = 0; 762 errno = 0;
740 return false; 763 return CMD_FAILURE;
741 } 764 }
742 765
743 if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) { 766 if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) {
744 return false; 767 return CMD_FAILURE;
745 } 768 }
746 769
747 if (strcmp(argv[0], "shrink") == 0) { 770 if (strcmp(argv[0], "shrink") == 0) {
@@ -749,11 +772,13 @@ static bool cmd_resize(int argc, char **argv) {
749 } 772 }
750 773
751 if (strcmp(argv[1], "width") == 0) { 774 if (strcmp(argv[1], "width") == 0) {
752 return resize_tiled(amount, true); 775 resize_tiled(amount, true);
753 } else if (strcmp(argv[1], "height") == 0) { 776 } else if (strcmp(argv[1], "height") == 0) {
754 return resize_tiled(amount, false); 777 resize_tiled(amount, false);
778 } else {
779 return CMD_FAILURE;
755 } 780 }
756 return false; 781 return CMD_SUCCESS;
757} 782}
758 783
759static swayc_t *fetch_view_from_scratchpad() { 784static swayc_t *fetch_view_from_scratchpad() {
@@ -801,9 +826,10 @@ void remove_view_from_scratchpad(swayc_t *view) {
801 } 826 }
802} 827}
803 828
804static bool cmd_scratchpad(int argc, char **argv) { 829static enum cmd_status cmd_scratchpad(int argc, char **argv) {
805 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) { 830 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)
806 return false; 831 || config->reading || !config->active) {
832 return CMD_FAILURE;
807 } 833 }
808 834
809 if (strcasecmp(argv[0], "show") == 0 && scratchpad->length > 0) { 835 if (strcasecmp(argv[0], "show") == 0 && scratchpad->length > 0) {
@@ -822,10 +848,9 @@ static bool cmd_scratchpad(int argc, char **argv) {
822 sp_view = NULL; 848 sp_view = NULL;
823 } 849 }
824 } 850 }
825 return true; 851 return CMD_SUCCESS;
826 } else {
827 return false;
828 } 852 }
853 return CMD_FAILURE;
829} 854}
830 855
831// sort in order of longest->shortest 856// sort in order of longest->shortest
@@ -835,9 +860,10 @@ static int compare_set(const void *_l, const void *_r) {
835 return strlen((*r)->name) - strlen((*l)->name); 860 return strlen((*r)->name) - strlen((*l)->name);
836} 861}
837 862
838static bool cmd_set(int argc, char **argv) { 863static enum cmd_status cmd_set(int argc, char **argv) {
839 if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2)) { 864 if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2)
840 return false; 865 || !config->reading) {
866 return CMD_FAILURE;
841 } 867 }
842 struct sway_variable *var = NULL; 868 struct sway_variable *var = NULL;
843 // Find old variable if it exists 869 // Find old variable if it exists
@@ -858,20 +884,21 @@ static bool cmd_set(int argc, char **argv) {
858 list_sort(config->symbols, compare_set); 884 list_sort(config->symbols, compare_set);
859 } 885 }
860 var->value = join_args(argv + 1, argc - 1); 886 var->value = join_args(argv + 1, argc - 1);
861 return true; 887 return CMD_SUCCESS;
862} 888}
863 889
864static bool _do_split(int argc, char **argv, int layout) { 890static enum cmd_status _do_split(int argc, char **argv, int layout) {
865 char *name = layout == L_VERT ? "splitv" : 891 char *name = layout == L_VERT ? "splitv" :
866 layout == L_HORIZ ? "splith" : "split"; 892 layout == L_HORIZ ? "splith" : "split";
867 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { 893 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)
868 return false; 894 || config->reading || !config->active) {
895 return CMD_FAILURE;
869 } 896 }
870 swayc_t *focused = get_focused_container(&root_container); 897 swayc_t *focused = get_focused_container(&root_container);
871 898
872 // Case of floating window, dont split 899 // Case of floating window, dont split
873 if (focused->is_floating) { 900 if (focused->is_floating) {
874 return true; 901 return CMD_SUCCESS;
875 } 902 }
876 /* Case that focus is on an workspace with 0/1 children.change its layout */ 903 /* Case that focus is on an workspace with 0/1 children.change its layout */
877 if (focused->type == C_WORKSPACE && focused->children->length <= 1) { 904 if (focused->type == C_WORKSPACE && focused->children->length <= 1) {
@@ -889,12 +916,13 @@ static bool _do_split(int argc, char **argv, int layout) {
889 set_focused_container(focused); 916 set_focused_container(focused);
890 arrange_windows(parent, -1, -1); 917 arrange_windows(parent, -1, -1);
891 } 918 }
892 return true; 919 return CMD_SUCCESS;
893} 920}
894 921
895static bool cmd_split(int argc, char **argv) { 922static enum cmd_status cmd_split(int argc, char **argv) {
896 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) { 923 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)
897 return false; 924 || config->reading || !config->active) {
925 return CMD_FAILURE;
898 } 926 }
899 927
900 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { 928 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) {
@@ -903,36 +931,39 @@ static bool cmd_split(int argc, char **argv) {
903 _do_split(argc - 1, argv + 1, L_HORIZ); 931 _do_split(argc - 1, argv + 1, L_HORIZ);
904 } else { 932 } else {
905 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); 933 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");
906 return false; 934 return CMD_FAILURE;
907 } 935 }
908 936 return CMD_SUCCESS;
909 return true;
910} 937}
911 938
912static bool cmd_splitv(int argc, char **argv) { 939static enum cmd_status cmd_splitv(int argc, char **argv) {
913 return _do_split(argc, argv, L_VERT); 940 return _do_split(argc, argv, L_VERT);
914} 941}
915 942
916static bool cmd_splith(int argc, char **argv) { 943static enum cmd_status cmd_splith(int argc, char **argv) {
917 return _do_split(argc, argv, L_HORIZ); 944 return _do_split(argc, argv, L_HORIZ);
918} 945}
919 946
920static bool cmd_log_colors(int argc, char **argv) { 947static enum cmd_status cmd_log_colors(int argc, char **argv) {
921 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) { 948 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)
922 return false; 949 || !config->reading) {
950 return CMD_FAILURE;
923 } 951 }
924 if (strcasecmp(argv[0], "no") != 0 && strcasecmp(argv[0], "yes") != 0) { 952 if (strcasecmp(argv[0], "no") == 0) {
953 sway_log_colors(0);
954 } else if(strcasecmp(argv[0], "yes") == 0) {
955 sway_log_colors(1);
956 } else {
925 sway_log(L_ERROR, "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]); 957 sway_log(L_ERROR, "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]);
926 return false; 958 return CMD_FAILURE;
927 } 959 }
928 960 return CMD_SUCCESS;
929 sway_log_colors(!strcasecmp(argv[0], "yes"));
930 return true;
931} 961}
932 962
933static bool cmd_fullscreen(int argc, char **argv) { 963static enum cmd_status cmd_fullscreen(int argc, char **argv) {
934 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) { 964 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)
935 return false; 965 || config->reading || !config->active) {
966 return CMD_FAILURE;
936 } 967 }
937 968
938 swayc_t *container = get_focused_view(&root_container); 969 swayc_t *container = get_focused_view(&root_container);
@@ -946,103 +977,100 @@ static bool cmd_fullscreen(int argc, char **argv) {
946 // Only resize container when going into fullscreen 977 // Only resize container when going into fullscreen
947 arrange_windows(container, -1, -1); 978 arrange_windows(container, -1, -1);
948 979
949 return true; 980 return CMD_SUCCESS;
950} 981}
951 982
952static bool cmd_workspace(int argc, char **argv) { 983static enum cmd_status cmd_workspace(int argc, char **argv) {
953 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { 984 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
954 return false; 985 return CMD_FAILURE;
955 } 986 }
956 987
957 if (argc == 1) { 988 if (argc == 1) {
989 if (config->reading || !config->active) {
990 return CMD_DEFER;
991 }
958 // Handle workspace next/prev 992 // Handle workspace next/prev
993 swayc_t *ws = NULL;
959 if (strcasecmp(argv[0], "next") == 0) { 994 if (strcasecmp(argv[0], "next") == 0) {
960 workspace_switch(workspace_next()); 995 ws = workspace_next();
961 return true; 996 } else if (strcasecmp(argv[0], "prev") == 0) {
962 } 997 ws = workspace_prev();
963 998 } else if (strcasecmp(argv[0], "next_on_output") == 0) {
964 if (strcasecmp(argv[0], "prev") == 0) { 999 ws = workspace_output_next();
965 workspace_switch(workspace_prev()); 1000 } else if (strcasecmp(argv[0], "prev_on_output") == 0) {
966 return true; 1001 ws = workspace_output_prev();
967 } 1002 } else if (strcasecmp(argv[0], "back_and_forth") == 0) {
968
969 // Handle workspace output_next/prev
970 if (strcasecmp(argv[0], "next_on_output") == 0) {
971 workspace_switch(workspace_output_next());
972 return true;
973 }
974
975 if (strcasecmp(argv[0], "prev_on_output") == 0) {
976 workspace_switch(workspace_output_prev());
977 return true;
978 }
979 if (strcasecmp(argv[0], "back_and_forth") == 0) {
980 if (prev_workspace_name) { 1003 if (prev_workspace_name) {
981 swayc_t *ws = workspace_by_name(prev_workspace_name); 1004 if (!(ws = workspace_by_name(prev_workspace_name))) {
982 workspace_switch(ws ? ws : workspace_create(prev_workspace_name)); 1005 ws = workspace_create(prev_workspace_name);
1006 }
1007 }
1008 } else {
1009 if (!(ws= workspace_by_name(argv[0]))) {
1010 ws = workspace_create(argv[0]);
983 } 1011 }
984 return true;
985 }
986
987 swayc_t *workspace = workspace_by_name(argv[0]);
988 if (!workspace) {
989 workspace = workspace_create(argv[0]);
990 } 1012 }
991 workspace_switch(workspace); 1013 workspace_switch(ws);
992 } else { 1014 } else {
993 if (strcasecmp(argv[1], "output") == 0) { 1015 if (strcasecmp(argv[1], "output") == 0) {
994 if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { 1016 if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) {
995 return false; 1017 return CMD_FAILURE;
996 } 1018 }
997 struct workspace_output *wso = calloc(1, sizeof(struct workspace_output)); 1019 struct workspace_output *wso = calloc(1, sizeof(struct workspace_output));
998 sway_log(L_DEBUG, "Assigning workspace %s to output %s", argv[0], argv[2]); 1020 sway_log(L_DEBUG, "Assigning workspace %s to output %s", argv[0], argv[2]);
999 wso->workspace = strdup(argv[0]); 1021 wso->workspace = strdup(argv[0]);
1000 wso->output = strdup(argv[2]); 1022 wso->output = strdup(argv[2]);
1001 list_add(config->workspace_outputs, wso); 1023 list_add(config->workspace_outputs, wso);
1002 // TODO: Consider moving any existing workspace to that output? This might be executed sometime after config load 1024 if (!config->reading) {
1025 // TODO: Move workspace to output. (dont do so when reloading)
1026 }
1003 } 1027 }
1004 } 1028 }
1005 return true; 1029 return CMD_SUCCESS;
1006} 1030}
1007 1031
1008static bool cmd_ws_auto_back_and_forth(int argc, char **argv) { 1032static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) {
1009 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { 1033 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) {
1010 return false; 1034 return CMD_FAILURE;
1011 } 1035 }
1012 if (strcasecmp(argv[0], "yes") == 0) { 1036 if (strcasecmp(argv[0], "yes") == 0) {
1013 config->auto_back_and_forth = true; 1037 config->auto_back_and_forth = true;
1038 } else if (strcasecmp(argv[0], "no") == 0) {
1039 config->auto_back_and_forth = false;
1040 } else {
1041 return CMD_FAILURE;
1014 } 1042 }
1015 return true; 1043 return CMD_SUCCESS;
1016} 1044}
1017 1045
1018/* Keep alphabetized */ 1046/* Keep alphabetized */
1019static struct cmd_handler handlers[] = { 1047static struct cmd_handler handlers[] = {
1020 { "bindsym", cmd_bindsym, CMD_ANYTIME }, 1048 { "bindsym", cmd_bindsym },
1021 { "default_orientation", cmd_orientation, CMD_ANYTIME}, 1049 { "default_orientation", cmd_orientation },
1022 { "exec", cmd_exec, CMD_COMPOSITOR_READY }, 1050 { "exec", cmd_exec },
1023 { "exec_always", cmd_exec_always, CMD_COMPOSITOR_READY }, 1051 { "exec_always", cmd_exec_always },
1024 { "exit", cmd_exit, CMD_KEYBIND }, 1052 { "exit", cmd_exit },
1025 { "floating", cmd_floating, CMD_KEYBIND }, 1053 { "floating", cmd_floating },
1026 { "floating_modifier", cmd_floating_mod, CMD_ANYTIME }, 1054 { "floating_modifier", cmd_floating_mod },
1027 { "focus", cmd_focus, CMD_KEYBIND }, 1055 { "focus", cmd_focus },
1028 { "focus_follows_mouse", cmd_focus_follows_mouse, CMD_ANYTIME }, 1056 { "focus_follows_mouse", cmd_focus_follows_mouse },
1029 { "fullscreen", cmd_fullscreen, CMD_KEYBIND }, 1057 { "fullscreen", cmd_fullscreen },
1030 { "gaps", cmd_gaps, CMD_ANYTIME }, 1058 { "gaps", cmd_gaps },
1031 { "kill", cmd_kill, CMD_KEYBIND }, 1059 { "kill", cmd_kill },
1032 { "layout", cmd_layout, CMD_KEYBIND }, 1060 { "layout", cmd_layout },
1033 { "log_colors", cmd_log_colors, CMD_ANYTIME }, 1061 { "log_colors", cmd_log_colors },
1034 { "mode", cmd_mode, CMD_ANYTIME }, 1062 { "mode", cmd_mode },
1035 { "move", cmd_move, CMD_KEYBIND }, 1063 { "move", cmd_move },
1036 { "output", cmd_output, CMD_ANYTIME }, 1064 { "output", cmd_output },
1037 { "reload", cmd_reload, CMD_KEYBIND }, 1065 { "reload", cmd_reload },
1038 { "resize", cmd_resize, CMD_KEYBIND }, 1066 { "resize", cmd_resize },
1039 { "scratchpad", cmd_scratchpad, CMD_KEYBIND }, 1067 { "scratchpad", cmd_scratchpad },
1040 { "set", cmd_set, CMD_ANYTIME }, 1068 { "set", cmd_set },
1041 { "split", cmd_split, CMD_KEYBIND }, 1069 { "split", cmd_split },
1042 { "splith", cmd_splith, CMD_KEYBIND }, 1070 { "splith", cmd_splith },
1043 { "splitv", cmd_splitv, CMD_KEYBIND }, 1071 { "splitv", cmd_splitv },
1044 { "workspace", cmd_workspace, CMD_COMPOSITOR_READY }, 1072 { "workspace", cmd_workspace },
1045 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME }, 1073 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
1046}; 1074};
1047 1075
1048static int handler_compare(const void *_a, const void *_b) { 1076static int handler_compare(const void *_a, const void *_b) {
@@ -1059,63 +1087,58 @@ static struct cmd_handler *find_handler(char *line) {
1059 return res; 1087 return res;
1060} 1088}
1061 1089
1062bool handle_command(char *exec) { 1090enum cmd_status handle_command(char *exec) {
1063 sway_log(L_INFO, "Handling command '%s'", exec); 1091 sway_log(L_INFO, "Handling command '%s'", exec);
1064 int argc; 1092 int argc;
1065 char **argv = split_args(exec, &argc); 1093 char **argv = split_args(exec, &argc);
1066 if (argc == 0) { 1094 enum cmd_status status = CMD_FAILURE;
1067 return false; 1095 struct cmd_handler *handler;
1096 if (!argc) {
1097 return status;
1068 } 1098 }
1069 struct cmd_handler *handler = find_handler(argv[0]); 1099 if ((handler = find_handler(argv[0])) == NULL
1070 bool exec_success = false; 1100 || (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) {
1071 if (handler && !(handler->handle(argc - 1, argv + 1))) {
1072 sway_log(L_ERROR, "Command failed: %s", argv[0]); 1101 sway_log(L_ERROR, "Command failed: %s", argv[0]);
1073 } 1102 }
1074 free_argv(argc, argv); 1103 free_argv(argc, argv);
1075 return exec_success; 1104 return status;
1076} 1105}
1077 1106
1078bool config_command(char *exec) { 1107enum cmd_status config_command(char *exec) {
1079 sway_log(L_INFO, "handling config command '%s'", exec); 1108 sway_log(L_INFO, "handling config command '%s'", exec);
1080 struct cmd_handler *handler;
1081 int argc; 1109 int argc;
1082 char **argv = split_args(exec, &argc); 1110 char **argv = split_args(exec, &argc);
1083 bool res = false; 1111 enum cmd_status status = CMD_FAILURE;
1112 struct cmd_handler *handler;
1084 if (!argc) { 1113 if (!argc) {
1085 return true; 1114 status = CMD_SUCCESS;
1115 goto cleanup;
1086 } 1116 }
1087 //TODO make this better, it only handles modes right now, and very 1117 // TODO better block handling
1088 //simply at that
1089 if (strncmp(argv[0], "}", 1) == 0) { 1118 if (strncmp(argv[0], "}", 1) == 0) {
1090 config->current_mode = config->modes->items[0]; 1119 config->current_mode = config->modes->items[0];
1091 res = true; 1120 status = CMD_SUCCESS;
1092 goto cleanup; 1121 goto cleanup;
1093 } 1122 }
1094 if ((handler = find_handler(argv[0]))) { 1123 if ((handler = find_handler(argv[0]))) {
1095 int i = 1, e = argc; 1124 // Dont replace first argument in cmd_set
1096 // dont var replace first argument 1125 int i = handler->handle == cmd_set ? 2 : 1;
1097 if (handler->handle == cmd_set) { 1126 int e = argc;
1098 i = 2;
1099 }
1100 for (; i < e; ++i) { 1127 for (; i < e; ++i) {
1101 argv[i] = do_var_replacement(argv[i]); 1128 argv[i] = do_var_replacement(argv[i]);
1102 } 1129 }
1103 if (handler->config_type == CMD_KEYBIND) { 1130 status = handler->handle(argc - 1, argv + 1);
1104 sway_log(L_ERROR, "Invalid command during config `%s'", exec); 1131 if (status == CMD_FAILURE) {
1105 } else if (handler->config_type == CMD_COMPOSITOR_READY && !config->active) { 1132 sway_log(L_ERROR, "Config load failed for line `%s'", exec);
1133 } else if (status == CMD_DEFER) {
1106 sway_log(L_DEBUG, "Defferring command `%s'", exec); 1134 sway_log(L_DEBUG, "Defferring command `%s'", exec);
1107 char *cmd = join_args(argv, argc); 1135 list_add(config->cmd_queue, strdup(exec));
1108 list_add(config->cmd_queue, cmd); 1136 status = CMD_SUCCESS;
1109 res = true;
1110 } else if (!handler->handle(argc-1, argv+1)) {
1111 sway_log(L_DEBUG, "Config load failed for line `%s'", exec);
1112 } else {
1113 res = true;
1114 } 1137 }
1115 } else { 1138 } else {
1116 sway_log(L_ERROR, "Unknown command `%s'", exec); 1139 sway_log(L_ERROR, "Unknown command `%s'", exec);
1117 } 1140 }
1118 cleanup: 1141 cleanup:
1119 free_argv(argc, argv); 1142 free_argv(argc, argv);
1120 return res; 1143 return status;
1121} 1144}
diff --git a/sway/config.c b/sway/config.c
index 11394a7c..23d6ac0d 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -102,6 +102,7 @@ static void config_defaults(struct sway_config *config) {
102 config->active = false; 102 config->active = false;
103 config->failed = false; 103 config->failed = false;
104 config->auto_back_and_forth = false; 104 config->auto_back_and_forth = false;
105 config->reading = false;
105 106
106 config->gaps_inner = 0; 107 config->gaps_inner = 0;
107 config->gaps_outer = 0; 108 config->gaps_outer = 0;
@@ -217,6 +218,7 @@ bool read_config(FILE *file, bool is_active) {
217 config = malloc(sizeof(struct sway_config)); 218 config = malloc(sizeof(struct sway_config));
218 219
219 config_defaults(config); 220 config_defaults(config);
221 config->reading = true;
220 if (is_active) { 222 if (is_active) {
221 sway_log(L_DEBUG, "Performing configuration file reload"); 223 sway_log(L_DEBUG, "Performing configuration file reload");
222 config->reloading = true; 224 config->reloading = true;
@@ -228,7 +230,8 @@ bool read_config(FILE *file, bool is_active) {
228 while (!feof(file)) { 230 while (!feof(file)) {
229 line = read_line(file); 231 line = read_line(file);
230 line = strip_comments(line); 232 line = strip_comments(line);
231 if (!config_command(line)) { 233 if (config_command(line) == CMD_FAILURE) {
234 sway_log(L_ERROR, "Error on line '%s'", line);
232 success = false; 235 success = false;
233 } 236 }
234 free(line); 237 free(line);
@@ -242,6 +245,7 @@ bool read_config(FILE *file, bool is_active) {
242 free_config(old_config); 245 free_config(old_config);
243 } 246 }
244 247
248 config->reading = false;
245 return success; 249 return success;
246} 250}
247 251
diff --git a/sway/handlers.c b/sway/handlers.c
index c0472817..096df53c 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -478,12 +478,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
478static void handle_wlc_ready(void) { 478static void handle_wlc_ready(void) {
479 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); 479 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");
480 // Execute commands until there are none left 480 // Execute commands until there are none left
481 config->active = true;
481 while (config->cmd_queue->length) { 482 while (config->cmd_queue->length) {
482 handle_command(config->cmd_queue->items[0]); 483 handle_command(config->cmd_queue->items[0]);
483 free(config->cmd_queue->items[0]); 484 free(config->cmd_queue->items[0]);
484 list_del(config->cmd_queue, 0); 485 list_del(config->cmd_queue, 0);
485 } 486 }
486 config->active = true;
487} 487}
488 488
489struct wlc_interface interface = { 489struct wlc_interface interface = {
diff --git a/sway/stringop.c b/sway/stringop.c
index 270e673a..191e40c8 100644
--- a/sway/stringop.c
+++ b/sway/stringop.c
@@ -145,7 +145,7 @@ char **split_args(const char *start, int *argc) {
145} 145}
146 146
147void free_argv(int argc, char **argv) { 147void free_argv(int argc, char **argv) {
148 while (--argc) { 148 while (--argc > 0) {
149 free(argv[argc]); 149 free(argv[argc]);
150 } 150 }
151 free(argv); 151 free(argv);
diff --git a/sway/workspace.c b/sway/workspace.c
index 7eb422c4..658f79bc 100644
--- a/sway/workspace.c
+++ b/sway/workspace.c
@@ -76,7 +76,26 @@ char *workspace_next_name(void) {
76} 76}
77 77
78swayc_t *workspace_create(const char* name) { 78swayc_t *workspace_create(const char* name) {
79 swayc_t *parent = get_focused_container(&root_container); 79 swayc_t *parent;
80 // Search for workspace<->output pair
81 int i, e = config->workspace_outputs->length;
82 for (i = 0; i < e; ++i) {
83 struct workspace_output *wso = config->workspace_outputs->items[i];
84 if (strcasecmp(wso->workspace, name) == 0)
85 {
86 // Find output to use if it exists
87 e = root_container.children->length;
88 for (i = 0; i < e; ++i) {
89 parent = root_container.children->items[i];
90 if (strcmp(parent->name, wso->output) == 0) {
91 return new_workspace(parent, name);
92 }
93 }
94 break;
95 }
96 }
97 // Otherwise create a new one
98 parent = get_focused_container(&root_container);
80 parent = swayc_parent_by_type(parent, C_OUTPUT); 99 parent = swayc_parent_by_type(parent, C_OUTPUT);
81 return new_workspace(parent, name); 100 return new_workspace(parent, name);
82} 101}