aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/move.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r--sway/commands/move.c166
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
186static struct cmd_results *move_in_direction(struct sway_container *container, 182static 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
243static const char* expected_position_syntax =
244 "Expected 'move [absolute] position <x> <y>' or "
245 "'move [absolute] position mouse'";
246
247static 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
300static 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
211struct cmd_results *cmd_move(int argc, char **argv) { 313struct 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 }