diff options
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r-- | sway/commands/move.c | 147 |
1 files changed, 113 insertions, 34 deletions
diff --git a/sway/commands/move.c b/sway/commands/move.c index a4fae388..6ec050a8 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #define _XOPEN_SOURCE 500 | 1 | #define _XOPEN_SOURCE 500 |
2 | #include <string.h> | 2 | #include <string.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <wlr/types/wlr_cursor.h> | ||
4 | #include <wlr/types/wlr_output.h> | 5 | #include <wlr/types/wlr_output.h> |
5 | #include <wlr/types/wlr_output_layout.h> | 6 | #include <wlr/types/wlr_output_layout.h> |
6 | #include <wlr/util/log.h> | 7 | #include <wlr/util/log.h> |
7 | #include "sway/commands.h" | 8 | #include "sway/commands.h" |
8 | #include "sway/desktop/transaction.h" | 9 | #include "sway/input/cursor.h" |
9 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
10 | #include "sway/output.h" | 11 | #include "sway/output.h" |
11 | #include "sway/tree/arrange.h" | 12 | #include "sway/tree/arrange.h" |
@@ -103,10 +104,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
103 | // TODO: Ideally we would arrange the surviving parent after reaping, | 104 | // TODO: Ideally we would arrange the surviving parent after reaping, |
104 | // but container_reap_empty does not return it, so we arrange the | 105 | // but container_reap_empty does not return it, so we arrange the |
105 | // workspace instead. | 106 | // workspace instead. |
106 | struct sway_transaction *txn = transaction_create(); | 107 | arrange_windows(old_ws); |
107 | arrange_windows(old_ws, txn); | 108 | arrange_windows(destination->parent); |
108 | arrange_windows(destination->parent, txn); | ||
109 | transaction_commit(txn); | ||
110 | 109 | ||
111 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 110 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
112 | } else if (strcasecmp(argv[1], "to") == 0 | 111 | } else if (strcasecmp(argv[1], "to") == 0 |
@@ -142,10 +141,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
142 | // TODO: Ideally we would arrange the surviving parent after reaping, | 141 | // TODO: Ideally we would arrange the surviving parent after reaping, |
143 | // but container_reap_empty does not return it, so we arrange the | 142 | // but container_reap_empty does not return it, so we arrange the |
144 | // workspace instead. | 143 | // workspace instead. |
145 | struct sway_transaction *txn = transaction_create(); | 144 | arrange_windows(old_ws); |
146 | arrange_windows(old_ws, txn); | 145 | arrange_windows(focus->parent); |
147 | arrange_windows(focus->parent, txn); | ||
148 | transaction_commit(txn); | ||
149 | 146 | ||
150 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 147 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
151 | } | 148 | } |
@@ -175,20 +172,56 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, | |||
175 | } | 172 | } |
176 | container_move_to(current, destination); | 173 | container_move_to(current, destination); |
177 | 174 | ||
178 | struct sway_transaction *txn = transaction_create(); | 175 | arrange_windows(source); |
179 | arrange_windows(source, txn); | 176 | arrange_windows(destination); |
180 | arrange_windows(destination, txn); | ||
181 | transaction_commit(txn); | ||
182 | 177 | ||
183 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 178 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
184 | } | 179 | } |
185 | 180 | ||
186 | static struct cmd_results *move_in_direction(struct sway_container *container, | 181 | static struct cmd_results *move_in_direction(struct sway_container *container, |
187 | enum movement_direction direction, int move_amt) { | 182 | enum movement_direction direction, int argc, char **argv) { |
183 | int move_amt = 10; | ||
184 | if (argc > 1) { | ||
185 | char *inv; | ||
186 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
187 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
188 | return cmd_results_new(CMD_FAILURE, "move", | ||
189 | "Invalid distance specified"); | ||
190 | } | ||
191 | } | ||
192 | |||
188 | if (container->type == C_WORKSPACE) { | 193 | if (container->type == C_WORKSPACE) { |
189 | return cmd_results_new(CMD_FAILURE, "move", | 194 | return cmd_results_new(CMD_FAILURE, "move", |
190 | "Cannot move workspaces in a direction"); | 195 | "Cannot move workspaces in a direction"); |
191 | } | 196 | } |
197 | if (container_is_floating(container)) { | ||
198 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { | ||
199 | return cmd_results_new(CMD_FAILURE, "move", | ||
200 | "Cannot move fullscreen floating container"); | ||
201 | } | ||
202 | double lx = container->x; | ||
203 | double ly = container->y; | ||
204 | switch (direction) { | ||
205 | case MOVE_LEFT: | ||
206 | lx -= move_amt; | ||
207 | break; | ||
208 | case MOVE_RIGHT: | ||
209 | lx += move_amt; | ||
210 | break; | ||
211 | case MOVE_UP: | ||
212 | ly -= move_amt; | ||
213 | break; | ||
214 | case MOVE_DOWN: | ||
215 | ly += move_amt; | ||
216 | break; | ||
217 | case MOVE_PARENT: | ||
218 | case MOVE_CHILD: | ||
219 | return cmd_results_new(CMD_FAILURE, "move", | ||
220 | "Cannot move floating container to parent or child"); | ||
221 | } | ||
222 | container_floating_move_to(container, lx, ly); | ||
223 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
224 | } | ||
192 | // For simplicity, we'll arrange the entire workspace. The reason for this | 225 | // For simplicity, we'll arrange the entire workspace. The reason for this |
193 | // is moving the container might reap the old parent, and container_move | 226 | // is moving the container might reap the old parent, and container_move |
194 | // does not return a surviving parent. | 227 | // does not return a surviving parent. |
@@ -198,41 +231,86 @@ static struct cmd_results *move_in_direction(struct sway_container *container, | |||
198 | container_move(container, direction, move_amt); | 231 | container_move(container, direction, move_amt); |
199 | struct sway_container *new_ws = container_parent(container, C_WORKSPACE); | 232 | struct sway_container *new_ws = container_parent(container, C_WORKSPACE); |
200 | 233 | ||
201 | struct sway_transaction *txn = transaction_create(); | 234 | arrange_windows(old_ws); |
202 | arrange_windows(old_ws, txn); | ||
203 | if (new_ws != old_ws) { | 235 | if (new_ws != old_ws) { |
204 | arrange_windows(new_ws, txn); | 236 | arrange_windows(new_ws); |
205 | } | 237 | } |
206 | transaction_commit(txn); | ||
207 | 238 | ||
208 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 239 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
209 | } | 240 | } |
210 | 241 | ||
242 | static const char* expected_position_syntax = | ||
243 | "Expected 'move [absolute] position <x> <y>' or " | ||
244 | "'move [absolute] position mouse'"; | ||
245 | |||
246 | static struct cmd_results *move_to_position(struct sway_container *container, | ||
247 | int argc, char **argv) { | ||
248 | if (!container_is_floating(container)) { | ||
249 | return cmd_results_new(CMD_FAILURE, "move", | ||
250 | "Only floating containers " | ||
251 | "can be moved to an absolute position"); | ||
252 | } | ||
253 | if (!argc) { | ||
254 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
255 | } | ||
256 | if (strcmp(argv[0], "absolute") == 0) { | ||
257 | --argc; | ||
258 | ++argv; | ||
259 | } | ||
260 | if (!argc) { | ||
261 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
262 | } | ||
263 | if (strcmp(argv[0], "position") == 0) { | ||
264 | --argc; | ||
265 | ++argv; | ||
266 | } | ||
267 | if (!argc) { | ||
268 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
269 | } | ||
270 | if (strcmp(argv[0], "mouse") == 0) { | ||
271 | struct sway_seat *seat = config->handler_context.seat; | ||
272 | if (!seat->cursor) { | ||
273 | return cmd_results_new(CMD_FAILURE, "move", "No cursor device"); | ||
274 | } | ||
275 | double lx = seat->cursor->cursor->x - container->width / 2; | ||
276 | double ly = seat->cursor->cursor->y - container->height / 2; | ||
277 | container_floating_move_to(container, lx, ly); | ||
278 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
279 | } | ||
280 | if (argc != 2) { | ||
281 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
282 | } | ||
283 | double lx, ly; | ||
284 | char *inv; | ||
285 | lx = (double)strtol(argv[0], &inv, 10); | ||
286 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
287 | return cmd_results_new(CMD_FAILURE, "move", | ||
288 | "Invalid position specified"); | ||
289 | } | ||
290 | ly = (double)strtol(argv[1], &inv, 10); | ||
291 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
292 | return cmd_results_new(CMD_FAILURE, "move", | ||
293 | "Invalid position specified"); | ||
294 | } | ||
295 | container_floating_move_to(container, lx, ly); | ||
296 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
297 | } | ||
298 | |||
211 | struct cmd_results *cmd_move(int argc, char **argv) { | 299 | struct cmd_results *cmd_move(int argc, char **argv) { |
212 | struct cmd_results *error = NULL; | 300 | struct cmd_results *error = NULL; |
213 | int move_amt = 10; | ||
214 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { | 301 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { |
215 | return error; | 302 | return error; |
216 | } | 303 | } |
217 | struct sway_container *current = config->handler_context.current_container; | 304 | struct sway_container *current = config->handler_context.current_container; |
218 | 305 | ||
219 | if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) { | ||
220 | char *inv; | ||
221 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
222 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
223 | return cmd_results_new(CMD_FAILURE, "move", | ||
224 | "Invalid distance specified"); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | if (strcasecmp(argv[0], "left") == 0) { | 306 | if (strcasecmp(argv[0], "left") == 0) { |
229 | return move_in_direction(current, MOVE_LEFT, move_amt); | 307 | return move_in_direction(current, MOVE_LEFT, argc, argv); |
230 | } else if (strcasecmp(argv[0], "right") == 0) { | 308 | } else if (strcasecmp(argv[0], "right") == 0) { |
231 | return move_in_direction(current, MOVE_RIGHT, move_amt); | 309 | return move_in_direction(current, MOVE_RIGHT, argc, argv); |
232 | } else if (strcasecmp(argv[0], "up") == 0) { | 310 | } else if (strcasecmp(argv[0], "up") == 0) { |
233 | return move_in_direction(current, MOVE_UP, move_amt); | 311 | return move_in_direction(current, MOVE_UP, argc, argv); |
234 | } else if (strcasecmp(argv[0], "down") == 0) { | 312 | } else if (strcasecmp(argv[0], "down") == 0) { |
235 | return move_in_direction(current, MOVE_DOWN, move_amt); | 313 | return move_in_direction(current, MOVE_DOWN, argc, argv); |
236 | } else if (strcasecmp(argv[0], "container") == 0 | 314 | } else if (strcasecmp(argv[0], "container") == 0 |
237 | || strcasecmp(argv[0], "window") == 0) { | 315 | || strcasecmp(argv[0], "window") == 0) { |
238 | return cmd_move_container(current, argc, argv); | 316 | return cmd_move_container(current, argc, argv); |
@@ -244,8 +322,9 @@ struct cmd_results *cmd_move(int argc, char **argv) { | |||
244 | // TODO: scratchpad | 322 | // TODO: scratchpad |
245 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | 323 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); |
246 | } else if (strcasecmp(argv[0], "position") == 0) { | 324 | } else if (strcasecmp(argv[0], "position") == 0) { |
247 | // TODO: floating | 325 | return move_to_position(current, argc, argv); |
248 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | 326 | } else if (strcasecmp(argv[0], "absolute") == 0) { |
327 | return move_to_position(current, argc, argv); | ||
249 | } else { | 328 | } else { |
250 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | 329 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); |
251 | } | 330 | } |