From 710f27d0d2a33e937d5b8dd8c9342b19fa04ebe9 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 10:33:21 +0100 Subject: [PATCH 01/27] commands: allow "first", "last", "newest" and "recent" as values for urgent criteria --- sway/criteria.c | 11 ++++++++--- sway/sway.5.scd | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/sway/criteria.c b/sway/criteria.c index 39d300ea..dd995c4b 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -452,13 +452,18 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { criteria->tiling = true; break; case T_URGENT: - if (strcmp(effective_value, "latest") == 0) { + if (strcmp(effective_value, "latest") == 0 || + strcmp(effective_value, "newest") == 0 || + strcmp(effective_value, "last") == 0 || + strcmp(effective_value, "recent") == 0) { criteria->urgent = 'l'; - } else if (strcmp(effective_value, "oldest") == 0) { + } else if (strcmp(effective_value, "oldest") == 0 || + strcmp(effective_value, "first") == 0) { criteria->urgent = 'o'; } else { error = - strdup("The value for 'urgent' must be 'latest' or 'oldest'"); + strdup("The value for 'urgent' must be 'first', 'last', " + "'latest', 'newest', 'oldest' or 'recent'"); } break; case T_WORKSPACE: diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 82df38e3..2d35f5d0 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -612,7 +612,8 @@ The following attributes may be matched with: currently focused window. *urgent* - Compares the urgent state of the window. Can be "latest" or "oldest". + Compares the urgent state of the window. Can be "first", "last", "latest", + "newest", "oldest" or "recent". *window\_role* Compare against the window role (WM\_WINDOW\_ROLE). Can be a regular From 11ac66d6fef118077731fccdaecc350257b8942a Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 11:16:28 +0100 Subject: [PATCH 02/27] commands: allow __focused__ for con_id criterion --- sway/criteria.c | 15 ++++++++++++--- sway/sway.5.scd | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/sway/criteria.c b/sway/criteria.c index dd995c4b..2fa9878b 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -361,8 +361,17 @@ static char *get_focused_prop(enum criteria_token token) { } } break; - case T_CON_ID: // These do not support __focused__ - case T_CON_MARK: + case T_CON_ID: + if (view->swayc == NULL) { + return NULL; + } + size_t id = view->swayc->id; + int len = snprintf(NULL, 0, "%zu", id) + 1; + char *id_str = malloc(len); + snprintf(id_str, len, "%zu", id); + value = id_str; + break; + case T_CON_MARK: // These do not support __focused__ case T_FLOATING: #ifdef HAVE_XWAYLAND case T_ID: @@ -425,7 +434,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { case T_CON_ID: criteria->con_id = strtoul(effective_value, &endptr, 10); if (*endptr != 0) { - error = strdup("The value for 'con_id' should be numeric"); + error = strdup("The value for 'con_id' should be '__focused__' or numeric"); } break; case T_CON_MARK: diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 2d35f5d0..b639653a 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -582,7 +582,9 @@ The following attributes may be matched with: the currently focused window. *con\_id* - Compare against the internal container ID, which you can find via IPC. + Compare against the internal container ID, which you can find via IPC. If + value is \_\_focused\_\_, then the id must be the same as that of the + currently focused window. *con\_mark* Compare against the window marks. Can be a regular expression. From be64c466245d4c537a70484abfe21adc9d60f3c5 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 12:27:34 +0100 Subject: [PATCH 03/27] commands: complete layout implementation --- sway/commands/layout.c | 76 +++++++++++++++++++++++++++++++++--------- sway/sway.5.scd | 12 +++++-- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/sway/commands/layout.c b/sway/commands/layout.c index c446f1f9..ec170591 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -1,3 +1,4 @@ +#include #include #include #include "sway/commands.h" @@ -5,6 +6,26 @@ #include "sway/tree/container.h" #include "log.h" +static bool parse_layout_string(char *s, enum sway_container_layout *ptr) { + if (strcasecmp(s, "splith") == 0) { + *ptr = L_HORIZ; + } else if (strcasecmp(s, "splitv") == 0) { + *ptr = L_VERT; + } else if (strcasecmp(s, "tabbed") == 0) { + *ptr = L_TABBED; + } else if (strcasecmp(s, "stacking") == 0) { + *ptr = L_STACKED; + } else { + return false; + } + return true; +} + +static const char* expected_syntax = + "Expected 'layout default|tabbed|stacking|splitv|splith' or " + "'layout toggle [split|all]' or " + "'layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]...'"; + struct cmd_results *cmd_layout(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { @@ -23,30 +44,55 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (strcasecmp(argv[0], "default") == 0) { parent->layout = parent->prev_layout; - if (parent->layout == L_NONE) { - parent->layout = container_get_default_layout(parent); - } } else { if (parent->layout != L_TABBED && parent->layout != L_STACKED) { parent->prev_layout = parent->layout; } - if (strcasecmp(argv[0], "splith") == 0) { - parent->layout = L_HORIZ; - } else if (strcasecmp(argv[0], "splitv") == 0) { - parent->layout = L_VERT; - } else if (strcasecmp(argv[0], "tabbed") == 0) { - parent->layout = L_TABBED; - } else if (strcasecmp(argv[0], "stacking") == 0) { - parent->layout = L_STACKED; - } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { - if (parent->layout == L_HORIZ) { - parent->layout = L_VERT; + bool assigned_directly = parse_layout_string(argv[0], &parent->layout); + if (!assigned_directly && strcasecmp(argv[0], "toggle") == 0) { + if (argc == 1) { + parent->layout = + parent->layout == L_STACKED ? L_TABBED : + parent->layout == L_TABBED ? parent->prev_layout : L_STACKED; + } else if (argc == 2) { + if (strcasecmp(argv[1], "all") == 0) { + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + parent->layout == L_VERT ? L_STACKED : + parent->layout == L_STACKED ? L_TABBED : L_HORIZ; + } else if (strcasecmp(argv[1], "split") == 0) { + parent->layout = parent->layout == L_VERT ? L_HORIZ : L_VERT; + } else { + return cmd_results_new(CMD_INVALID, "layout", expected_syntax); + } } else { - parent->layout = L_HORIZ; + bool valid; + enum sway_container_layout parsed_layout; + int curr = 1; + for (; curr < argc; curr++) { + valid = parse_layout_string(argv[curr], &parsed_layout); + if (valid && parsed_layout == parent->layout) { + break; + } + } + for (int i = curr + 1; i != curr; ++i) { + // cycle round to find next valid layout + if (i >= argc) { + i = 1; + } + if (parse_layout_string(argv[i], &parent->layout)) { + break; + } // invalid layout strings are silently ignored + } } + } else { + return cmd_results_new(CMD_INVALID, "layout", expected_syntax); } } + if (parent->layout == L_NONE) { + parent->layout = container_get_default_layout(parent); + } container_notify_subtree_changed(parent); arrange_windows(parent); diff --git a/sway/sway.5.scd b/sway/sway.5.scd index b639653a..a580c7d6 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -111,11 +111,17 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *fullscreen* Toggles fullscreen for the focused view. -*layout* splith|splitv|stacking|tabbed +*layout* default|splith|splitv|stacking|tabbed Sets the layout mode of the focused container. -*layout* toggle split - Switches the focused container between the splitv and splith layouts. +*layout* toggle [split|all] + Cycles the layout mode of the focused container though a preset list of + layouts. If no argument is given, then it cycles through stacking, tabbed + and the last split layout. If "split" is given, then it cycles through + splith and splitv. If "all" is given, then it cycles through every layout. + +*layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... + Cycles the layout mode of the focused container through a list of layouts. *move* left|right|up|down [] Moves the focused container in the direction specified. If the container, From 69e1a421fc2ccecd93f79c9dd0537671138bb0a9 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Tue, 31 Jul 2018 11:38:34 +0100 Subject: [PATCH 04/27] commands: complete move implementation --- include/sway/tree/view.h | 5 ++ sway/commands/move.c | 140 +++++++++++++++++++++------------------ sway/sway.5.scd | 17 +++-- sway/tree/view.c | 9 +++ 4 files changed, 104 insertions(+), 67 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 @@ -315,6 +315,11 @@ void view_update_title(struct sway_view *view, bool force); */ void view_execute_criteria(struct sway_view *view); +/** + * Find any view that has the given mark and return it. + */ +struct sway_view *view_find_mark(char *mark); + /** * Find any view that has the given mark and remove the mark from the view. * Returns true if it matched a view. 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 = "Expected 'move <[px] px>' or " "'move to workspace ' or " "'move to output ' or " + "'move to mark ' or " "'move position mouse'"; static struct sway_container *output_in_direction(const char *direction, @@ -54,19 +55,27 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { return error; - } else if (strcasecmp(argv[1], "to") == 0 + } + + if (current->type == C_WORKSPACE) { + if (current->children->length == 0) { + return cmd_results_new(CMD_FAILURE, "move", + "Can't move an empty workspace"); + } + current = container_wrap_children(current); + } else if (current->type != C_CONTAINER && current->type != C_VIEW) { + return cmd_results_new(CMD_FAILURE, "move", + "Can only move containers and views."); + } + + struct sway_container *old_parent = current->parent; + struct sway_container *old_ws = container_parent(current, C_WORKSPACE); + struct sway_container *destination = NULL; + + // determine destination + if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "workspace") == 0) { // move container to workspace x - if (current->type == C_WORKSPACE) { - if (current->children->length == 0) { - return cmd_results_new(CMD_FAILURE, "move", - "Can't move an empty workspace"); - } - current = container_wrap_children(current); - } else if (current->type != C_CONTAINER && current->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move", - "Can only move containers and views."); - } struct sway_container *ws; char *ws_name = NULL; if (argc == 5 && strcasecmp(argv[3], "number") == 0) { @@ -80,8 +89,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if (config->auto_back_and_forth && prev_workspace_name) { // auto back and forth move - struct sway_container *curr_ws = container_parent(current, C_WORKSPACE); - if (curr_ws->name && strcmp(curr_ws->name, ws_name) == 0) { + if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { // if target workspace is the current one free(ws_name); ws_name = strdup(prev_workspace_name); @@ -93,63 +101,50 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, ws = workspace_create(NULL, ws_name); } free(ws_name); - struct sway_container *old_parent = current->parent; - struct sway_container *old_ws = container_parent(current, C_WORKSPACE); - struct sway_container *destination = seat_get_focus_inactive( - config->handler_context.seat, ws); - container_move_to(current, destination); - struct sway_container *focus = seat_get_focus_inactive( - config->handler_context.seat, old_parent); - seat_set_focus_warp(config->handler_context.seat, focus, true, false); - container_reap_empty(old_parent); - container_reap_empty(destination->parent); - // TODO: Ideally we would arrange the surviving parent after reaping, - // but container_reap_empty does not return it, so we arrange the - // workspace instead. - arrange_windows(old_ws); - arrange_windows(destination->parent); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); + destination = seat_get_focus_inactive(config->handler_context.seat, ws); } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { - if (current->type == C_WORKSPACE) { - // TODO: Wrap children in a container and move that - return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); - } else if (current->type != C_CONTAINER - && current->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move", - "Can only move containers and views."); - } struct sway_container *source = container_parent(current, C_OUTPUT); - struct sway_container *destination = output_in_direction(argv[3], + struct sway_container *dest_output = output_in_direction(argv[3], source->sway_output->wlr_output, current->x, current->y); - if (!destination) { + if (!dest_output) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[3]); } - struct sway_container *focus = seat_get_focus_inactive( - config->handler_context.seat, destination); - if (!focus) { + destination = seat_get_focus_inactive( + config->handler_context.seat, dest_output); + if (!destination) { // We've never been to this output before - focus = destination->children->items[0]; + destination = dest_output->children->items[0]; } - struct sway_container *old_parent = current->parent; - struct sway_container *old_ws = container_parent(current, C_WORKSPACE); - container_move_to(current, focus); - seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); - container_reap_empty(old_parent); - container_reap_empty(focus->parent); - - // TODO: Ideally we would arrange the surviving parent after reaping, - // but container_reap_empty does not return it, so we arrange the - // workspace instead. - arrange_windows(old_ws); - arrange_windows(focus->parent); - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else if (strcasecmp(argv[1], "to") == 0 + && strcasecmp(argv[2], "mark") == 0) { + struct sway_view *dest_view = view_find_mark(argv[3]); + if (dest_view == NULL) { + return cmd_results_new(CMD_FAILURE, "move", + "Mark '%s' not found", argv[3]); + } + destination = dest_view->swayc; + } else { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); } - return cmd_results_new(CMD_INVALID, "move", expected_syntax); + + // move container, arrange windows and return focus + container_move_to(current, destination); + struct sway_container *focus = + seat_get_focus_inactive(config->handler_context.seat, old_parent); + seat_set_focus_warp(config->handler_context.seat, focus, true, false); + container_reap_empty(old_parent); + container_reap_empty(destination->parent); + + // TODO: Ideally we would arrange the surviving parent after reaping, + // but container_reap_empty does not return it, so we arrange the + // workspace instead. + arrange_windows(old_ws); + arrange_windows(destination->parent); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } static 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, } static const char* expected_position_syntax = - "Expected 'move [absolute] position ' or " - "'move [absolute] position mouse'"; + "Expected 'move [absolute] position [px] [px]' or " + "'move [absolute] position center|mouse'"; static struct cmd_results *move_to_position(struct sway_container *container, int argc, char **argv) { @@ -279,10 +274,18 @@ static struct cmd_results *move_to_position(struct sway_container *container, double ly = seat->cursor->cursor->y - container->height / 2; container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else if (strcmp(argv[0], "center") == 0) { + struct sway_container *ws = container_parent(container, C_WORKSPACE); + double lx = ws->x + (ws->width - container->width) / 2; + double ly = ws->y + (ws->height - container->height) / 2; + container_floating_move_to(container, lx, ly); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } - if (argc != 2) { + + if (argc < 2) { return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); } + double lx, ly; char *inv; lx = (double)strtol(argv[0], &inv, 10); @@ -290,11 +293,22 @@ static struct cmd_results *move_to_position(struct sway_container *container, return cmd_results_new(CMD_FAILURE, "move", "Invalid position specified"); } + if (strcmp(argv[1], "px") == 0) { + --argc; + ++argv; + } + + if (argc > 3) { + return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); + } + ly = (double)strtol(argv[1], &inv, 10); - if (*inv != '\0' && strcasecmp(inv, "px") != 0) { + if ((*inv != '\0' && strcasecmp(inv, "px") != 0) || + (argc == 3 && strcmp(argv[2], "px") != 0)) { return cmd_results_new(CMD_FAILURE, "move", "Invalid position specified"); } + container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } 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). *layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... Cycles the layout mode of the focused container through a list of layouts. -*move* left|right|up|down [] +*move* left|right|up|down [ px] Moves the focused container in the direction specified. If the container, the optional _px_ argument specifies how many pixels to move the container. If unspecified, the default is 10 pixels. Pixels are ignored when moving tiled containers. +*move* [absolute] position [px] [px] + Moves the focused container to the specified position. + +*move* [absolute] position center|mouse + Moves the focused container to be centered on the workspace or mouse. + +*move* container|window to mark + Moves the focused container to the specified mark. + *move* container|window to workspace Moves the focused container to the specified workspace. -*move* container|window to workspace prev|next - Moves the focused container to the previous or next workspace on this - output, or if no workspaces remain, the previous or next output. +*move* container|window to workspace prev|next|current + Moves the focused container to the previous, next or current workspace on + this output, or if no workspaces remain, the previous or next output. *move* container|window to workspace prev\_on\_output|next\_on\_output 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, return con->type == C_VIEW && view_has_mark(con->sway_view, mark); } +struct sway_view *view_find_mark(char *mark) { + struct sway_container *container = container_find(&root_container, + find_by_mark_iterator, mark); + if (!container) { + return NULL; + } + return container->sway_view; +} + bool view_find_and_unmark(char *mark) { struct sway_container *container = container_find(&root_container, find_by_mark_iterator, mark); From 3a980857cba80719e70ee3960b5b3b12923fda81 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 1 Aug 2018 16:02:56 +0100 Subject: [PATCH 05/27] commands: better type for con_id string length --- sway/criteria.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/criteria.c b/sway/criteria.c index 2fa9878b..9077aa9b 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -366,9 +366,9 @@ static char *get_focused_prop(enum criteria_token token) { return NULL; } size_t id = view->swayc->id; - int len = snprintf(NULL, 0, "%zu", id) + 1; - char *id_str = malloc(len); - snprintf(id_str, len, "%zu", id); + size_t id_size = snprintf(NULL, 0, "%zu", id) + 1; + char *id_str = malloc(id_size); + snprintf(id_str, id_size, "%zu", id); value = id_str; break; case T_CON_MARK: // These do not support __focused__ From 356063b6c084a7c2d4e3e654fe48ec79a102294b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 1 Aug 2018 16:03:37 +0100 Subject: [PATCH 06/27] commands: fix layout implementation (also better name for previous split layout) --- include/sway/tree/container.h | 2 +- sway/commands/layout.c | 43 +++++++++++++++++++++-------------- sway/tree/layout.c | 4 ++-- sway/tree/workspace.c | 2 +- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 44ff9f7d..16a180f8 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -113,7 +113,7 @@ struct sway_container { enum sway_container_type type; enum sway_container_layout layout; - enum sway_container_layout prev_layout; + enum sway_container_layout prev_split_layout; bool is_sticky; diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ec170591..f4e4dda9 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -42,19 +42,16 @@ struct cmd_results *cmd_layout(int argc, char **argv) { parent = parent->parent; } - if (strcasecmp(argv[0], "default") == 0) { - parent->layout = parent->prev_layout; - } else { - if (parent->layout != L_TABBED && parent->layout != L_STACKED) { - parent->prev_layout = parent->layout; - } - - bool assigned_directly = parse_layout_string(argv[0], &parent->layout); - if (!assigned_directly && strcasecmp(argv[0], "toggle") == 0) { + enum sway_container_layout prev = parent->layout; + bool assigned_directly = parse_layout_string(argv[0], &parent->layout); + if (!assigned_directly) { + if (strcasecmp(argv[0], "default") == 0) { + parent->layout = parent->prev_split_layout; + } else if (strcasecmp(argv[0], "toggle") == 0) { if (argc == 1) { parent->layout = parent->layout == L_STACKED ? L_TABBED : - parent->layout == L_TABBED ? parent->prev_layout : L_STACKED; + parent->layout == L_TABBED ? parent->prev_split_layout : L_STACKED; } else if (argc == 2) { if (strcasecmp(argv[1], "all") == 0) { parent->layout = @@ -62,17 +59,20 @@ struct cmd_results *cmd_layout(int argc, char **argv) { parent->layout == L_VERT ? L_STACKED : parent->layout == L_STACKED ? L_TABBED : L_HORIZ; } else if (strcasecmp(argv[1], "split") == 0) { - parent->layout = parent->layout == L_VERT ? L_HORIZ : L_VERT; + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; } else { return cmd_results_new(CMD_INVALID, "layout", expected_syntax); } } else { - bool valid; enum sway_container_layout parsed_layout; int curr = 1; for (; curr < argc; curr++) { - valid = parse_layout_string(argv[curr], &parsed_layout); - if (valid && parsed_layout == parent->layout) { + bool valid = parse_layout_string(argv[curr], &parsed_layout); + if ((valid && parsed_layout == parent->layout) || + (strcmp(argv[curr], "split") == 0 && + (parent->layout == L_VERT || parent->layout == L_HORIZ))) { break; } } @@ -83,6 +83,11 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } if (parse_layout_string(argv[i], &parent->layout)) { break; + } else if (strcmp(argv[i], "split") == 0) { + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; + break; } // invalid layout strings are silently ignored } } @@ -93,9 +98,13 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (parent->layout == L_NONE) { parent->layout = container_get_default_layout(parent); } - - container_notify_subtree_changed(parent); - arrange_windows(parent); + if (prev != parent->layout) { + if (prev != L_TABBED && prev != L_STACKED) { + parent->prev_split_layout = prev; + } + container_notify_subtree_changed(parent); + arrange_windows(parent); + } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 07de9664..28cdc71e 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -859,7 +859,7 @@ struct sway_container *container_split(struct sway_container *child, } if (child->type == C_WORKSPACE && child->children->length == 0) { // Special case: this just behaves like splitt - child->prev_layout = child->layout; + child->prev_split_layout = child->layout; child->layout = layout; return child; } @@ -870,7 +870,7 @@ struct sway_container *container_split(struct sway_container *child, remove_gaps(child); - cont->prev_layout = L_NONE; + cont->prev_split_layout = L_NONE; cont->width = child->width; cont->height = child->height; cont->x = child->x; diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index cc225e79..250d5ba7 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -59,7 +59,7 @@ struct sway_container *workspace_create(struct sway_container *output, workspace->width = output->width; workspace->height = output->height; workspace->name = !name ? NULL : strdup(name); - workspace->prev_layout = L_NONE; + workspace->prev_split_layout = L_NONE; workspace->layout = container_get_default_layout(output); struct sway_workspace *swayws = calloc(1, sizeof(struct sway_workspace)); From 85ae121caad02265b95ecea66fa864607575eb31 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:05:48 +0100 Subject: [PATCH 07/27] commands: complete workspace implementation Allow optional --no-auto-back-and-forth flag, as well as refactoring some logic --- include/sway/tree/workspace.h | 4 ++- sway/commands/workspace.c | 54 +++++++++++++++-------------------- sway/sway.5.scd | 5 +++- sway/tree/workspace.c | 42 ++++++++++++++++++--------- 4 files changed, 59 insertions(+), 46 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 3337f2c8..239cbbdb 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -1,6 +1,7 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H +#include #include "sway/tree/container.h" struct sway_view; @@ -17,7 +18,8 @@ extern char *prev_workspace_name; char *workspace_next_name(const char *output_name); -bool workspace_switch(struct sway_container *workspace); +bool workspace_switch(struct sway_container *workspace, + bool no_auto_back_and_forth); struct sway_container *workspace_by_number(const char* name); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index e8b37182..f32ede1e 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -17,17 +17,6 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { int output_location = -1; - struct sway_container *current_container = config->handler_context.current_container; - struct sway_container *old_workspace = NULL, *old_output = NULL; - if (current_container) { - if (current_container->type == C_WORKSPACE) { - old_workspace = current_container; - } else { - old_workspace = container_parent(current_container, C_WORKSPACE); - } - old_output = container_parent(current_container, C_OUTPUT); - } - for (int i = 0; i < argc; ++i) { if (strcasecmp(argv[i], "output") == 0) { output_location = i; @@ -57,39 +46,42 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); } + + bool no_auto_back_and_forth = false; + while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if ((error = checkarg(--argc, "workspace", EXPECTED_AT_LEAST, 1))) { + return error; + } + ++argv; + } + + struct sway_container *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { + if (argc < 2) { + cmd_results_new(CMD_INVALID, "workspace", + "Expected workspace number"); + } if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); ws = workspace_create(NULL, name); free(name); } - } else if (strcasecmp(argv[0], "next") == 0) { - ws = workspace_next(old_workspace); - } else if (strcasecmp(argv[0], "prev") == 0) { - ws = workspace_prev(old_workspace); - } else if (strcasecmp(argv[0], "next_on_output") == 0) { - ws = workspace_output_next(old_output); - } else if (strcasecmp(argv[0], "prev_on_output") == 0) { - ws = workspace_output_prev(old_output); - } else if (strcasecmp(argv[0], "back_and_forth") == 0) { - // if auto_back_and_forth is enabled, workspace_switch will swap - // the workspaces. If we created prev_workspace here, workspace_switch - // would put us back on original workspace. - if (config->auto_back_and_forth) { - ws = old_workspace; - } else if (prev_workspace_name - && !(ws = workspace_by_name(prev_workspace_name))) { - ws = workspace_create(NULL, prev_workspace_name); - } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - ws = workspace_create(NULL, name); + if (strcasecmp(argv[0], "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } else { + ws = workspace_create(NULL, name); + } } free(name); } - workspace_switch(ws); + workspace_switch(ws, no_auto_back_and_forth); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 8083106b..36ce13df 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -526,7 +526,7 @@ config after the others, or it will be matched instead of the others. state. Using _allow_ or _deny_ controls the window's ability to set itself as urgent. By default, windows are allowed to set their own urgency. -*workspace* [number] +*workspace* [--no-auto-back-and-forth] [number] Switches to the specified workspace. The string "number" is optional and is used to sort workspaces. @@ -537,6 +537,9 @@ config after the others, or it will be matched instead of the others. *workspace* prev\_on\_output|next\_on\_output Switches to the next workspace on the current output. +*workspace* back_and_forth + Switches to the previously focused workspace. + *workspace* output Specifies that workspace _name_ should be shown on the specified _output_. diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 250d5ba7..5e20429b 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -250,20 +250,35 @@ struct sway_container *workspace_by_name(const char *name) { current_workspace = container_parent(focus, C_WORKSPACE); current_output = container_parent(focus, C_OUTPUT); } - if (strcmp(name, "prev") == 0) { - return workspace_prev(current_workspace); - } else if (strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(current_output); - } else if (strcmp(name, "next") == 0) { - return workspace_next(current_workspace); - } else if (strcmp(name, "next_on_output") == 0) { - return workspace_output_next(current_output); - } else if (strcmp(name, "current") == 0) { - return current_workspace; + + char *name_cpy = strdup(name); + char *first_word = strtok(name_cpy, " "); + if (first_word == NULL) { + first_word = name_cpy; + } + + struct sway_container *ws = NULL; + if (strcmp(first_word, "prev") == 0) { + ws = workspace_prev(current_workspace); + } else if (strcmp(first_word, "prev_on_output") == 0) { + ws = workspace_output_prev(current_output); + } else if (strcmp(first_word, "next") == 0) { + ws = workspace_next(current_workspace); + } else if (strcmp(first_word, "next_on_output") == 0) { + ws = workspace_output_next(current_output); + } else if (strcmp(first_word, "current") == 0) { + ws = current_workspace; + } else if (strcasecmp(first_word, "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = container_find(&root_container, _workspace_by_name, + (void *)prev_workspace_name); + } } else { - return container_find(&root_container, _workspace_by_name, + ws = container_find(&root_container, _workspace_by_name, (void *)name); } + free(name_cpy); + return ws; } /** @@ -364,7 +379,8 @@ struct sway_container *workspace_prev(struct sway_container *current) { return workspace_prev_next_impl(current, false); } -bool workspace_switch(struct sway_container *workspace) { +bool workspace_switch(struct sway_container *workspace, + bool no_auto_back_and_forth) { if (!workspace) { return false; } @@ -379,7 +395,7 @@ bool workspace_switch(struct sway_container *workspace) { active_ws = container_parent(focus, C_WORKSPACE); } - if (config->auto_back_and_forth + if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { struct sway_container *new_ws = workspace_by_name(prev_workspace_name); From dd48c8a579918f34c6a3441068e6f4b7e753e09c Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:16:21 +0100 Subject: [PATCH 08/27] commands: add optional flags to move --- sway/commands/move.c | 97 +++++++++++++++++++++++++++++++------------- sway/sway.5.scd | 19 +++++---- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index b80ce936..d49d6862 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 500 +#include #include #include #include @@ -16,12 +17,11 @@ #include "stringop.h" #include "list.h" -static const char* expected_syntax = +static const char *expected_syntax = "Expected 'move <[px] px>' or " - "'move to workspace ' or " - "'move to output ' or " - "'move to mark ' or " - "'move position mouse'"; + "'move [--no-auto-back-and-forth] [to] workspace ' or " + "'move [--no-auto-back-and-forth] [to] output ' or " + "'move [to] mark '"; static struct sway_container *output_in_direction(const char *direction, struct wlr_output *reference, int ref_lx, int ref_ly) { @@ -53,7 +53,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "move container/window", - EXPECTED_AT_LEAST, 4))) { + EXPECTED_AT_LEAST, 3))) { return error; } @@ -68,26 +68,52 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, "Can only move containers and views."); } + bool no_auto_back_and_forth = false; + while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + ++argv; + } + while (strcasecmp(argv[1], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + argv++; + } + + while (strcasecmp(argv[1], "to") == 0) { + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + argv++; + } + struct sway_container *old_parent = current->parent; struct sway_container *old_ws = container_parent(current, C_WORKSPACE); struct sway_container *destination = NULL; // determine destination - if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "workspace") == 0) { + if (strcasecmp(argv[1], "workspace") == 0) { // move container to workspace x struct sway_container *ws; char *ws_name = NULL; - if (argc == 5 && strcasecmp(argv[3], "number") == 0) { + if (strcasecmp(argv[2], "number") == 0) { // move "container to workspace number x" - ws_name = strdup(argv[4]); + if (argc < 4) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + ws_name = strdup(argv[3]); ws = workspace_by_number(ws_name); } else { - ws_name = join_args(argv + 3, argc - 3); + ws_name = join_args(argv + 2, argc - 2); ws = workspace_by_name(ws_name); } - if (config->auto_back_and_forth && prev_workspace_name) { + if (!no_auto_back_and_forth && config->auto_back_and_forth && + prev_workspace_name) { // auto back and forth move if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { // if target workspace is the current one @@ -98,19 +124,23 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, } if (!ws) { + if (strcasecmp(argv[2], "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } ws = workspace_create(NULL, ws_name); } free(ws_name); destination = seat_get_focus_inactive(config->handler_context.seat, ws); - } else if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "output") == 0) { + } else if (strcasecmp(argv[1], "output") == 0) { struct sway_container *source = container_parent(current, C_OUTPUT); - struct sway_container *dest_output = output_in_direction(argv[3], + struct sway_container *dest_output = output_in_direction(argv[2], source->sway_output->wlr_output, current->x, current->y); if (!dest_output) { return cmd_results_new(CMD_FAILURE, "move workspace", - "Can't find output with name/direction '%s'", argv[3]); + "Can't find output with name/direction '%s'", argv[2]); } destination = seat_get_focus_inactive( config->handler_context.seat, dest_output); @@ -118,12 +148,11 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // We've never been to this output before destination = dest_output->children->items[0]; } - } else if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "mark") == 0) { - struct sway_view *dest_view = view_find_mark(argv[3]); + } else if (strcasecmp(argv[1], "mark") == 0) { + struct sway_view *dest_view = view_find_mark(argv[2]); if (dest_view == NULL) { return cmd_results_new(CMD_FAILURE, "move", - "Mark '%s' not found", argv[3]); + "Mark '%s' not found", argv[2]); } destination = dest_view->swayc; } else { @@ -150,20 +179,29 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, static struct cmd_results *cmd_move_workspace(struct sway_container *current, int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { + if ((error = checkarg(argc, "move workspace", EXPECTED_AT_LEAST, 2))) { return error; - } else if (strcasecmp(argv[1], "to") != 0 - || strcasecmp(argv[2], "output") != 0) { + } + + while (strcasecmp(argv[1], "to") == 0) { + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + ++argv; + } + + if (strcasecmp(argv[1], "output") != 0) { return cmd_results_new(CMD_INVALID, "move", expected_syntax); } + struct sway_container *source = container_parent(current, C_OUTPUT); int center_x = current->width / 2 + current->x, center_y = current->height / 2 + current->y; - struct sway_container *destination = output_in_direction(argv[3], + struct sway_container *destination = output_in_direction(argv[2], source->sway_output->wlr_output, center_x, center_y); if (!destination) { return cmd_results_new(CMD_FAILURE, "move workspace", - "Can't find output with name/direction '%s'", argv[3]); + "Can't find output with name/direction '%s'", argv[2]); } if (current->type != C_WORKSPACE) { current = container_parent(current, C_WORKSPACE); @@ -237,7 +275,7 @@ static struct cmd_results *move_in_direction(struct sway_container *container, return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static const char* expected_position_syntax = +static const char *expected_position_syntax = "Expected 'move [absolute] position [px] [px]' or " "'move [absolute] position center|mouse'"; @@ -356,8 +394,11 @@ struct cmd_results *cmd_move(int argc, char **argv) { return move_in_direction(current, MOVE_UP, argc, argv); } else if (strcasecmp(argv[0], "down") == 0) { return move_in_direction(current, MOVE_DOWN, argc, argv); - } else if (strcasecmp(argv[0], "container") == 0 - || strcasecmp(argv[0], "window") == 0) { + } else if ((strcasecmp(argv[0], "container") == 0 + || strcasecmp(argv[0], "window") == 0) || + (strcasecmp(argv[0], "--no-auto-back-and-forth") && + (strcasecmp(argv[0], "container") == 0 + || strcasecmp(argv[0], "window") == 0))) { return cmd_move_container(current, argc, argv); } else if (strcasecmp(argv[0], "workspace") == 0) { return cmd_move_workspace(current, argc, argv); diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 36ce13df..b43cbe8d 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -135,24 +135,29 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *move* [absolute] position center|mouse Moves the focused container to be centered on the workspace or mouse. -*move* container|window to mark +*move* container|window [to] mark Moves the focused container to the specified mark. -*move* container|window to workspace - Moves the focused container to the specified workspace. +*move* [--no-auto-back-and-forth] container|window [to] workspace [number] + Moves the focused container to the specified workspace. The string "number" + is optional and is used to match a workspace with the same number, even if + it has a different name. -*move* container|window to workspace prev|next|current +*move* container|window [to] workspace prev|next|current Moves the focused container to the previous, next or current workspace on this output, or if no workspaces remain, the previous or next output. -*move* container|window to workspace prev\_on\_output|next\_on\_output +*move* container|window [to] workspace prev\_on\_output|next\_on\_output Moves the focused container to the previous or next workspace on this output, wrapping around if already at the first or last workspace. -*move* container|window|workspace to output +*move* container|window [to] workspace back_and_forth + Moves the focused container to previously focused workspace. + +*move* container|window|workspace [to] output Moves the focused container or workspace to the specified output. -*move* container|window|workspace to output up|right|down|left +*move* container|window|workspace [to] output up|right|down|left Moves the focused container or workspace to next output in the specified direction. From 3b1f58e1353f68ea10a3c5325ba4e04fbbe0c6a7 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:27:53 +0100 Subject: [PATCH 09/27] commands: document focus --- sway/sway.5.scd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index b43cbe8d..73a01152 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -84,6 +84,9 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *floating* enable|disable|toggle Make focused view floating, non-floating, or the opposite of what it is now. + *focus* + Moves focus to the container that matches the specified criteria. + *focus* up|right|down|left Moves focus to the next container in the specified direction. From 667b8dcb67d8c3f15b52f59d228bb3146a5cdb30 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 6 Aug 2018 10:43:09 +0100 Subject: [PATCH 10/27] commands: check for special workspaces in workspace & move commands --- sway/commands/move.c | 60 ++++++++++++++++++++++----------------- sway/commands/workspace.c | 18 +++++++----- sway/tree/workspace.c | 39 +++++++++---------------- 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index d49d6862..500151f7 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -99,40 +99,48 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if (strcasecmp(argv[1], "workspace") == 0) { // move container to workspace x struct sway_container *ws; - char *ws_name = NULL; - if (strcasecmp(argv[2], "number") == 0) { - // move "container to workspace number x" - if (argc < 4) { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); + if (strcasecmp(argv[2], "next") == 0 || + strcasecmp(argv[2], "prev") == 0 || + strcasecmp(argv[2], "next_on_output") == 0 || + strcasecmp(argv[2], "prev_on_output") == 0 || + strcasecmp(argv[2], "back_and_forth") == 0 || + strcasecmp(argv[2], "current") == 0) { + ws = workspace_by_name(argv[2]); + } else if (strcasecmp(argv[2], "back_and_forth") == 0) { + if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); } - ws_name = strdup(argv[3]); - ws = workspace_by_number(ws_name); } else { - ws_name = join_args(argv + 2, argc - 2); - ws = workspace_by_name(ws_name); - } - - if (!no_auto_back_and_forth && config->auto_back_and_forth && - prev_workspace_name) { - // auto back and forth move - if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { - // if target workspace is the current one - free(ws_name); - ws_name = strdup(prev_workspace_name); + char *ws_name = NULL; + if (strcasecmp(argv[2], "number") == 0) { + // move "container to workspace number x" + if (argc < 4) { + return cmd_results_new(CMD_INVALID, "move", + expected_syntax); + } + ws_name = strdup(argv[3]); + ws = workspace_by_number(ws_name); + } else { + ws_name = join_args(argv + 2, argc - 2); ws = workspace_by_name(ws_name); } - } - if (!ws) { - if (strcasecmp(argv[2], "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); + if (!no_auto_back_and_forth && config->auto_back_and_forth && + prev_workspace_name) { + // auto back and forth move + if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { + // if target workspace is the current one + free(ws_name); + ws_name = strdup(prev_workspace_name); + ws = workspace_by_name(ws_name); } } - ws = workspace_create(NULL, ws_name); - } - free(ws_name); + if (!ws) { + 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); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index f32ede1e..f5558bb4 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -68,16 +68,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = workspace_create(NULL, name); free(name); } + } else if (strcasecmp(argv[0], "next") == 0 || + strcasecmp(argv[0], "prev") == 0 || + strcasecmp(argv[0], "next_on_output") == 0 || + strcasecmp(argv[0], "prev_on_output") == 0 || + strcasecmp(argv[0], "current") == 0) { + ws = workspace_by_name(argv[0]); + } else if (strcasecmp(argv[0], "back_and_forth") == 0) { + if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - if (strcasecmp(argv[0], "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); - } - } else { - ws = workspace_create(NULL, name); - } + ws = workspace_create(NULL, name); } free(name); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5e20429b..3fcad631 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -251,34 +251,23 @@ struct sway_container *workspace_by_name(const char *name) { current_output = container_parent(focus, C_OUTPUT); } - char *name_cpy = strdup(name); - char *first_word = strtok(name_cpy, " "); - if (first_word == NULL) { - first_word = name_cpy; - } - - struct sway_container *ws = NULL; - if (strcmp(first_word, "prev") == 0) { - ws = workspace_prev(current_workspace); - } else if (strcmp(first_word, "prev_on_output") == 0) { - ws = workspace_output_prev(current_output); - } else if (strcmp(first_word, "next") == 0) { - ws = workspace_next(current_workspace); - } else if (strcmp(first_word, "next_on_output") == 0) { - ws = workspace_output_next(current_output); - } else if (strcmp(first_word, "current") == 0) { - ws = current_workspace; - } else if (strcasecmp(first_word, "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = container_find(&root_container, _workspace_by_name, - (void *)prev_workspace_name); - } + if (strcmp(name, "prev") == 0) { + return workspace_prev(current_workspace); + } else if (strcmp(name, "prev_on_output") == 0) { + return workspace_output_prev(current_output); + } else if (strcmp(name, "next") == 0) { + return workspace_next(current_workspace); + } else if (strcmp(name, "next_on_output") == 0) { + return workspace_output_next(current_output); + } else if (strcmp(name, "current") == 0) { + return current_workspace; + } else if (strcasecmp(name, "back_and_forth") == 0) { + return prev_workspace_name ? container_find(&root_container, + _workspace_by_name, (void *)prev_workspace_name) : NULL; } else { - ws = container_find(&root_container, _workspace_by_name, + return container_find(&root_container, _workspace_by_name, (void *)name); } - free(name_cpy); - return ws; } /** From f7c21451dfa7c4ffdce1307b5856707a0ed40405 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 6 Aug 2018 12:46:28 +0100 Subject: [PATCH 11/27] commands: fix workspace edge cases --- sway/commands/move.c | 9 +++++++-- sway/commands/rename.c | 10 ++++++++++ sway/tree/view.c | 9 ++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 500151f7..af3dc538 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -107,8 +107,13 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, strcasecmp(argv[2], "current") == 0) { ws = workspace_by_name(argv[2]); } else if (strcasecmp(argv[2], "back_and_forth") == 0) { - if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); + if (!(ws = workspace_by_name(argv[2]))) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } else { + return cmd_results_new(CMD_FAILURE, "move", + "No workspace was previously active."); + } } } else { char *ws_name = NULL; diff --git a/sway/commands/rename.c b/sway/commands/rename.c index a380ff9c..c6952bbb 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -61,6 +61,16 @@ struct cmd_results *cmd_rename(int argc, char **argv) { } char *new_name = join_args(argv + argn, argc - argn); + if (strcasecmp(new_name, "next") == 0 || + strcasecmp(new_name, "prev") == 0 || + strcasecmp(new_name, "next_on_output") == 0 || + strcasecmp(new_name, "prev_on_output") == 0 || + strcasecmp(new_name, "back_and_forth") == 0 || + strcasecmp(new_name, "current") == 0) { + free(new_name); + return cmd_results_new(CMD_INVALID, "rename", + "Cannot use special workspace name '%s'", argv[argn]); + } struct sway_container *tmp_workspace = workspace_by_name(new_name); if (tmp_workspace) { free(new_name); diff --git a/sway/tree/view.c b/sway/tree/view.c index 48bd7ac0..faaa53a1 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -456,7 +457,13 @@ static struct sway_container *select_workspace(struct sway_view *view) { if (criteria->type == CT_ASSIGN_WORKSPACE) { ws = workspace_by_name(criteria->target); if (!ws) { - ws = workspace_create(NULL, criteria->target); + if (strcasecmp(criteria->target, "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } else { + ws = workspace_create(NULL, criteria->target); + } } break; } else { From f57a3919cf5ad7c3edbf9e2e19051971a5f2d42f Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 7 Aug 2018 00:03:01 +1000 Subject: [PATCH 12/27] Move workspace moving code out of container_move_to container_move_to handled moving containers to new parents, as well as moving workspaces to new outputs. This commit removes the workspace-moving code from this function and introduces workspace_move_to_output. Moving workspaces using container_move_to only happened from the move command, so it's been implemented as a static function in that file. Simplifying container_move_to makes it easier for me to fix some issues in #2420. --- sway/commands/move.c | 44 +++++++++++++++++++++++++++++++++++++++++++- sway/tree/layout.c | 28 ++++++---------------------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 841da4c4..1af98e1f 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -8,6 +8,7 @@ #include "sway/commands.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" #include "sway/output.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" @@ -15,6 +16,7 @@ #include "sway/tree/workspace.h" #include "stringop.h" #include "list.h" +#include "log.h" static const char* expected_syntax = "Expected 'move <[px] px>' or " @@ -152,6 +154,46 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, return cmd_results_new(CMD_INVALID, "move", expected_syntax); } +static void workspace_move_to_output(struct sway_container *workspace, + struct sway_container *output) { + if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { + return; + } + if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { + return; + } + if (workspace->parent == output) { + return; + } + struct sway_container *old_output = container_remove_child(workspace); + struct sway_seat *seat = input_manager_get_default_seat(input_manager); + struct sway_container *new_output_focus = + seat_get_focus_inactive(seat, output); + + container_add_child(output, workspace); + wl_signal_emit(&workspace->events.reparent, old_output); + + // If moving the last workspace from the old output, create a new workspace + // on the old output + if (old_output->children->length == 0) { + char *ws_name = workspace_next_name(old_output->name); + struct sway_container *ws = workspace_create(old_output, ws_name); + free(ws_name); + seat_set_focus(seat, ws); + } + + // Try to remove an empty workspace from the destination output. + container_reap_empty_recursive(new_output_focus); + + container_sort_workspaces(output); + seat_set_focus(seat, output); + workspace_output_raise_priority(workspace, old_output, output); + ipc_event_workspace(NULL, workspace, "move"); + + container_notify_subtree_changed(old_output); + container_notify_subtree_changed(output); +} + static struct cmd_results *cmd_move_workspace(struct sway_container *current, int argc, char **argv) { struct cmd_results *error = NULL; @@ -173,7 +215,7 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, if (current->type != C_WORKSPACE) { current = container_parent(current, C_WORKSPACE); } - container_move_to(current, destination); + workspace_move_to_output(current, destination); arrange_windows(source); arrange_windows(destination); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 07de9664..9485e675 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -142,6 +142,10 @@ struct sway_container *container_remove_child(struct sway_container *child) { void container_move_to(struct sway_container *container, struct sway_container *destination) { + if (!sway_assert(container->type == C_CONTAINER || + container->type == C_VIEW, "Expected a container or view")) { + return; + } if (container == destination || container_has_ancestor(container, destination)) { return; @@ -154,11 +158,8 @@ void container_move_to(struct sway_container *container, container->width = container->height = 0; container->saved_width = container->saved_height = 0; - struct sway_container *new_parent, *new_parent_focus; - struct sway_seat *seat = input_manager_get_default_seat(input_manager); + struct sway_container *new_parent; - // Get the focus of the destination before we change it. - new_parent_focus = seat_get_focus_inactive(seat, destination); if (destination->type == C_VIEW) { new_parent = container_add_sibling(destination, container); } else { @@ -167,24 +168,7 @@ void container_move_to(struct sway_container *container, } wl_signal_emit(&container->events.reparent, old_parent); - if (container->type == C_WORKSPACE) { - // If moving a workspace to a new output, maybe create a new workspace - // on the previous output - if (old_parent->children->length == 0) { - char *ws_name = workspace_next_name(old_parent->name); - struct sway_container *ws = workspace_create(old_parent, ws_name); - free(ws_name); - seat_set_focus(seat, ws); - } - - // Try to remove an empty workspace from the destination output. - container_reap_empty_recursive(new_parent_focus); - - container_sort_workspaces(new_parent); - seat_set_focus(seat, new_parent); - workspace_output_raise_priority(container, old_parent, new_parent); - ipc_event_workspace(NULL, container, "move"); - } else if (container->type == C_VIEW) { + if (container->type == C_VIEW) { ipc_event_window(container, "move"); } container_notify_subtree_changed(old_parent); From 700941dde8d270b7986bd592fcb42333e7626718 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 13 Jul 2018 21:53:56 +0100 Subject: [PATCH 13/27] Listen to server-decoration mode changes --- include/sway/decoration.h | 13 +++++++++++++ include/sway/server.h | 10 +++++++++- sway/decoration.c | 41 +++++++++++++++++++++++++++++++++++++++ sway/meson.build | 5 +++-- sway/server.c | 9 ++++++--- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 include/sway/decoration.h create mode 100644 sway/decoration.c diff --git a/include/sway/decoration.h b/include/sway/decoration.h new file mode 100644 index 00000000..c77c04c7 --- /dev/null +++ b/include/sway/decoration.h @@ -0,0 +1,13 @@ +#ifndef _SWAY_DECORATION_H +#define _SWAY_DECORATION_H + +#include + +struct sway_server_decoration { + struct wlr_server_decoration *wlr_server_decoration; + + struct wl_listener destroy; + struct wl_listener mode; +}; + +#endif diff --git a/include/sway/server.h b/include/sway/server.h index a3782f91..7e73fb4f 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -4,12 +4,13 @@ #include #include #include +#include #include #include #include +#include #include #include -#include // TODO WLR: make Xwayland optional #include "list.h" #include "config.h" @@ -42,11 +43,16 @@ struct sway_server { struct wlr_xdg_shell *xdg_shell; struct wl_listener xdg_shell_surface; + #ifdef HAVE_XWAYLAND struct sway_xwayland xwayland; struct wl_listener xwayland_surface; struct wl_listener xwayland_ready; #endif + + struct wlr_server_decoration_manager *server_decoration_manager; + struct wl_listener server_decoration; + bool debug_txn_timings; list_t *transactions; @@ -71,4 +77,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data); #ifdef HAVE_XWAYLAND void handle_xwayland_surface(struct wl_listener *listener, void *data); #endif +void handle_server_decoration(struct wl_listener *listener, void *data); + #endif diff --git a/sway/decoration.c b/sway/decoration.c new file mode 100644 index 00000000..73b3f45d --- /dev/null +++ b/sway/decoration.c @@ -0,0 +1,41 @@ +#include +#include "sway/decoration.h" +#include "sway/server.h" +#include "sway/tree/view.h" +#include "log.h" + +static void server_decoration_handle_destroy(struct wl_listener *listener, + void *data) { + struct sway_server_decoration *deco = + wl_container_of(listener, deco, destroy); + wl_list_remove(&deco->destroy.link); + free(deco); +} + +static void server_decoration_handle_mode(struct wl_listener *listener, + void *data) { + struct sway_server_decoration *deco = + wl_container_of(listener, deco, mode); + struct sway_view *view = + view_from_wlr_surface(deco->wlr_server_decoration->surface); + + // TODO + wlr_log(WLR_ERROR, "%p %d", view, deco->wlr_server_decoration->mode); +} + +void handle_server_decoration(struct wl_listener *listener, void *data) { + struct wlr_server_decoration *wlr_deco = data; + + struct sway_server_decoration *deco = calloc(1, sizeof(*deco)); + if (deco == NULL) { + return; + } + + deco->wlr_server_decoration = wlr_deco; + + wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); + deco->destroy.notify = server_decoration_handle_destroy; + + wl_signal_add(&wlr_deco->events.mode, &deco->mode); + deco->mode.notify = server_decoration_handle_mode; +} diff --git a/sway/meson.build b/sway/meson.build index c18fb6e2..2a457270 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -1,13 +1,14 @@ sway_sources = files( - 'main.c', - 'server.c', 'commands.c', 'config.c', 'criteria.c', 'debug-tree.c', + 'decoration.c', 'ipc-json.c', 'ipc-server.c', + 'main.c', 'security.c', + 'server.c', 'swaynag.c', 'desktop/desktop.c', diff --git a/sway/server.c b/sway/server.c index e8755360..bf6255bc 100644 --- a/sway/server.c +++ b/sway/server.c @@ -109,11 +109,14 @@ bool server_init(struct sway_server *server) { } #endif - // TODO: Integration with sway borders - struct wlr_server_decoration_manager *deco_manager = + server->server_decoration_manager = wlr_server_decoration_manager_create(server->wl_display); wlr_server_decoration_manager_set_default_mode( - deco_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + server->server_decoration_manager, + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + wl_signal_add(&server->server_decoration_manager->events.new_decoration, + &server->server_decoration); + server->server_decoration.notify = handle_server_decoration; wlr_linux_dmabuf_v1_create(server->wl_display, renderer); wlr_export_dmabuf_manager_v1_create(server->wl_display); From 9d578e0a0f08e053dfc1982e32d9fda172b0087f Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 29 Jul 2018 18:31:10 +0100 Subject: [PATCH 14/27] Handle views created after decoration mode is sent for xdg-shell --- include/sway/decoration.h | 4 ++++ include/sway/server.h | 1 + include/sway/tree/view.h | 4 ++++ sway/decoration.c | 34 ++++++++++++++++++++++++++++++++-- sway/desktop/xdg_shell.c | 19 +++++++++++++++++++ sway/server.c | 3 +-- 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/include/sway/decoration.h b/include/sway/decoration.h index c77c04c7..7916746e 100644 --- a/include/sway/decoration.h +++ b/include/sway/decoration.h @@ -5,9 +5,13 @@ struct sway_server_decoration { struct wlr_server_decoration *wlr_server_decoration; + struct wl_list link; struct wl_listener destroy; struct wl_listener mode; }; +struct sway_server_decoration *decoration_from_surface( + struct wlr_surface *surface); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index 7e73fb4f..b93584b6 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -52,6 +52,7 @@ struct sway_server { struct wlr_server_decoration_manager *server_decoration_manager; struct wl_listener server_decoration; + struct wl_list decorations; // sway_server_decoration::link bool debug_txn_timings; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 37fd02bc..e91d2a20 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -118,6 +118,8 @@ struct sway_view { struct sway_xdg_shell_v6_view { struct sway_view view; + enum wlr_server_decoration_manager_mode deco_mode; + struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; @@ -134,6 +136,8 @@ struct sway_xdg_shell_v6_view { struct sway_xdg_shell_view { struct sway_view view; + enum wlr_server_decoration_manager_mode deco_mode; + struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; diff --git a/sway/decoration.c b/sway/decoration.c index 73b3f45d..0e3e67ac 100644 --- a/sway/decoration.c +++ b/sway/decoration.c @@ -9,6 +9,8 @@ static void server_decoration_handle_destroy(struct wl_listener *listener, struct sway_server_decoration *deco = wl_container_of(listener, deco, destroy); wl_list_remove(&deco->destroy.link); + wl_list_remove(&deco->mode.link); + wl_list_remove(&deco->link); free(deco); } @@ -18,9 +20,24 @@ static void server_decoration_handle_mode(struct wl_listener *listener, wl_container_of(listener, deco, mode); struct sway_view *view = view_from_wlr_surface(deco->wlr_server_decoration->surface); + if (view == NULL || view->surface != deco->wlr_server_decoration->surface) { + return; + } - // TODO - wlr_log(WLR_ERROR, "%p %d", view, deco->wlr_server_decoration->mode); + switch (view->type) { + case SWAY_VIEW_XDG_SHELL_V6:; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + (struct sway_xdg_shell_v6_view *)view; + xdg_shell_v6_view->deco_mode = deco->wlr_server_decoration->mode; + break; + case SWAY_VIEW_XDG_SHELL:; + struct sway_xdg_shell_view *xdg_shell_view = + (struct sway_xdg_shell_view *)view; + xdg_shell_view->deco_mode = deco->wlr_server_decoration->mode; + break; + default: + break; + } } void handle_server_decoration(struct wl_listener *listener, void *data) { @@ -38,4 +55,17 @@ void handle_server_decoration(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_deco->events.mode, &deco->mode); deco->mode.notify = server_decoration_handle_mode; + + wl_list_insert(&server.decorations, &deco->link); +} + +struct sway_server_decoration *decoration_from_surface( + struct wlr_surface *surface) { + struct sway_server_decoration *deco; + wl_list_for_each(deco, &server.decorations, link) { + if (deco->wlr_server_decoration->surface == surface) { + return deco; + } + } + return NULL; } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b364663d..3b73f99c 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -6,6 +6,7 @@ #include #include #include "log.h" +#include "sway/decoration.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/server.h" @@ -170,6 +171,15 @@ static bool wants_floating(struct sway_view *view) { || toplevel->parent; } +static bool has_client_side_decorations(struct sway_view *view) { + struct sway_xdg_shell_view *xdg_shell_view = + xdg_shell_view_from_view(view); + if (xdg_shell_view == NULL) { + return true; + } + return xdg_shell_view->deco_mode != WLR_SERVER_DECORATION_MANAGER_MODE_SERVER; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_view_from_view(view) == NULL) { @@ -226,6 +236,7 @@ static const struct sway_view_impl view_impl = { .set_tiled = set_tiled, .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, + .has_client_side_decorations = has_client_side_decorations, .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, @@ -357,6 +368,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_height = view->wlr_xdg_surface->surface->current.height; } + struct sway_server_decoration *deco = + decoration_from_surface(xdg_surface->surface); + if (deco != NULL) { + xdg_shell_view->deco_mode = deco->wlr_server_decoration->mode; + } else { + xdg_shell_view->deco_mode = WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + } + view_map(view, view->wlr_xdg_surface->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { diff --git a/sway/server.c b/sway/server.c index bf6255bc..e8dc63be 100644 --- a/sway/server.c +++ b/sway/server.c @@ -19,7 +19,6 @@ #include #include #include -// TODO WLR: make Xwayland optional #include "list.h" #include "sway/config.h" #include "sway/desktop/idle_inhibit_v1.h" @@ -85,7 +84,6 @@ bool server_init(struct sway_server *server) { &server->xdg_shell_surface); server->xdg_shell_surface.notify = handle_xdg_shell_surface; - // TODO make xwayland optional #ifdef HAVE_XWAYLAND server->xwayland.wlr_xwayland = wlr_xwayland_create(server->wl_display, server->compositor, true); @@ -117,6 +115,7 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->server_decoration_manager->events.new_decoration, &server->server_decoration); server->server_decoration.notify = handle_server_decoration; + wl_list_init(&server->decorations); wlr_linux_dmabuf_v1_create(server->wl_display, renderer); wlr_export_dmabuf_manager_v1_create(server->wl_display); From d2ac48f9206e9962ab47f337f824ce7f69ffb9c1 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 6 Aug 2018 15:28:33 +0100 Subject: [PATCH 15/27] Handle views created after decoration mode is sent for xdg-shell-v6 --- sway/desktop/xdg_shell_v6.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ffea03ad..a947fb35 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -4,14 +4,15 @@ #include #include #include +#include "log.h" +#include "sway/decoration.h" +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/server.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" -#include "sway/input/seat.h" -#include "sway/input/input-manager.h" -#include "log.h" static const struct sway_view_child_impl popup_impl; @@ -166,6 +167,15 @@ static bool wants_floating(struct sway_view *view) { || toplevel->parent; } +static bool has_client_side_decorations(struct sway_view *view) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { + return true; + } + return xdg_shell_v6_view->deco_mode != WLR_SERVER_DECORATION_MANAGER_MODE_SERVER; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_v6_view_from_view(view) == NULL) { @@ -223,6 +233,7 @@ static const struct sway_view_impl view_impl = { .set_tiled = set_tiled, .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, + .has_client_side_decorations = has_client_side_decorations, .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, @@ -353,6 +364,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_height = view->wlr_xdg_surface_v6->surface->current.height; } + struct sway_server_decoration *deco = + decoration_from_surface(xdg_surface->surface); + if (deco != NULL) { + xdg_shell_v6_view->deco_mode = deco->wlr_server_decoration->mode; + } else { + xdg_shell_v6_view->deco_mode = WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + } + view_map(view, view->wlr_xdg_surface_v6->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { From baf4604629f2e54219af1b103c58e210ce3d0952 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 6 Aug 2018 13:58:12 +0100 Subject: [PATCH 16/27] ipc-client: fix memory leaks in get_socketpath --- common/ipc-client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/ipc-client.c b/common/ipc-client.c index 4d2d88cc..24a2f9c2 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -25,6 +25,7 @@ char *get_socketpath(void) { if (line && *line) { return line; } + free(line); } const char *i3sock = getenv("I3SOCK"); if (i3sock) { @@ -37,6 +38,7 @@ char *get_socketpath(void) { if (line && *line) { return line; } + free(line); } return NULL; } From 5ac6f2f4290e609897faa322997fc7516e7dfb63 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 7 Aug 2018 23:04:21 +1000 Subject: [PATCH 17/27] Fix crash when running `move container to workspace back_and_forth` The back_and_forth condition is intended to be handled in the else-if block, but this was never reached because it remained in the first block's conditions. --- sway/commands/move.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index bb4a7124..95dcb088 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -105,7 +105,6 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, strcasecmp(argv[2], "prev") == 0 || strcasecmp(argv[2], "next_on_output") == 0 || strcasecmp(argv[2], "prev_on_output") == 0 || - strcasecmp(argv[2], "back_and_forth") == 0 || strcasecmp(argv[2], "current") == 0) { ws = workspace_by_name(argv[2]); } else if (strcasecmp(argv[2], "back_and_forth") == 0) { From 50f3a7ff5cf2f30b6644dc578723b60ab3f0d26d Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 7 Aug 2018 23:27:56 +1000 Subject: [PATCH 18/27] Fix infinite loop when focusing sticky containers via workspace command In a multi-output setup, if a sticky container is on one output and focus is on the other output, and you run (eg) `workspace 1` to focus the workspace containing the sticky container, an infinite loop would occur. It would loop infinitely because it would remove the sticky container from the workspace, add it back to the same workspace, and then decrement the iterator variable. The fix just wraps the loop in a workspace comparison. --- sway/tree/workspace.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 3fcad631..395c6c10 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -411,17 +411,20 @@ bool workspace_switch(struct sway_container *workspace, struct sway_container *floating = next_output_prev_ws->sway_workspace->floating; bool has_sticky = false; - for (int i = 0; i < floating->children->length; ++i) { - struct sway_container *floater = floating->children->items[i]; - if (floater->is_sticky) { - has_sticky = true; - container_remove_child(floater); - container_add_child(workspace->sway_workspace->floating, floater); - if (floater == focus) { - seat_set_focus(seat, NULL); - seat_set_focus(seat, floater); + if (workspace != next_output_prev_ws) { + for (int i = 0; i < floating->children->length; ++i) { + struct sway_container *floater = floating->children->items[i]; + if (floater->is_sticky) { + has_sticky = true; + container_remove_child(floater); + container_add_child(workspace->sway_workspace->floating, + floater); + if (floater == focus) { + seat_set_focus(seat, NULL); + seat_set_focus(seat, floater); + } + --i; } - --i; } } From 36281609ea882d4c0a2a10fc9e604eb1ec2e8951 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 4 Aug 2018 14:46:27 +1000 Subject: [PATCH 19/27] Implement move to workspace on a floating container Also adjusts container_floating_translate to not change the current properties directly. --- include/sway/tree/container.h | 8 ++++++ sway/tree/container.c | 51 ++++++++++++++++++++++++++++++----- sway/tree/layout.c | 2 +- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 16a180f8..d82db89c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -328,6 +328,14 @@ void container_floating_translate(struct sway_container *con, void container_floating_move_to(struct sway_container *con, double lx, double ly); +/** + * Move a floating container to the center of the workspace. + */ +void container_floating_move_to_center(struct sway_container *con); + +void container_floating_move_to_container(struct sway_container *container, + struct sway_container *destination); + /** * Mark a container as dirty if it isn't already. Dirty containers will be * included in the next transaction then unmarked as dirty. diff --git a/sway/tree/container.c b/sway/tree/container.c index 6da5ac3c..f31c152f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1163,19 +1163,16 @@ void container_floating_translate(struct sway_container *con, double x_amount, double y_amount) { con->x += x_amount; con->y += y_amount; - con->current.swayc_x += x_amount; - con->current.swayc_y += y_amount; if (con->type == C_VIEW) { con->sway_view->x += x_amount; con->sway_view->y += y_amount; - con->current.view_x += x_amount; - con->current.view_y += y_amount; } else { for (int i = 0; i < con->children->length; ++i) { struct sway_container *child = con->children->items[i]; container_floating_translate(child, x_amount, y_amount); } } + container_set_dirty(con); } /** @@ -1219,9 +1216,7 @@ void container_floating_move_to(struct sway_container *con, "Expected a floating container")) { return; } - desktop_damage_whole_container(con); container_floating_translate(con, lx - con->x, ly - con->y); - desktop_damage_whole_container(con); struct sway_container *old_workspace = container_parent(con, C_WORKSPACE); struct sway_container *new_output = container_floating_find_output(con); if (!sway_assert(new_output, "Unable to find any output")) { @@ -1239,6 +1234,50 @@ void container_floating_move_to(struct sway_container *con, } } +void container_floating_move_to_center(struct sway_container *con) { + if (!sway_assert(container_is_floating(con), + "Expected a floating container")) { + return; + } + struct sway_container *ws = container_parent(con, C_WORKSPACE); + double new_lx = ws->x + (ws->width - con->width) / 2; + double new_ly = ws->y + (ws->height - con->height) / 2; + container_floating_translate(con, new_lx - con->x, new_ly - con->y); +} + +void container_floating_move_to_container(struct sway_container *container, + struct sway_container *destination) { + // Resolve destination into a workspace + struct sway_container *new_ws = NULL; + if (destination->type == C_OUTPUT) { + new_ws = output_get_active_workspace(destination->sway_output); + } else if (destination->type == C_WORKSPACE) { + new_ws = destination; + } else { + new_ws = container_parent(destination, C_WORKSPACE); + } + if (!new_ws) { + // This can happen if the user has run "move container to mark foo", + // where mark foo is on a hidden scratchpad container. + return; + } + struct sway_container *old_ws = container_parent(container, C_WORKSPACE); + if (old_ws != new_ws) { + container_remove_child(container); + container_add_child(new_ws->sway_workspace->floating, container); + arrange_windows(old_ws); + arrange_windows(new_ws); + workspace_detect_urgent(old_ws); + workspace_detect_urgent(new_ws); + } + // If the container's center doesn't overlap the new workspace, center it + // within the workspace. + struct sway_container *output = container_floating_find_output(container); + if (new_ws->parent != output) { + container_floating_move_to_center(container); + } +} + void container_set_dirty(struct sway_container *container) { if (container->dirty) { return; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 20815654..bdcd1a9b 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -151,7 +151,7 @@ void container_move_to(struct sway_container *container, return; } if (container_is_floating(container)) { - // TODO + container_floating_move_to_container(container, destination); return; } struct sway_container *old_parent = container_remove_child(container); From a0649190deaaf093112e99881c25ff550f07e96b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 7 Aug 2018 09:30:27 +1000 Subject: [PATCH 20/27] Fix edge cases when moving floating container to new workspace * Removes container_floating_move_to_container, instead opting to put that logic in container_move_to * In the seat code, focusing a floating view now updates the pending state only and lets the next transaction carry it over to the current state. This is required, otherwise it would crash. * When unfullscreening a floating container, an output check is now done to see if it should center it. --- include/sway/tree/container.h | 9 ++++--- sway/input/seat.c | 4 --- sway/tree/container.c | 40 +++++------------------------ sway/tree/layout.c | 48 +++++++++++++++++++++++++---------- 4 files changed, 47 insertions(+), 54 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d82db89c..4d0e6003 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -322,6 +322,12 @@ void container_get_box(struct sway_container *container, struct wlr_box *box); void container_floating_translate(struct sway_container *con, double x_amount, double y_amount); +/** + * Choose an output for the floating container's new position. + */ +struct sway_container *container_floating_find_output( + struct sway_container *con); + /** * Move a floating container to a new layout-local position. */ @@ -333,9 +339,6 @@ void container_floating_move_to(struct sway_container *con, */ void container_floating_move_to_center(struct sway_container *con); -void container_floating_move_to_container(struct sway_container *container, - struct sway_container *destination); - /** * Mark a container as dirty if it isn't already. Dirty containers will be * included in the next transaction then unmarked as dirty. 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, // If we've focused a floating container, bring it to the front. // We do this by putting it at the end of the floating list. - // This must happen for both the pending and current children lists. if (container && container_is_floating(container)) { list_move_to_end(container->parent->children, container); - if (container_has_ancestor(container, container->current.parent)) { - list_move_to_end(container->parent->current.children, container); - } } // clean up unfocused empty workspace on new output diff --git a/sway/tree/container.c b/sway/tree/container.c index f31c152f..4507655e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1182,7 +1182,7 @@ void container_floating_translate(struct sway_container *con, * one, otherwise we'll choose whichever output is closest to the container's * center. */ -static struct sway_container *container_floating_find_output( +struct sway_container *container_floating_find_output( struct sway_container *con) { double center_x = con->x + con->width / 2; double center_y = con->y + con->height / 2; @@ -1245,39 +1245,6 @@ void container_floating_move_to_center(struct sway_container *con) { container_floating_translate(con, new_lx - con->x, new_ly - con->y); } -void container_floating_move_to_container(struct sway_container *container, - struct sway_container *destination) { - // Resolve destination into a workspace - struct sway_container *new_ws = NULL; - if (destination->type == C_OUTPUT) { - new_ws = output_get_active_workspace(destination->sway_output); - } else if (destination->type == C_WORKSPACE) { - new_ws = destination; - } else { - new_ws = container_parent(destination, C_WORKSPACE); - } - if (!new_ws) { - // This can happen if the user has run "move container to mark foo", - // where mark foo is on a hidden scratchpad container. - return; - } - struct sway_container *old_ws = container_parent(container, C_WORKSPACE); - if (old_ws != new_ws) { - container_remove_child(container); - container_add_child(new_ws->sway_workspace->floating, container); - arrange_windows(old_ws); - arrange_windows(new_ws); - workspace_detect_urgent(old_ws); - workspace_detect_urgent(new_ws); - } - // If the container's center doesn't overlap the new workspace, center it - // within the workspace. - struct sway_container *output = container_floating_find_output(container); - if (new_ws->parent != output) { - container_floating_move_to_center(container); - } -} - void container_set_dirty(struct sway_container *container) { if (container->dirty) { return; @@ -1357,6 +1324,11 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { container->y = container->saved_y; container->width = container->saved_width; container->height = container->saved_height; + struct sway_container *output = + container_floating_find_output(container); + if (!container_has_ancestor(container, output)) { + container_floating_move_to_center(container); + } } else { container->width = container->saved_width; container->height = container->saved_height; diff --git a/sway/tree/layout.c b/sway/tree/layout.c index bdcd1a9b..38e14d00 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -150,22 +150,44 @@ void container_move_to(struct sway_container *container, || container_has_ancestor(container, destination)) { return; } + struct sway_container *old_parent = NULL; + struct sway_container *new_parent = NULL; if (container_is_floating(container)) { - container_floating_move_to_container(container, destination); - return; - } - struct sway_container *old_parent = container_remove_child(container); - container->width = container->height = 0; - container->saved_width = container->saved_height = 0; - - struct sway_container *new_parent; - - if (destination->type == C_VIEW) { - new_parent = container_add_sibling(destination, container); + // Resolve destination into a workspace + struct sway_container *new_ws = NULL; + if (destination->type == C_OUTPUT) { + new_ws = output_get_active_workspace(destination->sway_output); + } else if (destination->type == C_WORKSPACE) { + new_ws = destination; + } else { + new_ws = container_parent(destination, C_WORKSPACE); + } + if (!new_ws) { + // This can happen if the user has run "move container to mark foo", + // where mark foo is on a hidden scratchpad container. + return; + } + struct sway_container *old_output = + container_parent(container, C_OUTPUT); + old_parent = container_remove_child(container); + container_add_child(new_ws->sway_workspace->floating, container); + // If changing output, center it within the workspace + if (old_output != new_ws->parent && !container->is_fullscreen) { + container_floating_move_to_center(container); + } } else { - new_parent = destination; - container_add_child(destination, container); + old_parent = container_remove_child(container); + container->width = container->height = 0; + container->saved_width = container->saved_height = 0; + + if (destination->type == C_VIEW) { + new_parent = container_add_sibling(destination, container); + } else { + new_parent = destination; + container_add_child(destination, container); + } } + wl_signal_emit(&container->events.reparent, old_parent); if (container->type == C_VIEW) { From 5653fc754b09ae5344f42f9e3df71cd4420b7d61 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 10:04:11 +1000 Subject: [PATCH 21/27] 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); From 1e984fec05c7b63fa65a9b11b77a2c2f639bfc73 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 21:45:58 +1000 Subject: [PATCH 22/27] Fix focus when clicking floating decorations It's not right for container_at_view to only return the swayc if a surface was clicked. --- sway/tree/container.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 4507655e..39df86a5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -567,9 +567,8 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sx = _sx; *sy = _sy; *surface = _surface; - return swayc; } - return NULL; + return swayc; } /** From a0ece6f95620674514da633584ebdadabf5b4072 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 22:14:11 +1000 Subject: [PATCH 23/27] Rename container_at_view to surface_at_view and make it return void --- sway/tree/container.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 39df86a5..aecb2ac6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -533,11 +533,10 @@ struct sway_container *container_parent(struct sway_container *container, return container; } -static struct sway_container *container_at_view(struct sway_container *swayc, - double lx, double ly, +static void surface_at_view(struct sway_container *swayc, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) { - return NULL; + return; } struct sway_view *sview = swayc->sway_view; double view_sx = lx - sview->x; @@ -568,7 +567,6 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sy = _sy; *surface = _surface; } - return swayc; } /** @@ -681,7 +679,8 @@ struct sway_container *tiling_container_at( struct sway_container *con, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { if (con->type == C_VIEW) { - return container_at_view(con, lx, ly, surface, sx, sy); + surface_at_view(con, lx, ly, surface, sx, sy); + return con; } if (!con->children->length) { return NULL; @@ -744,7 +743,7 @@ struct sway_container *container_at(struct sway_container *workspace, struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); if (focus && focus->type == C_VIEW) { - container_at_view(focus, lx, ly, surface, sx, sy); + surface_at_view(focus, lx, ly, surface, sx, sy); if (*surface && surface_is_popup(*surface)) { return focus; } From 4c5dc6f135ce1b46ecffb6440b0b106df0a3e18d Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 22:27:21 +1000 Subject: [PATCH 24/27] Focus floating views when beginning move/resize operations --- sway/input/cursor.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 80b4f9dc..39874b73 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -429,6 +429,9 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, struct sway_container *cont) { struct sway_seat *seat = cursor->seat; + seat_set_focus(seat, cont); + seat_pointer_notify_button(seat, time_msec, button, state); + // Deny moving or resizing a fullscreen container if (container_is_fullscreen_or_child(cont)) { seat_pointer_notify_button(seat, time_msec, button, state); @@ -468,10 +471,6 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, seat_begin_resize(seat, floater, button, edge); return; } - - // Send event to surface - seat_set_focus(seat, cont); - seat_pointer_notify_button(seat, time_msec, button, state); } /** From f5dc3ac09d6f44d51b5bb7f8f5ac863cd228afd8 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 22:32:59 +1000 Subject: [PATCH 25/27] Don't call send_pointer_notify_button when doing move or resize --- sway/input/cursor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 39874b73..3f417e96 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -430,7 +430,6 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, struct sway_seat *seat = cursor->seat; seat_set_focus(seat, cont); - seat_pointer_notify_button(seat, time_msec, button, state); // Deny moving or resizing a fullscreen container if (container_is_fullscreen_or_child(cont)) { @@ -471,6 +470,8 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, seat_begin_resize(seat, floater, button, edge); return; } + + seat_pointer_notify_button(seat, time_msec, button, state); } /** From 1c7a6a49b696fc0890016ea70ebb4b8984758b10 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 8 Aug 2018 11:40:33 -0400 Subject: [PATCH 26/27] Remove setcap instructions These are obsolete, we don't require them anymore. --- README.de.md | 4 ---- README.el.md | 4 ---- README.fr.md | 4 ---- README.it.md | 4 ---- README.ja.md | 6 ++---- README.md | 6 ++---- 6 files changed, 4 insertions(+), 24 deletions(-) diff --git a/README.de.md b/README.de.md index a872e888..9d8a41ce 100644 --- a/README.de.md +++ b/README.de.md @@ -76,10 +76,6 @@ Führe diese Befehle aus: ninja -C build sudo ninja -C build install -In Systemen mit logind musst du `sway` einige Capabilities geben: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - In Systemen ohne logind musst du `sway` das suid-Flag geben: sudo chmod a+s /usr/local/bin/sway diff --git a/README.el.md b/README.el.md index 6887fe8e..53fdd2d9 100644 --- a/README.el.md +++ b/README.el.md @@ -69,10 +69,6 @@ _\*\*Απαιτείται μόνο για swaylock_ ninja -C build sudo ninja -C build install -Σε συστήματα με logind, χρειάζεται να ορίσετε μερικά δικαιώματα caps στο εκτελέσιμο αρχείο: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - Σε συστήματα χωρίς logind, χρειάζεται να θέσετε το suid bit στο εκτελέσιμο αρχείο: sudo chmod a+s /usr/local/bin/sway diff --git a/README.fr.md b/README.fr.md index 6ea4d14c..0a9697b8 100644 --- a/README.fr.md +++ b/README.fr.md @@ -71,10 +71,6 @@ Exécutez ces commandes : ninja -C build sudo ninja -C build install -Sur les systèmes avec logind, vous devez définir quelques caps sur le binaire : - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - Sur les systèmes sans logind, vous devez suid le binaire de sway : sudo chmod a+s /usr/local/bin/sway diff --git a/README.it.md b/README.it.md index 3b1b1ebc..653e6aea 100644 --- a/README.it.md +++ b/README.it.md @@ -72,10 +72,6 @@ Esegui questi comandi: ninja -C build sudo ninja -C build install -Per i sistemi con logind, devi impostare un paio di caps sull'eseguibile: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - Per i sistemi senza logind, devi cambiare i permessi (suid): sudo chmod a+s /usr/local/bin/sway diff --git a/README.ja.md b/README.ja.md index 7b437966..a73ffa25 100644 --- a/README.ja.md +++ b/README.ja.md @@ -62,14 +62,12 @@ _\*\*swaylockでのみ必要です_ ninja -C build sudo ninja -C build install -logindを使用しているシステムでは、バイナリにいくつかのケーパビリティを設定する必要があります: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - logindを使用していないシステムでは、バイナリにsuidを設定する必要があります: sudo chmod a+s /usr/local/bin/sway +swayは始まるのすぐにrootの許可を落としてます。 + ## 設定 既にi3を使用している場合は、i3の設定ファイルを`~/.config/sway/config`にコピーすれば動きます。そうでない場合は、サンプルの設定ファイルを`~/.config/sway/config`にコピーしてください。サンプルの設定ファイルは、通常`/etc/sway/config`にあります。`man 5 sway`を実行することで、設定に関する情報を見ることができます。 diff --git a/README.md b/README.md index ce753265..0bad8343 100644 --- a/README.md +++ b/README.md @@ -72,14 +72,12 @@ Run these commands: ninja -C build sudo ninja -C build install -On systems with logind, you need to set a few caps on the binary: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - On systems without logind, you need to suid the sway binary: sudo chmod a+s /usr/local/bin/sway +Sway will drop root permissions shortly after startup. + ## Configuration If you already use i3, then copy your i3 config to `~/.config/sway/config` and From e28101e6e1ed757fe8a7402c5123ee7e58546895 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 8 Aug 2018 11:53:11 -0400 Subject: [PATCH 27/27] =?UTF-8?q?=E7=A7=81=E3=81=AE=E6=97=A5=E6=9C=AC?= =?UTF-8?q?=E8=AA=9E=E3=81=8C=E4=B8=8A=E6=89=8B=E3=81=98=E3=82=83=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=81=A7=E3=81=99=E3=81=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.ja.md b/README.ja.md index a73ffa25..75d29c73 100644 --- a/README.ja.md +++ b/README.ja.md @@ -66,7 +66,7 @@ logindを使用していないシステムでは、バイナリにsuidを設定 sudo chmod a+s /usr/local/bin/sway -swayは始まるのすぐにrootの許可を落としてます。 +swayは起動後、すぐにroot許可を落とします。 ## 設定