aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-07-09 19:04:45 +0100
committerLibravatar GitHub <noreply@github.com>2018-07-09 19:04:45 +0100
commitebcdce457a318a0c23509fe1e5ab3a3dc94f24b6 (patch)
treeb980c2518830ffc61b57d5721fa2a7fccf12a4ee
parentMerge pull request #2230 from vilhalmer/replace-empty-workspace (diff)
parentRemove duplicate function declaration and add assertion (diff)
downloadsway-ebcdce457a318a0c23509fe1e5ab3a3dc94f24b6.tar.gz
sway-ebcdce457a318a0c23509fe1e5ab3a3dc94f24b6.tar.zst
sway-ebcdce457a318a0c23509fe1e5ab3a3dc94f24b6.zip
Merge pull request #2223 from RyanDwyer/floating-move
Implement some floating move commands
-rw-r--r--include/sway/desktop.h4
-rw-r--r--include/sway/tree/container.h6
-rw-r--r--sway/commands/move.c122
-rw-r--r--sway/desktop/desktop.c9
-rw-r--r--sway/tree/container.c86
5 files changed, 210 insertions, 17 deletions
diff --git a/include/sway/desktop.h b/include/sway/desktop.h
index f1ad759a..348fb187 100644
--- a/include/sway/desktop.h
+++ b/include/sway/desktop.h
@@ -1,4 +1,8 @@
1#include <wlr/types/wlr_surface.h> 1#include <wlr/types/wlr_surface.h>
2 2
3struct sway_container;
4
3void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, 5void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly,
4 bool whole); 6 bool whole);
7
8void desktop_damage_whole_container(struct sway_container *con);
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 728daa84..a69da9db 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -297,4 +297,10 @@ bool container_is_floating(struct sway_container *container);
297 */ 297 */
298void container_get_box(struct sway_container *container, struct wlr_box *box); 298void container_get_box(struct sway_container *container, struct wlr_box *box);
299 299
300/**
301 * Move a floating container to a new layout-local position.
302 */
303void container_floating_move_to(struct sway_container *con,
304 double lx, double ly);
305
300#endif 306#endif
diff --git a/sway/commands/move.c b/sway/commands/move.c
index a4fae388..a1c1e018 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -1,11 +1,13 @@
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/desktop/transaction.h"
10#include "sway/input/cursor.h"
9#include "sway/input/seat.h" 11#include "sway/input/seat.h"
10#include "sway/output.h" 12#include "sway/output.h"
11#include "sway/tree/arrange.h" 13#include "sway/tree/arrange.h"
@@ -184,11 +186,49 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current,
184} 186}
185 187
186static struct cmd_results *move_in_direction(struct sway_container *container, 188static struct cmd_results *move_in_direction(struct sway_container *container,
187 enum movement_direction direction, int move_amt) { 189 enum movement_direction direction, int argc, char **argv) {
190 int move_amt = 10;
191 if (argc > 1) {
192 char *inv;
193 move_amt = (int)strtol(argv[1], &inv, 10);
194 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
195 return cmd_results_new(CMD_FAILURE, "move",
196 "Invalid distance specified");
197 }
198 }
199
188 if (container->type == C_WORKSPACE) { 200 if (container->type == C_WORKSPACE) {
189 return cmd_results_new(CMD_FAILURE, "move", 201 return cmd_results_new(CMD_FAILURE, "move",
190 "Cannot move workspaces in a direction"); 202 "Cannot move workspaces in a direction");
191 } 203 }
204 if (container_is_floating(container)) {
205 if (container->type == C_VIEW && container->sway_view->is_fullscreen) {
206 return cmd_results_new(CMD_FAILURE, "move",
207 "Cannot move fullscreen floating container");
208 }
209 double lx = container->x;
210 double ly = container->y;
211 switch (direction) {
212 case MOVE_LEFT:
213 lx -= move_amt;
214 break;
215 case MOVE_RIGHT:
216 lx += move_amt;
217 break;
218 case MOVE_UP:
219 ly -= move_amt;
220 break;
221 case MOVE_DOWN:
222 ly += move_amt;
223 break;
224 case MOVE_PARENT:
225 case MOVE_CHILD:
226 return cmd_results_new(CMD_FAILURE, "move",
227 "Cannot move floating container to parent or child");
228 }
229 container_floating_move_to(container, lx, ly);
230 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
231 }
192 // For simplicity, we'll arrange the entire workspace. The reason for this 232 // 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 233 // is moving the container might reap the old parent, and container_move
194 // does not return a surviving parent. 234 // does not return a surviving parent.
@@ -208,31 +248,78 @@ static struct cmd_results *move_in_direction(struct sway_container *container,
208 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 248 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
209} 249}
210 250
251static const char* expected_position_syntax =
252 "Expected 'move [absolute] position <x> <y>' or "
253 "'move [absolute] position mouse'";
254
255static struct cmd_results *move_to_position(struct sway_container *container,
256 int argc, char **argv) {
257 if (!container_is_floating(container)) {
258 return cmd_results_new(CMD_FAILURE, "move",
259 "Only floating containers "
260 "can be moved to an absolute position");
261 }
262 if (!argc) {
263 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
264 }
265 if (strcmp(argv[0], "absolute") == 0) {
266 --argc;
267 ++argv;
268 }
269 if (!argc) {
270 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
271 }
272 if (strcmp(argv[0], "position") == 0) {
273 --argc;
274 ++argv;
275 }
276 if (!argc) {
277 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
278 }
279 if (strcmp(argv[0], "mouse") == 0) {
280 struct sway_seat *seat = config->handler_context.seat;
281 if (!seat->cursor) {
282 return cmd_results_new(CMD_FAILURE, "move", "No cursor device");
283 }
284 double lx = seat->cursor->cursor->x - container->width / 2;
285 double ly = seat->cursor->cursor->y - container->height / 2;
286 container_floating_move_to(container, lx, ly);
287 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
288 }
289 if (argc != 2) {
290 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
291 }
292 double lx, ly;
293 char *inv;
294 lx = (double)strtol(argv[0], &inv, 10);
295 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
296 return cmd_results_new(CMD_FAILURE, "move",
297 "Invalid position specified");
298 }
299 ly = (double)strtol(argv[1], &inv, 10);
300 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
301 return cmd_results_new(CMD_FAILURE, "move",
302 "Invalid position specified");
303 }
304 container_floating_move_to(container, lx, ly);
305 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
306}
307
211struct cmd_results *cmd_move(int argc, char **argv) { 308struct cmd_results *cmd_move(int argc, char **argv) {
212 struct cmd_results *error = NULL; 309 struct cmd_results *error = NULL;
213 int move_amt = 10;
214 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { 310 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
215 return error; 311 return error;
216 } 312 }
217 struct sway_container *current = config->handler_context.current_container; 313 struct sway_container *current = config->handler_context.current_container;
218 314
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) { 315 if (strcasecmp(argv[0], "left") == 0) {
229 return move_in_direction(current, MOVE_LEFT, move_amt); 316 return move_in_direction(current, MOVE_LEFT, argc, argv);
230 } else if (strcasecmp(argv[0], "right") == 0) { 317 } else if (strcasecmp(argv[0], "right") == 0) {
231 return move_in_direction(current, MOVE_RIGHT, move_amt); 318 return move_in_direction(current, MOVE_RIGHT, argc, argv);
232 } else if (strcasecmp(argv[0], "up") == 0) { 319 } else if (strcasecmp(argv[0], "up") == 0) {
233 return move_in_direction(current, MOVE_UP, move_amt); 320 return move_in_direction(current, MOVE_UP, argc, argv);
234 } else if (strcasecmp(argv[0], "down") == 0) { 321 } else if (strcasecmp(argv[0], "down") == 0) {
235 return move_in_direction(current, MOVE_DOWN, move_amt); 322 return move_in_direction(current, MOVE_DOWN, argc, argv);
236 } else if (strcasecmp(argv[0], "container") == 0 323 } else if (strcasecmp(argv[0], "container") == 0
237 || strcasecmp(argv[0], "window") == 0) { 324 || strcasecmp(argv[0], "window") == 0) {
238 return cmd_move_container(current, argc, argv); 325 return cmd_move_container(current, argc, argv);
@@ -244,8 +331,9 @@ struct cmd_results *cmd_move(int argc, char **argv) {
244 // TODO: scratchpad 331 // TODO: scratchpad
245 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); 332 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
246 } else if (strcasecmp(argv[0], "position") == 0) { 333 } else if (strcasecmp(argv[0], "position") == 0) {
247 // TODO: floating 334 return move_to_position(current, argc, argv);
248 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); 335 } else if (strcasecmp(argv[0], "absolute") == 0) {
336 return move_to_position(current, argc, argv);
249 } else { 337 } else {
250 return cmd_results_new(CMD_INVALID, "move", expected_syntax); 338 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
251 } 339 }
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c
index e495790c..6575519d 100644
--- a/sway/desktop/desktop.c
+++ b/sway/desktop/desktop.c
@@ -13,3 +13,12 @@ void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly,
13 } 13 }
14 } 14 }
15} 15}
16
17void desktop_damage_whole_container(struct sway_container *con) {
18 for (int i = 0; i < root_container.children->length; ++i) {
19 struct sway_container *cont = root_container.children->items[i];
20 if (cont->type == C_OUTPUT) {
21 output_damage_whole_container(cont->sway_output, con);
22 }
23 }
24}
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 5fdcb6e3..92408ce6 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -11,11 +11,14 @@
11#include "cairo.h" 11#include "cairo.h"
12#include "pango.h" 12#include "pango.h"
13#include "sway/config.h" 13#include "sway/config.h"
14#include "sway/desktop.h"
15#include "sway/desktop/transaction.h"
14#include "sway/input/input-manager.h" 16#include "sway/input/input-manager.h"
15#include "sway/input/seat.h" 17#include "sway/input/seat.h"
16#include "sway/ipc-server.h" 18#include "sway/ipc-server.h"
17#include "sway/output.h" 19#include "sway/output.h"
18#include "sway/server.h" 20#include "sway/server.h"
21#include "sway/tree/arrange.h"
19#include "sway/tree/layout.h" 22#include "sway/tree/layout.h"
20#include "sway/tree/view.h" 23#include "sway/tree/view.h"
21#include "sway/tree/workspace.h" 24#include "sway/tree/workspace.h"
@@ -989,3 +992,86 @@ void container_get_box(struct sway_container *container, struct wlr_box *box) {
989 box->width = container->width; 992 box->width = container->width;
990 box->height = container->height; 993 box->height = container->height;
991} 994}
995
996/**
997 * Translate the container's position as well as all children.
998 */
999static void container_floating_translate(struct sway_container *con,
1000 double x_amount, double y_amount) {
1001 con->x += x_amount;
1002 con->y += y_amount;
1003 con->current.swayc_x += x_amount;
1004 con->current.swayc_y += y_amount;
1005 if (con->type == C_VIEW) {
1006 con->sway_view->x += x_amount;
1007 con->sway_view->y += y_amount;
1008 con->current.view_x += x_amount;
1009 con->current.view_y += y_amount;
1010 } else {
1011 for (int i = 0; i < con->children->length; ++i) {
1012 struct sway_container *child = con->children->items[i];
1013 container_floating_translate(child, x_amount, y_amount);
1014 }
1015 }
1016}
1017
1018/**
1019 * Choose an output for the floating container's new position.
1020 *
1021 * If the center of the container intersects an output then we'll choose that
1022 * one, otherwise we'll choose whichever output is closest to the container's
1023 * center.
1024 */
1025static struct sway_container *container_floating_find_output(
1026 struct sway_container *con) {
1027 double center_x = con->x + con->width / 2;
1028 double center_y = con->y + con->height / 2;
1029 struct sway_container *closest_output = NULL;
1030 double closest_distance = DBL_MAX;
1031 for (int i = 0; i < root_container.children->length; ++i) {
1032 struct sway_container *output = root_container.children->items[i];
1033 struct wlr_box output_box;
1034 double closest_x, closest_y;
1035 container_get_box(output, &output_box);
1036 wlr_box_closest_point(&output_box, center_x, center_y,
1037 &closest_x, &closest_y);
1038 if (center_x == closest_x && center_y == closest_y) {
1039 // The center of the floating container is on this output
1040 return output;
1041 }
1042 double x_dist = closest_x - center_x;
1043 double y_dist = closest_y - center_y;
1044 double distance = x_dist * x_dist + y_dist * y_dist;
1045 if (distance < closest_distance) {
1046 closest_output = output;
1047 closest_distance = distance;
1048 }
1049 }
1050 return closest_output;
1051}
1052
1053void container_floating_move_to(struct sway_container *con,
1054 double lx, double ly) {
1055 if (!sway_assert(container_is_floating(con),
1056 "Expected a floating container")) {
1057 return;
1058 }
1059 desktop_damage_whole_container(con);
1060 container_floating_translate(con, lx - con->x, ly - con->y);
1061 desktop_damage_whole_container(con);
1062 struct sway_container *old_workspace = container_parent(con, C_WORKSPACE);
1063 struct sway_container *new_output = container_floating_find_output(con);
1064 if (!sway_assert(new_output, "Unable to find any output")) {
1065 return;
1066 }
1067 struct sway_container *new_workspace =
1068 output_get_active_workspace(new_output->sway_output);
1069 if (old_workspace != new_workspace) {
1070 container_remove_child(con);
1071 container_add_child(new_workspace->sway_workspace->floating, con);
1072 struct sway_transaction *transaction = transaction_create();
1073 arrange_windows(old_workspace, transaction);
1074 arrange_windows(new_workspace, transaction);
1075 transaction_commit(transaction);
1076 }
1077}