aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-04-19 02:46:49 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2019-04-19 08:39:57 -0600
commit09595da0bcf84364e957235c8c50c69d11912515 (patch)
tree6be531d8a730b4cc081cf98ca605baa656103339
parenthide_edge_borders.c: add missing case for --i3 (diff)
downloadsway-09595da0bcf84364e957235c8c50c69d11912515.tar.gz
sway-09595da0bcf84364e957235c8c50c69d11912515.tar.zst
sway-09595da0bcf84364e957235c8c50c69d11912515.zip
cmd_move: allow for all i3 syntax options
This modifies cmd_move to allow for the syntax options allowed by i3. The following syntaxes are supported: - `move left|right|up|down [<amount> [px]]` - `move [--no-auto-back-and-forth] [window|container] [to] workspace <name>|next|prev|next_on_output|prev_on_output|current|number <num>` - `move [window|container] [to] output <name/id>|left|right|up|down` - `move [window|container] [to] mark <mark>` - `move workspace to [output] <name/id>|left|right|up|down` - `move [window|container] [to] [absolute] position <x> [px] <y> [px]` - `move [window|container] [to] [absolute] position center` - `move [window|container] [to] position mouse|cursor|pointer` This also allows retains the following syntax option that is not supported by i3, but is supported in sway 1.0: - `move workspace [to] output <name/id>|left|right|up|down` The changes are: - `window` and `container` are now optional - `output` is now optional for `move workspace` when `to` is given There is also stricter command checking now. If `absolute` or `--no-auto-back-and-forth` are given for commands that do not support them, it will be treated as invalid syntax instead of being silently ignored.
-rw-r--r--sway/commands/move.c179
-rw-r--r--sway/sway.5.scd34
2 files changed, 120 insertions, 93 deletions
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 4ebc949b..4dec889c 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -377,10 +377,11 @@ static bool container_move_in_direction(struct sway_container *container,
377 return false; 377 return false;
378} 378}
379 379
380static struct cmd_results *cmd_move_container(int argc, char **argv) { 380static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
381 int argc, char **argv) {
381 struct cmd_results *error = NULL; 382 struct cmd_results *error = NULL;
382 if ((error = checkarg(argc, "move container/window", 383 if ((error = checkarg(argc, "move container/window",
383 EXPECTED_AT_LEAST, 3))) { 384 EXPECTED_AT_LEAST, 2))) {
384 return error; 385 return error;
385 } 386 }
386 387
@@ -400,29 +401,6 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
400 "Can't move fullscreen global container"); 401 "Can't move fullscreen global container");
401 } 402 }
402 403
403 bool no_auto_back_and_forth = false;
404 while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) {
405 no_auto_back_and_forth = true;
406 if (--argc < 3) {
407 return cmd_results_new(CMD_INVALID, expected_syntax);
408 }
409 ++argv;
410 }
411 while (strcasecmp(argv[1], "--no-auto-back-and-forth") == 0) {
412 no_auto_back_and_forth = true;
413 if (--argc < 3) {
414 return cmd_results_new(CMD_INVALID, expected_syntax);
415 }
416 argv++;
417 }
418
419 while (strcasecmp(argv[1], "to") == 0) {
420 if (--argc < 3) {
421 return cmd_results_new(CMD_INVALID, expected_syntax);
422 }
423 argv++;
424 }
425
426 struct sway_seat *seat = config->handler_context.seat; 404 struct sway_seat *seat = config->handler_context.seat;
427 struct sway_container *old_parent = container->parent; 405 struct sway_container *old_parent = container->parent;
428 struct sway_workspace *old_ws = container->workspace; 406 struct sway_workspace *old_ws = container->workspace;
@@ -430,18 +408,18 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
430 struct sway_node *destination = NULL; 408 struct sway_node *destination = NULL;
431 409
432 // determine destination 410 // determine destination
433 if (strcasecmp(argv[1], "workspace") == 0) { 411 if (strcasecmp(argv[0], "workspace") == 0) {
434 // move container to workspace x 412 // move container to workspace x
435 struct sway_workspace *ws = NULL; 413 struct sway_workspace *ws = NULL;
436 char *ws_name = NULL; 414 char *ws_name = NULL;
437 if (strcasecmp(argv[2], "next") == 0 || 415 if (strcasecmp(argv[1], "next") == 0 ||
438 strcasecmp(argv[2], "prev") == 0 || 416 strcasecmp(argv[1], "prev") == 0 ||
439 strcasecmp(argv[2], "next_on_output") == 0 || 417 strcasecmp(argv[1], "next_on_output") == 0 ||
440 strcasecmp(argv[2], "prev_on_output") == 0 || 418 strcasecmp(argv[1], "prev_on_output") == 0 ||
441 strcasecmp(argv[2], "current") == 0) { 419 strcasecmp(argv[1], "current") == 0) {
442 ws = workspace_by_name(argv[2]); 420 ws = workspace_by_name(argv[1]);
443 } else if (strcasecmp(argv[2], "back_and_forth") == 0) { 421 } else if (strcasecmp(argv[1], "back_and_forth") == 0) {
444 if (!(ws = workspace_by_name(argv[2]))) { 422 if (!(ws = workspace_by_name(argv[1]))) {
445 if (seat->prev_workspace_name) { 423 if (seat->prev_workspace_name) {
446 ws_name = strdup(seat->prev_workspace_name); 424 ws_name = strdup(seat->prev_workspace_name);
447 } else { 425 } else {
@@ -450,19 +428,19 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
450 } 428 }
451 } 429 }
452 } else { 430 } else {
453 if (strcasecmp(argv[2], "number") == 0) { 431 if (strcasecmp(argv[1], "number") == 0) {
454 // move "container to workspace number x" 432 // move [window|container] [to] "workspace number x"
455 if (argc < 4) { 433 if (argc < 3) {
456 return cmd_results_new(CMD_INVALID, expected_syntax); 434 return cmd_results_new(CMD_INVALID, expected_syntax);
457 } 435 }
458 if (!isdigit(argv[3][0])) { 436 if (!isdigit(argv[2][0])) {
459 return cmd_results_new(CMD_INVALID, 437 return cmd_results_new(CMD_INVALID,
460 "Invalid workspace number '%s'", argv[3]); 438 "Invalid workspace number '%s'", argv[2]);
461 } 439 }
462 ws_name = join_args(argv + 3, argc - 3); 440 ws_name = join_args(argv + 2, argc - 2);
463 ws = workspace_by_number(ws_name); 441 ws = workspace_by_number(ws_name);
464 } else { 442 } else {
465 ws_name = join_args(argv + 2, argc - 2); 443 ws_name = join_args(argv + 1, argc - 1);
466 ws = workspace_by_name(ws_name); 444 ws = workspace_by_name(ws_name);
467 } 445 }
468 446
@@ -497,19 +475,19 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
497 free(ws_name); 475 free(ws_name);
498 struct sway_container *dst = seat_get_focus_inactive_tiling(seat, ws); 476 struct sway_container *dst = seat_get_focus_inactive_tiling(seat, ws);
499 destination = dst ? &dst->node : &ws->node; 477 destination = dst ? &dst->node : &ws->node;
500 } else if (strcasecmp(argv[1], "output") == 0) { 478 } else if (strcasecmp(argv[0], "output") == 0) {
501 struct sway_output *new_output = output_in_direction(argv[2], 479 struct sway_output *new_output = output_in_direction(argv[1],
502 old_output, container->x, container->y); 480 old_output, container->x, container->y);
503 if (!new_output) { 481 if (!new_output) {
504 return cmd_results_new(CMD_FAILURE, 482 return cmd_results_new(CMD_FAILURE,
505 "Can't find output with name/direction '%s'", argv[2]); 483 "Can't find output with name/direction '%s'", argv[1]);
506 } 484 }
507 destination = seat_get_focus_inactive(seat, &new_output->node); 485 destination = seat_get_focus_inactive(seat, &new_output->node);
508 } else if (strcasecmp(argv[1], "mark") == 0) { 486 } else if (strcasecmp(argv[0], "mark") == 0) {
509 struct sway_container *dest_con = container_find_mark(argv[2]); 487 struct sway_container *dest_con = container_find_mark(argv[1]);
510 if (dest_con == NULL) { 488 if (dest_con == NULL) {
511 return cmd_results_new(CMD_FAILURE, 489 return cmd_results_new(CMD_FAILURE,
512 "Mark '%s' not found", argv[2]); 490 "Mark '%s' not found", argv[1]);
513 } 491 }
514 destination = &dest_con->node; 492 destination = &dest_con->node;
515 } else { 493 } else {
@@ -635,19 +613,17 @@ static void workspace_move_to_output(struct sway_workspace *workspace,
635 613
636static struct cmd_results *cmd_move_workspace(int argc, char **argv) { 614static struct cmd_results *cmd_move_workspace(int argc, char **argv) {
637 struct cmd_results *error = NULL; 615 struct cmd_results *error = NULL;
638 if ((error = checkarg(argc, "move workspace", EXPECTED_AT_LEAST, 2))) { 616 if ((error = checkarg(argc, "move workspace", EXPECTED_AT_LEAST, 1))) {
639 return error; 617 return error;
640 } 618 }
641 619
642 while (strcasecmp(argv[1], "to") == 0) { 620 if (strcasecmp(argv[0], "output") == 0) {
643 if (--argc < 3) { 621 --argc; ++argv;
644 return cmd_results_new(CMD_INVALID, expected_syntax);
645 }
646 ++argv;
647 } 622 }
648 623
649 if (strcasecmp(argv[1], "output") != 0) { 624 if (!argc) {
650 return cmd_results_new(CMD_INVALID, expected_syntax); 625 return cmd_results_new(CMD_INVALID,
626 "Expected 'move workspace to [output] <output>'");
651 } 627 }
652 628
653 struct sway_workspace *workspace = config->handler_context.workspace; 629 struct sway_workspace *workspace = config->handler_context.workspace;
@@ -658,11 +634,11 @@ static struct cmd_results *cmd_move_workspace(int argc, char **argv) {
658 struct sway_output *old_output = workspace->output; 634 struct sway_output *old_output = workspace->output;
659 int center_x = workspace->width / 2 + workspace->x, 635 int center_x = workspace->width / 2 + workspace->x,
660 center_y = workspace->height / 2 + workspace->y; 636 center_y = workspace->height / 2 + workspace->y;
661 struct sway_output *new_output = output_in_direction(argv[2], 637 struct sway_output *new_output = output_in_direction(argv[0],
662 old_output, center_x, center_y); 638 old_output, center_x, center_y);
663 if (!new_output) { 639 if (!new_output) {
664 return cmd_results_new(CMD_FAILURE, 640 return cmd_results_new(CMD_FAILURE,
665 "Can't find output with name/direction '%s'", argv[2]); 641 "Can't find output with name/direction '%s'", argv[0]);
666 } 642 }
667 workspace_move_to_output(workspace, new_output); 643 workspace_move_to_output(workspace, new_output);
668 644
@@ -675,9 +651,9 @@ static struct cmd_results *cmd_move_workspace(int argc, char **argv) {
675static struct cmd_results *cmd_move_in_direction( 651static struct cmd_results *cmd_move_in_direction(
676 enum wlr_direction direction, int argc, char **argv) { 652 enum wlr_direction direction, int argc, char **argv) {
677 int move_amt = 10; 653 int move_amt = 10;
678 if (argc > 1) { 654 if (argc) {
679 char *inv; 655 char *inv;
680 move_amt = (int)strtol(argv[1], &inv, 10); 656 move_amt = (int)strtol(argv[0], &inv, 10);
681 if (*inv != '\0' && strcasecmp(inv, "px") != 0) { 657 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
682 return cmd_results_new(CMD_FAILURE, "Invalid distance specified"); 658 return cmd_results_new(CMD_FAILURE, "Invalid distance specified");
683 } 659 }
@@ -769,7 +745,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
769 } 745 }
770 746
771 if (!argc) { 747 if (!argc) {
772 return cmd_results_new(CMD_FAILURE, expected_position_syntax); 748 return cmd_results_new(CMD_INVALID, expected_position_syntax);
773 } 749 }
774 750
775 bool absolute = false; 751 bool absolute = false;
@@ -779,17 +755,20 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
779 ++argv; 755 ++argv;
780 } 756 }
781 if (!argc) { 757 if (!argc) {
782 return cmd_results_new(CMD_FAILURE, expected_position_syntax); 758 return cmd_results_new(CMD_INVALID, expected_position_syntax);
783 } 759 }
784 if (strcmp(argv[0], "position") == 0) { 760 if (strcmp(argv[0], "position") == 0) {
785 --argc; 761 --argc;
786 ++argv; 762 ++argv;
787 } 763 }
788 if (!argc) { 764 if (!argc) {
789 return cmd_results_new(CMD_FAILURE, expected_position_syntax); 765 return cmd_results_new(CMD_INVALID, expected_position_syntax);
790 } 766 }
791 if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 || 767 if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 ||
792 strcmp(argv[0], "pointer") == 0) { 768 strcmp(argv[0], "pointer") == 0) {
769 if (absolute) {
770 return cmd_results_new(CMD_INVALID, expected_position_syntax);
771 }
793 struct sway_seat *seat = config->handler_context.seat; 772 struct sway_seat *seat = config->handler_context.seat;
794 if (!seat->cursor) { 773 if (!seat->cursor) {
795 return cmd_results_new(CMD_FAILURE, "No cursor device"); 774 return cmd_results_new(CMD_FAILURE, "No cursor device");
@@ -875,6 +854,18 @@ static struct cmd_results *cmd_move_to_scratchpad(void) {
875 return cmd_results_new(CMD_SUCCESS, NULL); 854 return cmd_results_new(CMD_SUCCESS, NULL);
876} 855}
877 856
857static const char expected_full_syntax[] = "Expected "
858 "'move left|right|up|down [<amount> [px]]'"
859 " or 'move [--no-auto-back-and-forth] [window|container] [to] workspace"
860 " <name>|next|prev|next_on_output|prev_on_output|current|(number <num>)'"
861 " or 'move [window|container] [to] output <name/id>|left|right|up|down'"
862 " or 'move [window|container] [to] mark <mark>'"
863 " or 'move [window|container] [to] scratchpad'"
864 " or 'move workspace to [output] <name/id>|left|right|up|down'"
865 " or 'move [window|container] [to] [absolute] position <x> [px] <y> [px]'"
866 " or 'move [window|container] [to] [absolute] position center'"
867 " or 'move [window|container] [to] position mouse|cursor|pointer'";
868
878struct cmd_results *cmd_move(int argc, char **argv) { 869struct cmd_results *cmd_move(int argc, char **argv) {
879 struct cmd_results *error = NULL; 870 struct cmd_results *error = NULL;
880 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { 871 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
@@ -886,31 +877,55 @@ struct cmd_results *cmd_move(int argc, char **argv) {
886 } 877 }
887 878
888 if (strcasecmp(argv[0], "left") == 0) { 879 if (strcasecmp(argv[0], "left") == 0) {
889 return cmd_move_in_direction(WLR_DIRECTION_LEFT, argc, argv); 880 return cmd_move_in_direction(WLR_DIRECTION_LEFT, --argc, ++argv);
890 } else if (strcasecmp(argv[0], "right") == 0) { 881 } else if (strcasecmp(argv[0], "right") == 0) {
891 return cmd_move_in_direction(WLR_DIRECTION_RIGHT, argc, argv); 882 return cmd_move_in_direction(WLR_DIRECTION_RIGHT, --argc, ++argv);
892 } else if (strcasecmp(argv[0], "up") == 0) { 883 } else if (strcasecmp(argv[0], "up") == 0) {
893 return cmd_move_in_direction(WLR_DIRECTION_UP, argc, argv); 884 return cmd_move_in_direction(WLR_DIRECTION_UP, --argc, ++argv);
894 } else if (strcasecmp(argv[0], "down") == 0) { 885 } else if (strcasecmp(argv[0], "down") == 0) {
895 return cmd_move_in_direction(WLR_DIRECTION_DOWN, argc, argv); 886 return cmd_move_in_direction(WLR_DIRECTION_DOWN, --argc, ++argv);
896 } else if ((strcasecmp(argv[0], "container") == 0 887 } else if (strcasecmp(argv[0], "workspace") == 0 && argc >= 2
897 || strcasecmp(argv[0], "window") == 0) || 888 && (strcasecmp(argv[1], "to") == 0 ||
898 (strcasecmp(argv[0], "--no-auto-back-and-forth") && argc >= 2 889 strcasecmp(argv[1], "output") == 0)) {
899 && (strcasecmp(argv[1], "container") == 0 890 argc -= 2; argv += 2;
900 || strcasecmp(argv[1], "window") == 0))) {
901 return cmd_move_container(argc, argv);
902 } else if (strcasecmp(argv[0], "workspace") == 0) {
903 return cmd_move_workspace(argc, argv); 891 return cmd_move_workspace(argc, argv);
904 } else if (strcasecmp(argv[0], "scratchpad") == 0 892 }
905 || (strcasecmp(argv[0], "to") == 0 && argc == 2 893
906 && strcasecmp(argv[1], "scratchpad") == 0)) { 894 bool no_auto_back_and_forth = false;
895 if (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) {
896 no_auto_back_and_forth = true;
897 --argc; ++argv;
898 }
899
900 if (strcasecmp(argv[0], "window") == 0 ||
901 strcasecmp(argv[0], "container") == 0) {
902 --argc; ++argv;
903 }
904
905 if (strcasecmp(argv[0], "to") == 0) {
906 --argc; ++argv;
907 }
908
909 if (!argc) {
910 return cmd_results_new(CMD_INVALID, expected_full_syntax);
911 }
912
913 // Only `move [window|container] [to] workspace` supports
914 // `--no-auto-back-and-forth` so treat others as invalid syntax
915 if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) {
916 return cmd_results_new(CMD_INVALID, expected_full_syntax);
917 }
918
919 if (strcasecmp(argv[0], "workspace") == 0 ||
920 strcasecmp(argv[0], "output") == 0 ||
921 strcasecmp(argv[0], "mark") == 0) {
922 return cmd_move_container(no_auto_back_and_forth, argc, argv);
923 } else if (strcasecmp(argv[0], "scratchpad") == 0) {
907 return cmd_move_to_scratchpad(); 924 return cmd_move_to_scratchpad();
908 } else if (strcasecmp(argv[0], "position") == 0) { 925 } else if (strcasecmp(argv[0], "position") == 0 ||
909 return cmd_move_to_position(argc, argv); 926 (argc > 1 && strcasecmp(argv[0], "absolute") == 0 &&
910 } else if (strcasecmp(argv[0], "absolute") == 0) { 927 strcasecmp(argv[1], "position") == 0)) {
911 return cmd_move_to_position(argc, argv); 928 return cmd_move_to_position(argc, argv);
912 } else {
913 return cmd_results_new(CMD_INVALID, expected_syntax);
914 } 929 }
915 return cmd_results_new(CMD_SUCCESS, NULL); 930 return cmd_results_new(CMD_INVALID, expected_full_syntax);
916} 931}
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 80193651..230ceeec 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -187,34 +187,46 @@ set|plus|minus <amount>
187*move* position cursor|mouse|pointer 187*move* position cursor|mouse|pointer
188 Moves the focused container to be centered on the cursor. 188 Moves the focused container to be centered on the cursor.
189 189
190*move* container|window [to] mark <mark> 190*move* [container|window] [to] mark <mark>
191 Moves the focused container to the specified mark. 191 Moves the focused container to the specified mark.
192 192
193*move* [--no-auto-back-and-forth] container|window [to] workspace [number] <name> 193*move* [--no-auto-back-and-forth] [container|window] [to] workspace [number] <name>
194 Moves the focused container to the specified workspace. The string "number" 194 Moves the focused container to the specified workspace. The string "number"
195 is optional and is used to match a workspace with the same number, even if 195 is optional and is used to match a workspace with the same number, even if
196 it has a different name. 196 it has a different name.
197 197
198*move* container|window [to] workspace prev|next|current 198*move* [container|window] [to] workspace prev|next|current
199 Moves the focused container to the previous, next or current workspace on 199 Moves the focused container to the previous, next or current workspace on
200 this output, or if no workspaces remain, the previous or next output. 200 this output, or if no workspaces remain, the previous or next output.
201 201
202*move* container|window [to] workspace prev_on_output|next_on_output 202*move* [container|window] [to] workspace prev_on_output|next_on_output
203 Moves the focused container to the previous or next workspace on this 203 Moves the focused container to the previous or next workspace on this
204 output, wrapping around if already at the first or last workspace. 204 output, wrapping around if already at the first or last workspace.
205 205
206*move* container|window [to] workspace back_and_forth 206*move* [container|window] [to] workspace back_and_forth
207 Moves the focused container to previously focused workspace. 207 Moves the focused container to previously focused workspace.
208 208
209*move* container|window|workspace [to] output <name> 209*move* [container|window] [to] output <name-or-id>
210 Moves the focused container or workspace to the specified output. 210 Moves the focused container to the specified output.
211 211
212*move* container|window|workspace [to] output up|right|down|left 212*move* [container|window] [to] output up|right|down|left
213 Moves the focused container or workspace to next output in the specified 213 Moves the focused container to next output in the specified
214 direction. 214 direction.
215 215
216*move* [to] scratchpad 216*move* [container|window] [to] scratchpad
217 Moves the focused window to the scratchpad. 217 Moves the focused container to the scratchpad.
218
219*move* workspace [to] output <name-or-id>
220 Moves the focused workspace to the specified output.
221
222*move* workspace to [output] <name-or-id>
223 Moves the focused workspace to the specified output.
224
225*move* workspace [to] output up|right|down|left
226 Moves the focused workspace to next output in the specified direction.
227
228*move* workspace to [output] up|right|down|left
229 Moves the focused workspace to next output in the specified direction.
218 230
219*nop* <comment> 231*nop* <comment>
220 A no operation command that can be used to override default behaviour. The 232 A no operation command that can be used to override default behaviour. The