From f2d29ceb6b831a07ce2bce4534fe6fec1f16eee3 Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sun, 26 Mar 2023 17:44:21 +0200 Subject: [PATCH] Extend minimize logic to work with XWayland and XDG applications (#132) * Extend minimize logic * Removed redundant xwayland minimize logic * minor fixes * Fixed not properly checking if window is ran though XWayland * Added config option with default being off * Set scratchpad_minimize to true by default * Improve config dependant logic * Switch to using enable|disable instead of on|off --- README.md | 1 + config.in | 3 +++ include/sway/commands.h | 1 + include/sway/config.h | 1 + include/sway/tree/view.h | 1 + sway/commands.c | 1 + sway/commands/scratchpad_minimize.c | 18 ++++++++++++++++++ sway/config.c | 1 + sway/desktop/xdg_shell.c | 27 +++++++++++++++++++++++++++ sway/desktop/xwayland.c | 22 ++++++++++++++++++++++ sway/meson.build | 1 + sway/sway.5.scd | 4 ++++ sway/tree/root.c | 26 ++++++++++++++++++++++++++ sway/tree/view.c | 11 ++++++++--- 14 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 sway/commands/scratchpad_minimize.c diff --git a/README.md b/README.md index 1ac57fda..e2bf891d 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Sway is an incredible window manager, and certainly one of the most well establi - `dim_inactive_colors.urgent ex, #900000FF` + Application saturation: `for_window [CRITERIA HERE] saturation 2.0>` + Keep/remove separator border between titlebar and content: `titlebar_separator enable|disable` ++ Treat Scratchpad as minimized: `scratchpad_minimize enable|disable` ## Roadmap diff --git a/config.in b/config.in index dc451f23..8053f03a 100644 --- a/config.in +++ b/config.in @@ -34,6 +34,9 @@ dim_inactive 0.0 dim_inactive_colors.unfocused #000000FF dim_inactive_colors.urgent #900000FF +# Move minimized windows into Scratchpad (enable|disable) +scratchpad_minimize enable + ### Output configuration # # Default wallpaper (more resolutions are available in @datadir@/backgrounds/sway/) diff --git a/include/sway/commands.h b/include/sway/commands.h index 84d44e27..91b1fc58 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -176,6 +176,7 @@ sway_cmd cmd_reload; sway_cmd cmd_rename; sway_cmd cmd_resize; sway_cmd cmd_scratchpad; +sway_cmd cmd_scratchpad_minimize; sway_cmd cmd_seamless_mouse; sway_cmd cmd_set; sway_cmd cmd_shortcuts_inhibitor; diff --git a/include/sway/config.h b/include/sway/config.h index 60c810e1..2dc4b52d 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -488,6 +488,7 @@ struct sway_config { int shadow_blur_sigma; float shadow_color[4]; bool titlebar_separator; + bool scratchpad_minimize; char *swaynag_command; struct swaynag_instance swaynag_config_errors; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 684d13a0..9d468612 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -134,6 +134,7 @@ struct sway_xdg_shell_view { struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; + struct wl_listener request_minimize; struct wl_listener request_fullscreen; struct wl_listener set_title; struct wl_listener set_app_id; diff --git a/sway/commands.c b/sway/commands.c index b8b98e99..fbe17039 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -115,6 +115,7 @@ static const struct cmd_handler handlers[] = { static const struct cmd_handler config_handlers[] = { { "default_orientation", cmd_default_orientation }, { "include", cmd_include }, + { "scratchpad_minimize", cmd_scratchpad_minimize }, { "swaybg_command", cmd_swaybg_command }, { "swaynag_command", cmd_swaynag_command }, { "workspace_layout", cmd_workspace_layout }, diff --git a/sway/commands/scratchpad_minimize.c b/sway/commands/scratchpad_minimize.c new file mode 100644 index 00000000..1245e1d5 --- /dev/null +++ b/sway/commands/scratchpad_minimize.c @@ -0,0 +1,18 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "log.h" +#include "stringop.h" +#include "util.h" + +struct cmd_results *cmd_scratchpad_minimize(int argc, char **argv) { + struct cmd_results *error = checkarg(argc, "scratchpad_minimize", EXPECTED_AT_LEAST, 1); + + if (error) { + return error; + } + + config->scratchpad_minimize = parse_boolean(argv[0], config->scratchpad_minimize); + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config.c b/sway/config.c index d1949a3a..24022762 100644 --- a/sway/config.c +++ b/sway/config.c @@ -344,6 +344,7 @@ static void config_defaults(struct sway_config *config) { config->shadow_blur_sigma = 20.0f; color_to_rgba(config->shadow_color, 0x0000007F); config->titlebar_separator = true; + config->scratchpad_minimize = true; // The keysym to keycode translation struct xkb_rule_names rules = {0}; diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 8da922d5..2d79727d 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -332,6 +332,24 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) { wlr_xdg_surface_schedule_configure(toplevel->base); } +/* Minimize to scratchpad */ +static void handle_request_minimize(struct wl_listener *listener, void *data) { + struct sway_xdg_shell_view *xdg_shell_view = + wl_container_of(listener, xdg_shell_view, request_minimize); + struct sway_container *container = xdg_shell_view->view.container; + if (!container->pending.workspace) { + while (container->pending.parent) { + container = container->pending.parent; + } + } + if (!container->scratchpad) { + root_scratchpad_add_container(container, NULL); + } else if (container->pending.workspace) { + root_scratchpad_hide(container); + } + transaction_commit_dirty(); +} + static void handle_request_fullscreen(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_fullscreen); @@ -406,6 +424,9 @@ static void handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&xdg_shell_view->commit.link); wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_maximize.link); + if (xdg_shell_view->request_minimize.notify) { + wl_list_remove(&xdg_shell_view->request_minimize.link); + } wl_list_remove(&xdg_shell_view->request_fullscreen.link); wl_list_remove(&xdg_shell_view->request_move.link); wl_list_remove(&xdg_shell_view->request_resize.link); @@ -458,6 +479,12 @@ static void handle_map(struct wl_listener *listener, void *data) { wl_signal_add(&toplevel->events.request_maximize, &xdg_shell_view->request_maximize); + if (config->scratchpad_minimize) { + xdg_shell_view->request_minimize.notify = handle_request_minimize; + wl_signal_add(&toplevel->events.request_minimize, + &xdg_shell_view->request_minimize); + } + xdg_shell_view->request_fullscreen.notify = handle_request_fullscreen; wl_signal_add(&toplevel->events.request_fullscreen, &xdg_shell_view->request_fullscreen); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e15a3341..55a14c0b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -575,6 +575,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) transaction_commit_dirty(); } +/* Minimize to scratchpad */ static void handle_request_minimize(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, request_minimize); @@ -585,6 +586,27 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) { } struct wlr_xwayland_minimize_event *e = data; + if (config->scratchpad_minimize) { + struct sway_container *container = view->container; + if (!container->pending.workspace) { + while (container->pending.parent) { + container = container->pending.parent; + } + } + if(e->minimize) { + if (!container->scratchpad) { + root_scratchpad_add_container(container, NULL); + } else if (container->pending.workspace) { + root_scratchpad_hide(container); + } + } else { + if(container->scratchpad) { + root_scratchpad_show(container); + } + } + transaction_commit_dirty(); + return; + } struct sway_seat *seat = input_manager_current_seat(); bool focused = seat_get_focus(seat) == &view->container->node; wlr_xwayland_surface_set_minimized(xsurface, !focused && e->minimize); diff --git a/sway/meson.build b/sway/meson.build index d1b47271..b6f63c16 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -98,6 +98,7 @@ sway_sources = files( 'commands/resize.c', 'commands/saturation.c', 'commands/scratchpad.c', + 'commands/scratchpad_minimize.c', 'commands/seat.c', 'commands/seat/attach.c', 'commands/seat/cursor.c', diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 0b860920..a470005a 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -71,6 +71,10 @@ The following commands may only be used in the configuration file. *wordexp*(3) for details). The same include file can only be included once; subsequent attempts will be ignored. +*scratchpad_minimize* + Adjusts if minimized windows should be moved into the scratchpad + (enable|disable). Must be set at config-time (when starting sway). + *swaybg_command* Executes custom background _command_. Default is _swaybg_. Refer to *sway-output*(5) for more information. diff --git a/sway/tree/root.c b/sway/tree/root.c index 8934721f..636a3b75 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -55,6 +55,17 @@ void root_destroy(struct sway_root *root) { free(root); } +/* Set minimized state from scratchpad container `show` state */ +static void root_scratchpad_set_minimize(struct sway_container *con, bool minimize) { + struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel = con->view->foreign_toplevel; + if (wlr_surface_is_xwayland_surface(con->view->surface)) { + struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(con->view->surface); + wlr_xwayland_surface_set_minimized(xsurface, minimize); + } else if (foreign_toplevel) { + wlr_foreign_toplevel_handle_v1_set_minimized(foreign_toplevel, minimize); + } +} + void root_scratchpad_add_container(struct sway_container *con, struct sway_workspace *ws) { if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { return; @@ -96,6 +107,11 @@ void root_scratchpad_add_container(struct sway_container *con, struct sway_works seat_set_focus(seat, new_focus); } + // Set minimize state to minimized + if (config->scratchpad_minimize) { + root_scratchpad_set_minimize(con, true); + } + ipc_event_window(con, "move"); } @@ -141,6 +157,11 @@ void root_scratchpad_show(struct sway_container *con) { } workspace_add_floating(new_ws, con); + // Set minimize state to normalized + if (config->scratchpad_minimize) { + root_scratchpad_set_minimize(con, false); + } + // Make sure the container's center point overlaps this workspace double center_lx = con->pending.x + con->pending.width / 2; double center_ly = con->pending.y + con->pending.height / 2; @@ -172,6 +193,11 @@ void root_scratchpad_hide(struct sway_container *con) { return; } + // Set minimize state to minimized + if (config->scratchpad_minimize) { + root_scratchpad_set_minimize(con, true); + } + disable_fullscreen(con, NULL); container_for_each_child(con, disable_fullscreen, NULL); container_detach(con); diff --git a/sway/tree/view.c b/sway/tree/view.c index 7d4dbaeb..b66dc2f8 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -746,6 +746,9 @@ static void handle_foreign_destroy( listener, view, foreign_destroy); wl_list_remove(&view->foreign_activate_request.link); + if (view->foreign_minimize.notify) { + wl_list_remove(&view->foreign_minimize.link); + } wl_list_remove(&view->foreign_fullscreen_request.link); wl_list_remove(&view->foreign_close_request.link); wl_list_remove(&view->foreign_destroy.link); @@ -819,9 +822,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view->foreign_destroy.notify = handle_foreign_destroy; wl_signal_add(&view->foreign_toplevel->events.destroy, &view->foreign_destroy); - view->foreign_minimize.notify = handle_foreign_minimize; - wl_signal_add(&view->foreign_toplevel->events.request_minimize, - &view->foreign_minimize); + if (config->scratchpad_minimize) { + view->foreign_minimize.notify = handle_foreign_minimize; + wl_signal_add(&view->foreign_toplevel->events.request_minimize, + &view->foreign_minimize); + } struct sway_container *container = view->container;