diff options
-rw-r--r-- | include/sway/tree/container.h | 11 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 2 | ||||
-rw-r--r-- | sway/commands/move.c | 38 | ||||
-rw-r--r-- | sway/input/seat.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 25 | ||||
-rw-r--r-- | sway/tree/layout.c | 48 | ||||
-rw-r--r-- | sway/tree/workspace.c | 4 |
7 files changed, 99 insertions, 33 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 16a180f8..4d0e6003 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -323,12 +323,23 @@ void container_floating_translate(struct sway_container *con, | |||
323 | double x_amount, double y_amount); | 323 | double x_amount, double y_amount); |
324 | 324 | ||
325 | /** | 325 | /** |
326 | * Choose an output for the floating container's new position. | ||
327 | */ | ||
328 | struct sway_container *container_floating_find_output( | ||
329 | struct sway_container *con); | ||
330 | |||
331 | /** | ||
326 | * Move a floating container to a new layout-local position. | 332 | * Move a floating container to a new layout-local position. |
327 | */ | 333 | */ |
328 | void container_floating_move_to(struct sway_container *con, | 334 | void container_floating_move_to(struct sway_container *con, |
329 | double lx, double ly); | 335 | double lx, double ly); |
330 | 336 | ||
331 | /** | 337 | /** |
338 | * Move a floating container to the center of the workspace. | ||
339 | */ | ||
340 | void container_floating_move_to_center(struct sway_container *con); | ||
341 | |||
342 | /** | ||
332 | * Mark a container as dirty if it isn't already. Dirty containers will be | 343 | * Mark a container as dirty if it isn't already. Dirty containers will be |
333 | * included in the next transaction then unmarked as dirty. | 344 | * included in the next transaction then unmarked as dirty. |
334 | */ | 345 | */ |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 239cbbdb..056f2329 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -16,6 +16,8 @@ struct sway_workspace { | |||
16 | 16 | ||
17 | extern char *prev_workspace_name; | 17 | extern char *prev_workspace_name; |
18 | 18 | ||
19 | struct sway_container *workspace_get_initial_output(const char *name); | ||
20 | |||
19 | char *workspace_next_name(const char *output_name); | 21 | char *workspace_next_name(const char *output_name); |
20 | 22 | ||
21 | bool workspace_switch(struct sway_container *workspace, | 23 | bool workspace_switch(struct sway_container *workspace, |
diff --git a/sway/commands/move.c b/sway/commands/move.c index 95dcb088..de6b1b0a 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -100,7 +100,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
100 | // determine destination | 100 | // determine destination |
101 | if (strcasecmp(argv[1], "workspace") == 0) { | 101 | if (strcasecmp(argv[1], "workspace") == 0) { |
102 | // move container to workspace x | 102 | // move container to workspace x |
103 | struct sway_container *ws; | 103 | struct sway_container *ws = NULL; |
104 | char *ws_name = NULL; | ||
104 | if (strcasecmp(argv[2], "next") == 0 || | 105 | if (strcasecmp(argv[2], "next") == 0 || |
105 | strcasecmp(argv[2], "prev") == 0 || | 106 | strcasecmp(argv[2], "prev") == 0 || |
106 | strcasecmp(argv[2], "next_on_output") == 0 || | 107 | strcasecmp(argv[2], "next_on_output") == 0 || |
@@ -110,14 +111,13 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
110 | } else if (strcasecmp(argv[2], "back_and_forth") == 0) { | 111 | } else if (strcasecmp(argv[2], "back_and_forth") == 0) { |
111 | if (!(ws = workspace_by_name(argv[2]))) { | 112 | if (!(ws = workspace_by_name(argv[2]))) { |
112 | if (prev_workspace_name) { | 113 | if (prev_workspace_name) { |
113 | ws = workspace_create(NULL, prev_workspace_name); | 114 | ws_name = strdup(prev_workspace_name); |
114 | } else { | 115 | } else { |
115 | return cmd_results_new(CMD_FAILURE, "move", | 116 | return cmd_results_new(CMD_FAILURE, "move", |
116 | "No workspace was previously active."); | 117 | "No workspace was previously active."); |
117 | } | 118 | } |
118 | } | 119 | } |
119 | } else { | 120 | } else { |
120 | char *ws_name = NULL; | ||
121 | if (strcasecmp(argv[2], "number") == 0) { | 121 | if (strcasecmp(argv[2], "number") == 0) { |
122 | // move "container to workspace number x" | 122 | // move "container to workspace number x" |
123 | if (argc < 4) { | 123 | if (argc < 4) { |
@@ -141,12 +141,26 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
141 | ws = workspace_by_name(ws_name); | 141 | ws = workspace_by_name(ws_name); |
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | } | |
145 | if (!ws) { | 145 | if (!ws) { |
146 | ws = workspace_create(NULL, ws_name); | 146 | // We have to create the workspace, but if the container is |
147 | // sticky and the workspace is going to be created on the same | ||
148 | // output, we'll bail out first. | ||
149 | if (container_is_floating(current) && current->is_sticky) { | ||
150 | struct sway_container *old_output = | ||
151 | container_parent(current, C_OUTPUT); | ||
152 | struct sway_container *new_output = | ||
153 | workspace_get_initial_output(ws_name); | ||
154 | if (old_output == new_output) { | ||
155 | free(ws_name); | ||
156 | return cmd_results_new(CMD_FAILURE, "move", | ||
157 | "Can't move sticky container to another workspace " | ||
158 | "on the same output"); | ||
159 | } | ||
147 | } | 160 | } |
148 | free(ws_name); | 161 | ws = workspace_create(NULL, ws_name); |
149 | } | 162 | } |
163 | free(ws_name); | ||
150 | destination = seat_get_focus_inactive(config->handler_context.seat, ws); | 164 | destination = seat_get_focus_inactive(config->handler_context.seat, ws); |
151 | } else if (strcasecmp(argv[1], "output") == 0) { | 165 | } else if (strcasecmp(argv[1], "output") == 0) { |
152 | struct sway_container *source = container_parent(current, C_OUTPUT); | 166 | struct sway_container *source = container_parent(current, C_OUTPUT); |
@@ -173,6 +187,16 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
173 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | 187 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); |
174 | } | 188 | } |
175 | 189 | ||
190 | if (container_is_floating(current) && current->is_sticky) { | ||
191 | struct sway_container *old_output = container_parent(current, C_OUTPUT); | ||
192 | struct sway_container *new_output = destination->type == C_OUTPUT ? | ||
193 | destination : container_parent(destination, C_OUTPUT); | ||
194 | if (old_output == new_output) { | ||
195 | return cmd_results_new(CMD_FAILURE, "move", "Can't move sticky " | ||
196 | "container to another workspace on the same output"); | ||
197 | } | ||
198 | } | ||
199 | |||
176 | // move container, arrange windows and return focus | 200 | // move container, arrange windows and return focus |
177 | container_move_to(current, destination); | 201 | container_move_to(current, destination); |
178 | struct sway_container *focus = | 202 | struct sway_container *focus = |
diff --git a/sway/input/seat.c b/sway/input/seat.c index dd4d5c3b..6dd7cf7d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -717,12 +717,8 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
717 | 717 | ||
718 | // If we've focused a floating container, bring it to the front. | 718 | // If we've focused a floating container, bring it to the front. |
719 | // We do this by putting it at the end of the floating list. | 719 | // We do this by putting it at the end of the floating list. |
720 | // This must happen for both the pending and current children lists. | ||
721 | if (container && container_is_floating(container)) { | 720 | if (container && container_is_floating(container)) { |
722 | list_move_to_end(container->parent->children, container); | 721 | list_move_to_end(container->parent->children, container); |
723 | if (container_has_ancestor(container, container->current.parent)) { | ||
724 | list_move_to_end(container->parent->current.children, container); | ||
725 | } | ||
726 | } | 722 | } |
727 | 723 | ||
728 | // clean up unfocused empty workspace on new output | 724 | // clean up unfocused empty workspace on new output |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 6da5ac3c..4507655e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -1163,19 +1163,16 @@ void container_floating_translate(struct sway_container *con, | |||
1163 | double x_amount, double y_amount) { | 1163 | double x_amount, double y_amount) { |
1164 | con->x += x_amount; | 1164 | con->x += x_amount; |
1165 | con->y += y_amount; | 1165 | con->y += y_amount; |
1166 | con->current.swayc_x += x_amount; | ||
1167 | con->current.swayc_y += y_amount; | ||
1168 | if (con->type == C_VIEW) { | 1166 | if (con->type == C_VIEW) { |
1169 | con->sway_view->x += x_amount; | 1167 | con->sway_view->x += x_amount; |
1170 | con->sway_view->y += y_amount; | 1168 | con->sway_view->y += y_amount; |
1171 | con->current.view_x += x_amount; | ||
1172 | con->current.view_y += y_amount; | ||
1173 | } else { | 1169 | } else { |
1174 | for (int i = 0; i < con->children->length; ++i) { | 1170 | for (int i = 0; i < con->children->length; ++i) { |
1175 | struct sway_container *child = con->children->items[i]; | 1171 | struct sway_container *child = con->children->items[i]; |
1176 | container_floating_translate(child, x_amount, y_amount); | 1172 | container_floating_translate(child, x_amount, y_amount); |
1177 | } | 1173 | } |
1178 | } | 1174 | } |
1175 | container_set_dirty(con); | ||
1179 | } | 1176 | } |
1180 | 1177 | ||
1181 | /** | 1178 | /** |
@@ -1185,7 +1182,7 @@ void container_floating_translate(struct sway_container *con, | |||
1185 | * one, otherwise we'll choose whichever output is closest to the container's | 1182 | * one, otherwise we'll choose whichever output is closest to the container's |
1186 | * center. | 1183 | * center. |
1187 | */ | 1184 | */ |
1188 | static struct sway_container *container_floating_find_output( | 1185 | struct sway_container *container_floating_find_output( |
1189 | struct sway_container *con) { | 1186 | struct sway_container *con) { |
1190 | double center_x = con->x + con->width / 2; | 1187 | double center_x = con->x + con->width / 2; |
1191 | double center_y = con->y + con->height / 2; | 1188 | double center_y = con->y + con->height / 2; |
@@ -1219,9 +1216,7 @@ void container_floating_move_to(struct sway_container *con, | |||
1219 | "Expected a floating container")) { | 1216 | "Expected a floating container")) { |
1220 | return; | 1217 | return; |
1221 | } | 1218 | } |
1222 | desktop_damage_whole_container(con); | ||
1223 | container_floating_translate(con, lx - con->x, ly - con->y); | 1219 | container_floating_translate(con, lx - con->x, ly - con->y); |
1224 | desktop_damage_whole_container(con); | ||
1225 | struct sway_container *old_workspace = container_parent(con, C_WORKSPACE); | 1220 | struct sway_container *old_workspace = container_parent(con, C_WORKSPACE); |
1226 | struct sway_container *new_output = container_floating_find_output(con); | 1221 | struct sway_container *new_output = container_floating_find_output(con); |
1227 | if (!sway_assert(new_output, "Unable to find any output")) { | 1222 | if (!sway_assert(new_output, "Unable to find any output")) { |
@@ -1239,6 +1234,17 @@ void container_floating_move_to(struct sway_container *con, | |||
1239 | } | 1234 | } |
1240 | } | 1235 | } |
1241 | 1236 | ||
1237 | void container_floating_move_to_center(struct sway_container *con) { | ||
1238 | if (!sway_assert(container_is_floating(con), | ||
1239 | "Expected a floating container")) { | ||
1240 | return; | ||
1241 | } | ||
1242 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
1243 | double new_lx = ws->x + (ws->width - con->width) / 2; | ||
1244 | double new_ly = ws->y + (ws->height - con->height) / 2; | ||
1245 | container_floating_translate(con, new_lx - con->x, new_ly - con->y); | ||
1246 | } | ||
1247 | |||
1242 | void container_set_dirty(struct sway_container *container) { | 1248 | void container_set_dirty(struct sway_container *container) { |
1243 | if (container->dirty) { | 1249 | if (container->dirty) { |
1244 | return; | 1250 | return; |
@@ -1318,6 +1324,11 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { | |||
1318 | container->y = container->saved_y; | 1324 | container->y = container->saved_y; |
1319 | container->width = container->saved_width; | 1325 | container->width = container->saved_width; |
1320 | container->height = container->saved_height; | 1326 | container->height = container->saved_height; |
1327 | struct sway_container *output = | ||
1328 | container_floating_find_output(container); | ||
1329 | if (!container_has_ancestor(container, output)) { | ||
1330 | container_floating_move_to_center(container); | ||
1331 | } | ||
1321 | } else { | 1332 | } else { |
1322 | container->width = container->saved_width; | 1333 | container->width = container->saved_width; |
1323 | container->height = container->saved_height; | 1334 | container->height = container->saved_height; |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 20815654..38e14d00 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -150,22 +150,44 @@ void container_move_to(struct sway_container *container, | |||
150 | || container_has_ancestor(container, destination)) { | 150 | || container_has_ancestor(container, destination)) { |
151 | return; | 151 | return; |
152 | } | 152 | } |
153 | struct sway_container *old_parent = NULL; | ||
154 | struct sway_container *new_parent = NULL; | ||
153 | if (container_is_floating(container)) { | 155 | if (container_is_floating(container)) { |
154 | // TODO | 156 | // Resolve destination into a workspace |
155 | return; | 157 | struct sway_container *new_ws = NULL; |
156 | } | 158 | if (destination->type == C_OUTPUT) { |
157 | struct sway_container *old_parent = container_remove_child(container); | 159 | new_ws = output_get_active_workspace(destination->sway_output); |
158 | container->width = container->height = 0; | 160 | } else if (destination->type == C_WORKSPACE) { |
159 | container->saved_width = container->saved_height = 0; | 161 | new_ws = destination; |
160 | 162 | } else { | |
161 | struct sway_container *new_parent; | 163 | new_ws = container_parent(destination, C_WORKSPACE); |
162 | 164 | } | |
163 | if (destination->type == C_VIEW) { | 165 | if (!new_ws) { |
164 | new_parent = container_add_sibling(destination, container); | 166 | // This can happen if the user has run "move container to mark foo", |
167 | // where mark foo is on a hidden scratchpad container. | ||
168 | return; | ||
169 | } | ||
170 | struct sway_container *old_output = | ||
171 | container_parent(container, C_OUTPUT); | ||
172 | old_parent = container_remove_child(container); | ||
173 | container_add_child(new_ws->sway_workspace->floating, container); | ||
174 | // If changing output, center it within the workspace | ||
175 | if (old_output != new_ws->parent && !container->is_fullscreen) { | ||
176 | container_floating_move_to_center(container); | ||
177 | } | ||
165 | } else { | 178 | } else { |
166 | new_parent = destination; | 179 | old_parent = container_remove_child(container); |
167 | container_add_child(destination, container); | 180 | container->width = container->height = 0; |
181 | container->saved_width = container->saved_height = 0; | ||
182 | |||
183 | if (destination->type == C_VIEW) { | ||
184 | new_parent = container_add_sibling(destination, container); | ||
185 | } else { | ||
186 | new_parent = destination; | ||
187 | container_add_child(destination, container); | ||
188 | } | ||
168 | } | 189 | } |
190 | |||
169 | wl_signal_emit(&container->events.reparent, old_parent); | 191 | wl_signal_emit(&container->events.reparent, old_parent); |
170 | 192 | ||
171 | if (container->type == C_VIEW) { | 193 | if (container->type == C_VIEW) { |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 395c6c10..b8bec044 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "util.h" | 19 | #include "util.h" |
20 | 20 | ||
21 | static struct sway_container *get_workspace_initial_output(const char *name) { | 21 | struct sway_container *workspace_get_initial_output(const char *name) { |
22 | struct sway_container *parent; | 22 | struct sway_container *parent; |
23 | // Search for workspace<->output pair | 23 | // Search for workspace<->output pair |
24 | int e = config->workspace_outputs->length; | 24 | int e = config->workspace_outputs->length; |
@@ -48,7 +48,7 @@ static struct sway_container *get_workspace_initial_output(const char *name) { | |||
48 | struct sway_container *workspace_create(struct sway_container *output, | 48 | struct sway_container *workspace_create(struct sway_container *output, |
49 | const char *name) { | 49 | const char *name) { |
50 | if (output == NULL) { | 50 | if (output == NULL) { |
51 | output = get_workspace_initial_output(name); | 51 | output = workspace_get_initial_output(name); |
52 | } | 52 | } |
53 | 53 | ||
54 | wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name); | 54 | wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name); |