diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-08-08 10:04:11 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-08-08 12:50:42 +1000 |
commit | 5653fc754b09ae5344f42f9e3df71cd4420b7d61 (patch) | |
tree | 2f70bd11f025791a2970850771baa2062413f00c /sway/commands/move.c | |
parent | Fix edge cases when moving floating container to new workspace (diff) | |
download | sway-5653fc754b09ae5344f42f9e3df71cd4420b7d61.tar.gz sway-5653fc754b09ae5344f42f9e3df71cd4420b7d61.tar.zst sway-5653fc754b09ae5344f42f9e3df71cd4420b7d61.zip |
Deny moving a sticky container to workspace if it's the same output
Rationale: Sticky containers are always assigned to the visible
workspace.
The basic idea here is to check the destination's output (move.c:190).
But if the command was `move container to workspace x` then a workspace
might have been created for it. We could destroy the workspace in this
case, but that results in unnecessary IPC events.
To avoid this, the logic for `move container to workspace x` has been
adjusted. It now delays creating the workspace until the end, and uses
`workspace_get_initial_output` to determine and check the output before
creating it.
Diffstat (limited to 'sway/commands/move.c')
-rw-r--r-- | sway/commands/move.c | 38 |
1 files changed, 31 insertions, 7 deletions
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 = |