diff options
author | Ian Fan <ianfan0@gmail.com> | 2018-07-31 11:38:34 +0100 |
---|---|---|
committer | Ian Fan <ianfan0@gmail.com> | 2018-08-06 14:17:58 +0100 |
commit | 69e1a421fc2ccecd93f79c9dd0537671138bb0a9 (patch) | |
tree | 4102876eb5f08897e03250929af5754410b0ca96 /sway/commands/move.c | |
parent | commands: complete layout implementation (diff) | |
download | sway-69e1a421fc2ccecd93f79c9dd0537671138bb0a9.tar.gz sway-69e1a421fc2ccecd93f79c9dd0537671138bb0a9.tar.zst sway-69e1a421fc2ccecd93f79c9dd0537671138bb0a9.zip |
commands: complete move implementation
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r-- | sway/commands/move.c | 138 |
1 files changed, 76 insertions, 62 deletions
diff --git a/sway/commands/move.c b/sway/commands/move.c index 841da4c4..b80ce936 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -20,6 +20,7 @@ static const char* expected_syntax = | |||
20 | "Expected 'move <left|right|up|down> <[px] px>' or " | 20 | "Expected 'move <left|right|up|down> <[px] px>' or " |
21 | "'move <container|window> to workspace <name>' or " | 21 | "'move <container|window> to workspace <name>' or " |
22 | "'move <container|window|workspace> to output <name|direction>' or " | 22 | "'move <container|window|workspace> to output <name|direction>' or " |
23 | "'move <container|window> to mark <mark>' or " | ||
23 | "'move position mouse'"; | 24 | "'move position mouse'"; |
24 | 25 | ||
25 | static struct sway_container *output_in_direction(const char *direction, | 26 | static struct sway_container *output_in_direction(const char *direction, |
@@ -54,19 +55,27 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
54 | if ((error = checkarg(argc, "move container/window", | 55 | if ((error = checkarg(argc, "move container/window", |
55 | EXPECTED_AT_LEAST, 4))) { | 56 | EXPECTED_AT_LEAST, 4))) { |
56 | return error; | 57 | return error; |
57 | } else if (strcasecmp(argv[1], "to") == 0 | 58 | } |
58 | && strcasecmp(argv[2], "workspace") == 0) { | 59 | |
59 | // move container to workspace x | 60 | if (current->type == C_WORKSPACE) { |
60 | if (current->type == C_WORKSPACE) { | 61 | if (current->children->length == 0) { |
61 | if (current->children->length == 0) { | ||
62 | return cmd_results_new(CMD_FAILURE, "move", | ||
63 | "Can't move an empty workspace"); | ||
64 | } | ||
65 | current = container_wrap_children(current); | ||
66 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { | ||
67 | return cmd_results_new(CMD_FAILURE, "move", | 62 | return cmd_results_new(CMD_FAILURE, "move", |
68 | "Can only move containers and views."); | 63 | "Can't move an empty workspace"); |
69 | } | 64 | } |
65 | current = container_wrap_children(current); | ||
66 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { | ||
67 | return cmd_results_new(CMD_FAILURE, "move", | ||
68 | "Can only move containers and views."); | ||
69 | } | ||
70 | |||
71 | struct sway_container *old_parent = current->parent; | ||
72 | struct sway_container *old_ws = container_parent(current, C_WORKSPACE); | ||
73 | struct sway_container *destination = NULL; | ||
74 | |||
75 | // determine destination | ||
76 | if (strcasecmp(argv[1], "to") == 0 | ||
77 | && strcasecmp(argv[2], "workspace") == 0) { | ||
78 | // move container to workspace x | ||
70 | struct sway_container *ws; | 79 | struct sway_container *ws; |
71 | char *ws_name = NULL; | 80 | char *ws_name = NULL; |
72 | if (argc == 5 && strcasecmp(argv[3], "number") == 0) { | 81 | if (argc == 5 && strcasecmp(argv[3], "number") == 0) { |
@@ -80,8 +89,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
80 | 89 | ||
81 | if (config->auto_back_and_forth && prev_workspace_name) { | 90 | if (config->auto_back_and_forth && prev_workspace_name) { |
82 | // auto back and forth move | 91 | // auto back and forth move |
83 | struct sway_container *curr_ws = container_parent(current, C_WORKSPACE); | 92 | if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { |
84 | if (curr_ws->name && strcmp(curr_ws->name, ws_name) == 0) { | ||
85 | // if target workspace is the current one | 93 | // if target workspace is the current one |
86 | free(ws_name); | 94 | free(ws_name); |
87 | ws_name = strdup(prev_workspace_name); | 95 | ws_name = strdup(prev_workspace_name); |
@@ -93,63 +101,50 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
93 | ws = workspace_create(NULL, ws_name); | 101 | ws = workspace_create(NULL, ws_name); |
94 | } | 102 | } |
95 | free(ws_name); | 103 | free(ws_name); |
96 | struct sway_container *old_parent = current->parent; | ||
97 | struct sway_container *old_ws = container_parent(current, C_WORKSPACE); | ||
98 | struct sway_container *destination = seat_get_focus_inactive( | ||
99 | config->handler_context.seat, ws); | ||
100 | container_move_to(current, destination); | ||
101 | struct sway_container *focus = seat_get_focus_inactive( | ||
102 | config->handler_context.seat, old_parent); | ||
103 | seat_set_focus_warp(config->handler_context.seat, focus, true, false); | ||
104 | container_reap_empty(old_parent); | ||
105 | container_reap_empty(destination->parent); | ||
106 | |||
107 | // TODO: Ideally we would arrange the surviving parent after reaping, | ||
108 | // but container_reap_empty does not return it, so we arrange the | ||
109 | // workspace instead. | ||
110 | arrange_windows(old_ws); | ||
111 | arrange_windows(destination->parent); | ||
112 | 104 | ||
113 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 105 | destination = seat_get_focus_inactive(config->handler_context.seat, ws); |
114 | } else if (strcasecmp(argv[1], "to") == 0 | 106 | } else if (strcasecmp(argv[1], "to") == 0 |
115 | && strcasecmp(argv[2], "output") == 0) { | 107 | && strcasecmp(argv[2], "output") == 0) { |
116 | if (current->type == C_WORKSPACE) { | ||
117 | // TODO: Wrap children in a container and move that | ||
118 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
119 | } else if (current->type != C_CONTAINER | ||
120 | && current->type != C_VIEW) { | ||
121 | return cmd_results_new(CMD_FAILURE, "move", | ||
122 | "Can only move containers and views."); | ||
123 | } | ||
124 | struct sway_container *source = container_parent(current, C_OUTPUT); | 108 | struct sway_container *source = container_parent(current, C_OUTPUT); |
125 | struct sway_container *destination = output_in_direction(argv[3], | 109 | struct sway_container *dest_output = output_in_direction(argv[3], |
126 | source->sway_output->wlr_output, current->x, current->y); | 110 | source->sway_output->wlr_output, current->x, current->y); |
127 | if (!destination) { | 111 | if (!dest_output) { |
128 | return cmd_results_new(CMD_FAILURE, "move workspace", | 112 | return cmd_results_new(CMD_FAILURE, "move workspace", |
129 | "Can't find output with name/direction '%s'", argv[3]); | 113 | "Can't find output with name/direction '%s'", argv[3]); |
130 | } | 114 | } |
131 | struct sway_container *focus = seat_get_focus_inactive( | 115 | destination = seat_get_focus_inactive( |
132 | config->handler_context.seat, destination); | 116 | config->handler_context.seat, dest_output); |
133 | if (!focus) { | 117 | if (!destination) { |
134 | // We've never been to this output before | 118 | // We've never been to this output before |
135 | focus = destination->children->items[0]; | 119 | destination = dest_output->children->items[0]; |
136 | } | 120 | } |
137 | struct sway_container *old_parent = current->parent; | 121 | } else if (strcasecmp(argv[1], "to") == 0 |
138 | struct sway_container *old_ws = container_parent(current, C_WORKSPACE); | 122 | && strcasecmp(argv[2], "mark") == 0) { |
139 | container_move_to(current, focus); | 123 | struct sway_view *dest_view = view_find_mark(argv[3]); |
140 | seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); | 124 | if (dest_view == NULL) { |
141 | container_reap_empty(old_parent); | 125 | return cmd_results_new(CMD_FAILURE, "move", |
142 | container_reap_empty(focus->parent); | 126 | "Mark '%s' not found", argv[3]); |
127 | } | ||
128 | destination = dest_view->swayc; | ||
129 | } else { | ||
130 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
131 | } | ||
143 | 132 | ||
144 | // TODO: Ideally we would arrange the surviving parent after reaping, | 133 | // move container, arrange windows and return focus |
145 | // but container_reap_empty does not return it, so we arrange the | 134 | container_move_to(current, destination); |
146 | // workspace instead. | 135 | struct sway_container *focus = |
147 | arrange_windows(old_ws); | 136 | seat_get_focus_inactive(config->handler_context.seat, old_parent); |
148 | arrange_windows(focus->parent); | 137 | seat_set_focus_warp(config->handler_context.seat, focus, true, false); |
138 | container_reap_empty(old_parent); | ||
139 | container_reap_empty(destination->parent); | ||
149 | 140 | ||
150 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 141 | // TODO: Ideally we would arrange the surviving parent after reaping, |
151 | } | 142 | // but container_reap_empty does not return it, so we arrange the |
152 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | 143 | // workspace instead. |
144 | arrange_windows(old_ws); | ||
145 | arrange_windows(destination->parent); | ||
146 | |||
147 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
153 | } | 148 | } |
154 | 149 | ||
155 | static struct cmd_results *cmd_move_workspace(struct sway_container *current, | 150 | static struct cmd_results *cmd_move_workspace(struct sway_container *current, |
@@ -243,8 +238,8 @@ static struct cmd_results *move_in_direction(struct sway_container *container, | |||
243 | } | 238 | } |
244 | 239 | ||
245 | static const char* expected_position_syntax = | 240 | static const char* expected_position_syntax = |
246 | "Expected 'move [absolute] position <x> <y>' or " | 241 | "Expected 'move [absolute] position <x> [px] <y> [px]' or " |
247 | "'move [absolute] position mouse'"; | 242 | "'move [absolute] position center|mouse'"; |
248 | 243 | ||
249 | static struct cmd_results *move_to_position(struct sway_container *container, | 244 | static struct cmd_results *move_to_position(struct sway_container *container, |
250 | int argc, char **argv) { | 245 | int argc, char **argv) { |
@@ -279,10 +274,18 @@ static struct cmd_results *move_to_position(struct sway_container *container, | |||
279 | double ly = seat->cursor->cursor->y - container->height / 2; | 274 | double ly = seat->cursor->cursor->y - container->height / 2; |
280 | container_floating_move_to(container, lx, ly); | 275 | container_floating_move_to(container, lx, ly); |
281 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 276 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
277 | } else if (strcmp(argv[0], "center") == 0) { | ||
278 | struct sway_container *ws = container_parent(container, C_WORKSPACE); | ||
279 | double lx = ws->x + (ws->width - container->width) / 2; | ||
280 | double ly = ws->y + (ws->height - container->height) / 2; | ||
281 | container_floating_move_to(container, lx, ly); | ||
282 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
282 | } | 283 | } |
283 | if (argc != 2) { | 284 | |
285 | if (argc < 2) { | ||
284 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | 286 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); |
285 | } | 287 | } |
288 | |||
286 | double lx, ly; | 289 | double lx, ly; |
287 | char *inv; | 290 | char *inv; |
288 | lx = (double)strtol(argv[0], &inv, 10); | 291 | lx = (double)strtol(argv[0], &inv, 10); |
@@ -290,11 +293,22 @@ static struct cmd_results *move_to_position(struct sway_container *container, | |||
290 | return cmd_results_new(CMD_FAILURE, "move", | 293 | return cmd_results_new(CMD_FAILURE, "move", |
291 | "Invalid position specified"); | 294 | "Invalid position specified"); |
292 | } | 295 | } |
296 | if (strcmp(argv[1], "px") == 0) { | ||
297 | --argc; | ||
298 | ++argv; | ||
299 | } | ||
300 | |||
301 | if (argc > 3) { | ||
302 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
303 | } | ||
304 | |||
293 | ly = (double)strtol(argv[1], &inv, 10); | 305 | ly = (double)strtol(argv[1], &inv, 10); |
294 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | 306 | if ((*inv != '\0' && strcasecmp(inv, "px") != 0) || |
307 | (argc == 3 && strcmp(argv[2], "px") != 0)) { | ||
295 | return cmd_results_new(CMD_FAILURE, "move", | 308 | return cmd_results_new(CMD_FAILURE, "move", |
296 | "Invalid position specified"); | 309 | "Invalid position specified"); |
297 | } | 310 | } |
311 | |||
298 | container_floating_move_to(container, lx, ly); | 312 | container_floating_move_to(container, lx, ly); |
299 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 313 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
300 | } | 314 | } |