From 5653fc754b09ae5344f42f9e3df71cd4420b7d61 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 10:04:11 +1000 Subject: [PATCH] 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. --- include/sway/tree/workspace.h | 2 ++ sway/commands/move.c | 40 ++++++++++++++++++++++++++++------- sway/tree/workspace.c | 4 ++-- 3 files changed, 36 insertions(+), 10 deletions(-) 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 { 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, 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, // 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 = 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 @@ #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);