summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/tree/view.h5
-rw-r--r--sway/commands/move.c138
-rw-r--r--sway/sway.5.scd17
-rw-r--r--sway/tree/view.c9
4 files changed, 103 insertions, 66 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 37fd02bc..4a3f01e7 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -316,6 +316,11 @@ void view_update_title(struct sway_view *view, bool force);
316void view_execute_criteria(struct sway_view *view); 316void view_execute_criteria(struct sway_view *view);
317 317
318/** 318/**
319 * Find any view that has the given mark and return it.
320 */
321struct sway_view *view_find_mark(char *mark);
322
323/**
319 * Find any view that has the given mark and remove the mark from the view. 324 * Find any view that has the given mark and remove the mark from the view.
320 * Returns true if it matched a view. 325 * Returns true if it matched a view.
321 */ 326 */
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 841da4c4..b80ce936 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -20,6 +20,7 @@ static const char* expected_syntax =
20 "Expected 'move <left|right|up|down> <[px] px>' or " 20 "Expected 'move <left|right|up|down> <[px] px>' or "
21 "'move <container|window> to workspace <name>' or " 21 "'move <container|window> to workspace <name>' or "
22 "'move <container|window|workspace> to output <name|direction>' or " 22 "'move <container|window|workspace> to output <name|direction>' or "
23 "'move <container|window> to mark <mark>' or "
23 "'move position mouse'"; 24 "'move position mouse'";
24 25
25static struct sway_container *output_in_direction(const char *direction, 26static struct sway_container *output_in_direction(const char *direction,
@@ -54,19 +55,27 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
54 if ((error = checkarg(argc, "move container/window", 55 if ((error = checkarg(argc, "move container/window",
55 EXPECTED_AT_LEAST, 4))) { 56 EXPECTED_AT_LEAST, 4))) {
56 return error; 57 return error;
57 } else if (strcasecmp(argv[1], "to") == 0 58 }
58 && strcasecmp(argv[2], "workspace") == 0) { 59
59 // move container to workspace x 60 if (current->type == C_WORKSPACE) {
60 if (current->type == C_WORKSPACE) { 61 if (current->children->length == 0) {
61 if (current->children->length == 0) {
62 return cmd_results_new(CMD_FAILURE, "move",
63 "Can't move an empty workspace");
64 }
65 current = container_wrap_children(current);
66 } else if (current->type != C_CONTAINER && current->type != C_VIEW) {
67 return cmd_results_new(CMD_FAILURE, "move", 62 return cmd_results_new(CMD_FAILURE, "move",
68 "Can only move containers and views."); 63 "Can't move an empty workspace");
69 } 64 }
65 current = container_wrap_children(current);
66 } else if (current->type != C_CONTAINER && current->type != C_VIEW) {
67 return cmd_results_new(CMD_FAILURE, "move",
68 "Can only move containers and views.");
69 }
70
71 struct sway_container *old_parent = current->parent;
72 struct sway_container *old_ws = container_parent(current, C_WORKSPACE);
73 struct sway_container *destination = NULL;
74
75 // determine destination
76 if (strcasecmp(argv[1], "to") == 0
77 && strcasecmp(argv[2], "workspace") == 0) {
78 // move container to workspace x
70 struct sway_container *ws; 79 struct sway_container *ws;
71 char *ws_name = NULL; 80 char *ws_name = NULL;
72 if (argc == 5 && strcasecmp(argv[3], "number") == 0) { 81 if (argc == 5 && strcasecmp(argv[3], "number") == 0) {
@@ -80,8 +89,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
80 89
81 if (config->auto_back_and_forth && prev_workspace_name) { 90 if (config->auto_back_and_forth && prev_workspace_name) {
82 // auto back and forth move 91 // auto back and forth move
83 struct sway_container *curr_ws = container_parent(current, C_WORKSPACE); 92 if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) {
84 if (curr_ws->name && strcmp(curr_ws->name, ws_name) == 0) {
85 // if target workspace is the current one 93 // if target workspace is the current one
86 free(ws_name); 94 free(ws_name);
87 ws_name = strdup(prev_workspace_name); 95 ws_name = strdup(prev_workspace_name);
@@ -93,63 +101,50 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
93 ws = workspace_create(NULL, ws_name); 101 ws = workspace_create(NULL, ws_name);
94 } 102 }
95 free(ws_name); 103 free(ws_name);
96 struct sway_container *old_parent = current->parent;
97 struct sway_container *old_ws = container_parent(current, C_WORKSPACE);
98 struct sway_container *destination = seat_get_focus_inactive(
99 config->handler_context.seat, ws);
100 container_move_to(current, destination);
101 struct sway_container *focus = seat_get_focus_inactive(
102 config->handler_context.seat, old_parent);
103 seat_set_focus_warp(config->handler_context.seat, focus, true, false);
104 container_reap_empty(old_parent);
105 container_reap_empty(destination->parent);
106
107 // TODO: Ideally we would arrange the surviving parent after reaping,
108 // but container_reap_empty does not return it, so we arrange the
109 // workspace instead.
110 arrange_windows(old_ws);
111 arrange_windows(destination->parent);
112 104
113 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 105 destination = seat_get_focus_inactive(config->handler_context.seat, ws);
114 } else if (strcasecmp(argv[1], "to") == 0 106 } else if (strcasecmp(argv[1], "to") == 0
115 && strcasecmp(argv[2], "output") == 0) { 107 && strcasecmp(argv[2], "output") == 0) {
116 if (current->type == C_WORKSPACE) {
117 // TODO: Wrap children in a container and move that
118 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
119 } else if (current->type != C_CONTAINER
120 && current->type != C_VIEW) {
121 return cmd_results_new(CMD_FAILURE, "move",
122 "Can only move containers and views.");
123 }
124 struct sway_container *source = container_parent(current, C_OUTPUT); 108 struct sway_container *source = container_parent(current, C_OUTPUT);
125 struct sway_container *destination = output_in_direction(argv[3], 109 struct sway_container *dest_output = output_in_direction(argv[3],
126 source->sway_output->wlr_output, current->x, current->y); 110 source->sway_output->wlr_output, current->x, current->y);
127 if (!destination) { 111 if (!dest_output) {
128 return cmd_results_new(CMD_FAILURE, "move workspace", 112 return cmd_results_new(CMD_FAILURE, "move workspace",
129 "Can't find output with name/direction '%s'", argv[3]); 113 "Can't find output with name/direction '%s'", argv[3]);
130 } 114 }
131 struct sway_container *focus = seat_get_focus_inactive( 115 destination = seat_get_focus_inactive(
132 config->handler_context.seat, destination); 116 config->handler_context.seat, dest_output);
133 if (!focus) { 117 if (!destination) {
134 // We've never been to this output before 118 // We've never been to this output before
135 focus = destination->children->items[0]; 119 destination = dest_output->children->items[0];
136 } 120 }
137 struct sway_container *old_parent = current->parent; 121 } else if (strcasecmp(argv[1], "to") == 0
138 struct sway_container *old_ws = container_parent(current, C_WORKSPACE); 122 && strcasecmp(argv[2], "mark") == 0) {
139 container_move_to(current, focus); 123 struct sway_view *dest_view = view_find_mark(argv[3]);
140 seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); 124 if (dest_view == NULL) {
141 container_reap_empty(old_parent); 125 return cmd_results_new(CMD_FAILURE, "move",
142 container_reap_empty(focus->parent); 126 "Mark '%s' not found", argv[3]);
127 }
128 destination = dest_view->swayc;
129 } else {
130 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
131 }
143 132
144 // TODO: Ideally we would arrange the surviving parent after reaping, 133 // move container, arrange windows and return focus
145 // but container_reap_empty does not return it, so we arrange the 134 container_move_to(current, destination);
146 // workspace instead. 135 struct sway_container *focus =
147 arrange_windows(old_ws); 136 seat_get_focus_inactive(config->handler_context.seat, old_parent);
148 arrange_windows(focus->parent); 137 seat_set_focus_warp(config->handler_context.seat, focus, true, false);
138 container_reap_empty(old_parent);
139 container_reap_empty(destination->parent);
149 140
150 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 141 // TODO: Ideally we would arrange the surviving parent after reaping,
151 } 142 // but container_reap_empty does not return it, so we arrange the
152 return cmd_results_new(CMD_INVALID, "move", expected_syntax); 143 // workspace instead.
144 arrange_windows(old_ws);
145 arrange_windows(destination->parent);
146
147 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
153} 148}
154 149
155static struct cmd_results *cmd_move_workspace(struct sway_container *current, 150static struct cmd_results *cmd_move_workspace(struct sway_container *current,
@@ -243,8 +238,8 @@ static struct cmd_results *move_in_direction(struct sway_container *container,
243} 238}
244 239
245static const char* expected_position_syntax = 240static const char* expected_position_syntax =
246 "Expected 'move [absolute] position <x> <y>' or " 241 "Expected 'move [absolute] position <x> [px] <y> [px]' or "
247 "'move [absolute] position mouse'"; 242 "'move [absolute] position center|mouse'";
248 243
249static struct cmd_results *move_to_position(struct sway_container *container, 244static struct cmd_results *move_to_position(struct sway_container *container,
250 int argc, char **argv) { 245 int argc, char **argv) {
@@ -279,10 +274,18 @@ static struct cmd_results *move_to_position(struct sway_container *container,
279 double ly = seat->cursor->cursor->y - container->height / 2; 274 double ly = seat->cursor->cursor->y - container->height / 2;
280 container_floating_move_to(container, lx, ly); 275 container_floating_move_to(container, lx, ly);
281 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 276 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
277 } else if (strcmp(argv[0], "center") == 0) {
278 struct sway_container *ws = container_parent(container, C_WORKSPACE);
279 double lx = ws->x + (ws->width - container->width) / 2;
280 double ly = ws->y + (ws->height - container->height) / 2;
281 container_floating_move_to(container, lx, ly);
282 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
282 } 283 }
283 if (argc != 2) { 284
285 if (argc < 2) {
284 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); 286 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
285 } 287 }
288
286 double lx, ly; 289 double lx, ly;
287 char *inv; 290 char *inv;
288 lx = (double)strtol(argv[0], &inv, 10); 291 lx = (double)strtol(argv[0], &inv, 10);
@@ -290,11 +293,22 @@ static struct cmd_results *move_to_position(struct sway_container *container,
290 return cmd_results_new(CMD_FAILURE, "move", 293 return cmd_results_new(CMD_FAILURE, "move",
291 "Invalid position specified"); 294 "Invalid position specified");
292 } 295 }
296 if (strcmp(argv[1], "px") == 0) {
297 --argc;
298 ++argv;
299 }
300
301 if (argc > 3) {
302 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
303 }
304
293 ly = (double)strtol(argv[1], &inv, 10); 305 ly = (double)strtol(argv[1], &inv, 10);
294 if (*inv != '\0' && strcasecmp(inv, "px") != 0) { 306 if ((*inv != '\0' && strcasecmp(inv, "px") != 0) ||
307 (argc == 3 && strcmp(argv[2], "px") != 0)) {
295 return cmd_results_new(CMD_FAILURE, "move", 308 return cmd_results_new(CMD_FAILURE, "move",
296 "Invalid position specified"); 309 "Invalid position specified");
297 } 310 }
311
298 container_floating_move_to(container, lx, ly); 312 container_floating_move_to(container, lx, ly);
299 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 313 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
300} 314}
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index a580c7d6..8083106b 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -123,18 +123,27 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
123*layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... 123*layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]...
124 Cycles the layout mode of the focused container through a list of layouts. 124 Cycles the layout mode of the focused container through a list of layouts.
125 125
126*move* left|right|up|down [<px>] 126*move* left|right|up|down [<px> px]
127 Moves the focused container in the direction specified. If the container, 127 Moves the focused container in the direction specified. If the container,
128 the optional _px_ argument specifies how many pixels to move the container. 128 the optional _px_ argument specifies how many pixels to move the container.
129 If unspecified, the default is 10 pixels. Pixels are ignored when moving 129 If unspecified, the default is 10 pixels. Pixels are ignored when moving
130 tiled containers. 130 tiled containers.
131 131
132*move* [absolute] position <pos_x> [px] <pos_y> [px]
133 Moves the focused container to the specified position.
134
135*move* [absolute] position center|mouse
136 Moves the focused container to be centered on the workspace or mouse.
137
138*move* container|window to mark <mark>
139 Moves the focused container to the specified mark.
140
132*move* container|window to workspace <name> 141*move* container|window to workspace <name>
133 Moves the focused container to the specified workspace. 142 Moves the focused container to the specified workspace.
134 143
135*move* container|window to workspace prev|next 144*move* container|window to workspace prev|next|current
136 Moves the focused container to the previous or next workspace on this 145 Moves the focused container to the previous, next or current workspace on
137 output, or if no workspaces remain, the previous or next output. 146 this output, or if no workspaces remain, the previous or next output.
138 147
139*move* container|window to workspace prev\_on\_output|next\_on\_output 148*move* container|window to workspace prev\_on\_output|next\_on\_output
140 Moves the focused container to the previous or next workspace on this 149 Moves the focused container to the previous or next workspace on this
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 9465b3a1..48bd7ac0 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -891,6 +891,15 @@ static bool find_by_mark_iterator(struct sway_container *con,
891 return con->type == C_VIEW && view_has_mark(con->sway_view, mark); 891 return con->type == C_VIEW && view_has_mark(con->sway_view, mark);
892} 892}
893 893
894struct sway_view *view_find_mark(char *mark) {
895 struct sway_container *container = container_find(&root_container,
896 find_by_mark_iterator, mark);
897 if (!container) {
898 return NULL;
899 }
900 return container->sway_view;
901}
902
894bool view_find_and_unmark(char *mark) { 903bool view_find_and_unmark(char *mark) {
895 struct sway_container *container = container_find(&root_container, 904 struct sway_container *container = container_find(&root_container,
896 find_by_mark_iterator, mark); 905 find_by_mark_iterator, mark);