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.
This commit is contained in:
Ryan Dwyer 2018-08-08 10:04:11 +10:00
parent a0649190de
commit 5653fc754b
3 changed files with 36 additions and 10 deletions

View file

@ -16,6 +16,8 @@ struct sway_workspace {
extern char *prev_workspace_name;
struct sway_container *workspace_get_initial_output(const char *name);
char *workspace_next_name(const char *output_name);
bool workspace_switch(struct sway_container *workspace,

View file

@ -100,7 +100,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
// determine destination
if (strcasecmp(argv[1], "workspace") == 0) {
// move container to workspace x
struct sway_container *ws;
struct sway_container *ws = NULL;
char *ws_name = NULL;
if (strcasecmp(argv[2], "next") == 0 ||
strcasecmp(argv[2], "prev") == 0 ||
strcasecmp(argv[2], "next_on_output") == 0 ||
@ -110,14 +111,13 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
} else if (strcasecmp(argv[2], "back_and_forth") == 0) {
if (!(ws = workspace_by_name(argv[2]))) {
if (prev_workspace_name) {
ws = workspace_create(NULL, prev_workspace_name);
ws_name = strdup(prev_workspace_name);
} else {
return cmd_results_new(CMD_FAILURE, "move",
"No workspace was previously active.");
}
}
} else {
char *ws_name = NULL;
if (strcasecmp(argv[2], "number") == 0) {
// move "container to workspace number x"
if (argc < 4) {
@ -141,12 +141,26 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
ws = workspace_by_name(ws_name);
}
}
if (!ws) {
ws = workspace_create(NULL, ws_name);
}
free(ws_name);
}
if (!ws) {
// We have to create the workspace, but if the container is
// sticky and the workspace is going to be created on the same
// output, we'll bail out first.
if (container_is_floating(current) && current->is_sticky) {
struct sway_container *old_output =
container_parent(current, C_OUTPUT);
struct sway_container *new_output =
workspace_get_initial_output(ws_name);
if (old_output == new_output) {
free(ws_name);
return cmd_results_new(CMD_FAILURE, "move",
"Can't move sticky container to another workspace "
"on the same output");
}
}
ws = workspace_create(NULL, ws_name);
}
free(ws_name);
destination = seat_get_focus_inactive(config->handler_context.seat, ws);
} else if (strcasecmp(argv[1], "output") == 0) {
struct sway_container *source = container_parent(current, C_OUTPUT);
@ -173,6 +187,16 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
return cmd_results_new(CMD_INVALID, "move", expected_syntax);
}
if (container_is_floating(current) && current->is_sticky) {
struct sway_container *old_output = container_parent(current, C_OUTPUT);
struct sway_container *new_output = destination->type == C_OUTPUT ?
destination : container_parent(destination, C_OUTPUT);
if (old_output == new_output) {
return cmd_results_new(CMD_FAILURE, "move", "Can't move sticky "
"container to another workspace on the same output");
}
}
// move container, arrange windows and return focus
container_move_to(current, destination);
struct sway_container *focus =

View file

@ -18,7 +18,7 @@
#include "log.h"
#include "util.h"
static struct sway_container *get_workspace_initial_output(const char *name) {
struct sway_container *workspace_get_initial_output(const char *name) {
struct sway_container *parent;
// Search for workspace<->output pair
int e = config->workspace_outputs->length;
@ -48,7 +48,7 @@ static struct sway_container *get_workspace_initial_output(const char *name) {
struct sway_container *workspace_create(struct sway_container *output,
const char *name) {
if (output == NULL) {
output = get_workspace_initial_output(name);
output = workspace_get_initial_output(name);
}
wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name);