aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/move.c
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 /sway/commands/move.c
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.
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r--sway/commands/move.c179
1 files changed, 97 insertions, 82 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}