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.c147
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
186static struct cmd_results *move_in_direction(struct sway_container *container, 181static 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
242static const char* expected_position_syntax =
243 "Expected 'move [absolute] position <x> <y>' or "
244 "'move [absolute] position mouse'";
245
246static 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
211struct cmd_results *cmd_move(int argc, char **argv) { 299struct 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 }