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