diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-31 21:21:26 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-04-02 11:12:18 -0400 |
commit | b2d871cfe215a82266d01847f4787bbcf8c721c9 (patch) | |
tree | 87dbae47c65d56730c816d7e6e2123e5e851dec2 /sway/commands/move.c | |
parent | Merge pull request #1684 from swaywm/follow-warp (diff) | |
download | sway-b2d871cfe215a82266d01847f4787bbcf8c721c9.tar.gz sway-b2d871cfe215a82266d01847f4787bbcf8c721c9.tar.zst sway-b2d871cfe215a82266d01847f4787bbcf8c721c9.zip |
Partially implement move command
Works:
- move [container|window] to workspace <name>
- Note, this should be able to move C_CONTAINER but this is untested
- move [workspace] to output [left|right|up|down|<name>]
Not implemented yet:
- move [left|right|up|down]
- move scratchpad
- move position
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r-- | sway/commands/move.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/sway/commands/move.c b/sway/commands/move.c new file mode 100644 index 00000000..222ef314 --- /dev/null +++ b/sway/commands/move.c | |||
@@ -0,0 +1,181 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include <wlr/types/wlr_output.h> | ||
4 | #include <wlr/types/wlr_output_layout.h> | ||
5 | #include <wlr/util/log.h> | ||
6 | #include "sway/commands.h" | ||
7 | #include "sway/input/seat.h" | ||
8 | #include "sway/output.h" | ||
9 | #include "sway/tree/container.h" | ||
10 | #include "sway/tree/layout.h" | ||
11 | #include "sway/tree/workspace.h" | ||
12 | #include "stringop.h" | ||
13 | #include "list.h" | ||
14 | |||
15 | static const char* expected_syntax = | ||
16 | "Expected 'move <left|right|up|down> <[px] px>' or " | ||
17 | "'move <container|window> to workspace <name>' or " | ||
18 | "'move <container|window|workspace> to output <name|direction>' or " | ||
19 | "'move position mouse'"; | ||
20 | |||
21 | static struct sway_container *output_in_direction(const char *direction, | ||
22 | struct wlr_output *reference, int ref_ox, int ref_oy) { | ||
23 | int ref_lx = ref_ox + reference->lx, | ||
24 | ref_ly = ref_oy + reference->ly; | ||
25 | struct { | ||
26 | char *name; | ||
27 | enum wlr_direction direction; | ||
28 | } names[] = { | ||
29 | { "up", WLR_DIRECTION_UP }, | ||
30 | { "down", WLR_DIRECTION_DOWN }, | ||
31 | { "left", WLR_DIRECTION_LEFT }, | ||
32 | { "right", WLR_DIRECTION_RIGHT }, | ||
33 | }; | ||
34 | for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { | ||
35 | if (strcasecmp(names[i].name, direction) == 0) { | ||
36 | struct wlr_output *adjacent = wlr_output_layout_adjacent_output( | ||
37 | root_container.sway_root->output_layout, | ||
38 | names[i].direction, reference, ref_lx, ref_ly); | ||
39 | if (adjacent) { | ||
40 | struct sway_output *sway_output = adjacent->data; | ||
41 | return sway_output->swayc; | ||
42 | } | ||
43 | break; | ||
44 | } | ||
45 | } | ||
46 | return output_by_name(direction); | ||
47 | } | ||
48 | |||
49 | static struct cmd_results *cmd_move_container(struct sway_container *current, | ||
50 | int argc, char **argv) { | ||
51 | struct cmd_results *error = NULL; | ||
52 | if ((error = checkarg(argc, "move container/window", | ||
53 | EXPECTED_AT_LEAST, 4))) { | ||
54 | return error; | ||
55 | } else if (strcasecmp(argv[1], "to") == 0 | ||
56 | && strcasecmp(argv[2], "workspace") == 0) { | ||
57 | // move container to workspace x | ||
58 | if (current->type == C_WORKSPACE) { | ||
59 | // TODO: Wrap children in a container and move that | ||
60 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
61 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { | ||
62 | return cmd_results_new(CMD_FAILURE, "move", | ||
63 | "Can only move containers and views."); | ||
64 | } | ||
65 | struct sway_container *ws; | ||
66 | const char *num_name = NULL; | ||
67 | char *ws_name = NULL; | ||
68 | if (argc == 5 && strcasecmp(argv[3], "number") == 0) { | ||
69 | // move "container to workspace number x" | ||
70 | num_name = argv[4]; | ||
71 | ws = workspace_by_number(num_name); | ||
72 | } else { | ||
73 | ws_name = join_args(argv + 3, argc - 3); | ||
74 | ws = workspace_by_name(ws_name); | ||
75 | } | ||
76 | if (!ws) { | ||
77 | ws = workspace_create(ws_name ? ws_name : num_name); | ||
78 | } | ||
79 | free(ws_name); | ||
80 | struct sway_container *old_parent = current->parent; | ||
81 | struct sway_container *focus = sway_seat_get_focus_inactive( | ||
82 | config->handler_context.seat, ws); | ||
83 | container_move_to(current, focus); | ||
84 | sway_seat_set_focus(config->handler_context.seat, old_parent); | ||
85 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
86 | } else if (strcasecmp(argv[1], "to") == 0 | ||
87 | && strcasecmp(argv[2], "output") == 0) { | ||
88 | if (current->type == C_WORKSPACE) { | ||
89 | // TODO: Wrap children in a container and move that | ||
90 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
91 | } else if (current->type != C_CONTAINER | ||
92 | && current->type != C_VIEW) { | ||
93 | return cmd_results_new(CMD_FAILURE, "move", | ||
94 | "Can only move containers and views."); | ||
95 | } | ||
96 | struct sway_container *source = container_parent(current, C_OUTPUT); | ||
97 | struct sway_container *destination = output_in_direction(argv[3], | ||
98 | source->sway_output->wlr_output, current->x, current->y); | ||
99 | if (!destination) { | ||
100 | return cmd_results_new(CMD_FAILURE, "move workspace", | ||
101 | "Can't find output with name/direction '%s'", argv[3]); | ||
102 | } | ||
103 | struct sway_container *focus = sway_seat_get_focus_inactive( | ||
104 | config->handler_context.seat, destination); | ||
105 | if (!focus) { | ||
106 | // We've never been to this output before | ||
107 | focus = destination->children->items[0]; | ||
108 | } | ||
109 | container_move_to(current, focus); | ||
110 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
111 | } | ||
112 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
113 | } | ||
114 | |||
115 | static struct cmd_results *cmd_move_workspace(struct sway_container *current, | ||
116 | int argc, char **argv) { | ||
117 | struct cmd_results *error = NULL; | ||
118 | if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { | ||
119 | return error; | ||
120 | } else if (strcasecmp(argv[1], "to") != 0 | ||
121 | || strcasecmp(argv[2], "output") != 0) { | ||
122 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
123 | } | ||
124 | struct sway_container *source = container_parent(current, C_OUTPUT); | ||
125 | int center_x = current->width / 2 + current->x, | ||
126 | center_y = current->height / 2 + current->y; | ||
127 | struct sway_container *destination = output_in_direction(argv[3], | ||
128 | source->sway_output->wlr_output, center_x, center_y); | ||
129 | if (!destination) { | ||
130 | return cmd_results_new(CMD_FAILURE, "move workspace", | ||
131 | "Can't find output with name/direction '%s'", argv[3]); | ||
132 | } | ||
133 | if (current->type != C_WORKSPACE) { | ||
134 | current = container_parent(current, C_WORKSPACE); | ||
135 | } | ||
136 | container_move_to(current, destination); | ||
137 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
138 | } | ||
139 | |||
140 | struct cmd_results *cmd_move(int argc, char **argv) { | ||
141 | struct cmd_results *error = NULL; | ||
142 | int move_amt = 10; | ||
143 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { | ||
144 | return error; | ||
145 | } | ||
146 | struct sway_container *current = config->handler_context.current_container; | ||
147 | |||
148 | if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) { | ||
149 | char *inv; | ||
150 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
151 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
152 | move_amt = 10; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | if (strcasecmp(argv[0], "left") == 0) { | ||
157 | container_move(current, MOVE_LEFT, move_amt); | ||
158 | } else if (strcasecmp(argv[0], "right") == 0) { | ||
159 | container_move(current, MOVE_RIGHT, move_amt); | ||
160 | } else if (strcasecmp(argv[0], "up") == 0) { | ||
161 | container_move(current, MOVE_UP, move_amt); | ||
162 | } else if (strcasecmp(argv[0], "down") == 0) { | ||
163 | container_move(current, MOVE_DOWN, move_amt); | ||
164 | } else if (strcasecmp(argv[0], "container") == 0 | ||
165 | || strcasecmp(argv[0], "window") == 0) { | ||
166 | return cmd_move_container(current, argc, argv); | ||
167 | } else if (strcasecmp(argv[0], "workspace") == 0) { | ||
168 | return cmd_move_workspace(current, argc, argv); | ||
169 | } else if (strcasecmp(argv[0], "scratchpad") == 0 | ||
170 | || (strcasecmp(argv[0], "to") == 0 | ||
171 | && strcasecmp(argv[1], "scratchpad") == 0)) { | ||
172 | // TODO: scratchpad | ||
173 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
174 | } else if (strcasecmp(argv[0], "position") == 0) { | ||
175 | // TODO: floating | ||
176 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
177 | } else { | ||
178 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
179 | } | ||
180 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
181 | } | ||