From 69e1a421fc2ccecd93f79c9dd0537671138bb0a9 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Tue, 31 Jul 2018 11:38:34 +0100 Subject: commands: complete move implementation --- include/sway/tree/view.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') 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. -- cgit v1.2.3 From 356063b6c084a7c2d4e3e654fe48ec79a102294b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 1 Aug 2018 16:03:37 +0100 Subject: 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(-) (limited to 'include') 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)); -- cgit v1.2.3 From 85ae121caad02265b95ecea66fa864607575eb31 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:05:48 +0100 Subject: 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(-) (limited to 'include') 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); -- cgit v1.2.3 From 700941dde8d270b7986bd592fcb42333e7626718 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 13 Jul 2018 21:53:56 +0100 Subject: 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 (limited to 'include') 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); -- cgit v1.2.3 From 9d578e0a0f08e053dfc1982e32d9fda172b0087f Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 29 Jul 2018 18:31:10 +0100 Subject: 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(-) (limited to 'include') 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); -- cgit v1.2.3 From 36281609ea882d4c0a2a10fc9e604eb1ec2e8951 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 4 Aug 2018 14:46:27 +1000 Subject: 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(-) (limited to 'include') 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); -- cgit v1.2.3 From a0649190deaaf093112e99881c25ff550f07e96b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 7 Aug 2018 09:30:27 +1000 Subject: 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(-) (limited to 'include') 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) { -- cgit v1.2.3 From 5653fc754b09ae5344f42f9e3df71cd4420b7d61 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 8 Aug 2018 10:04:11 +1000 Subject: 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 | 38 +++++++++++++++++++++++++++++++------- sway/tree/workspace.c | 4 ++-- 3 files changed, 35 insertions(+), 9 deletions(-) (limited to 'include') 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); + } + 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"); + } } - free(ws_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], "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); -- cgit v1.2.3