From ab58edfc90b7e4d72b28c679120f37da00f89124 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 15 Jun 2019 20:02:17 +0200 Subject: [PATCH] Add inhibit_fullscreen command inhibit_fullscreen allows a container to service but ignore fullscreen requests from clients. This allows clients to change to fullscreen mode without changing dimensions of its container. --- include/sway/commands.h | 1 + include/sway/tree/container.h | 5 ++++ sway/commands.c | 1 + sway/commands/inhibit_fullscreen.c | 45 ++++++++++++++++++++++++++++++ sway/desktop/xdg_shell.c | 2 +- sway/meson.build | 1 + sway/sway.5.scd | 6 ++++ sway/tree/container.c | 41 +++++++++++++++++++++------ 8 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 sway/commands/inhibit_fullscreen.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 4a2f8c20d..d26ad053c 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -135,6 +135,7 @@ sway_cmd cmd_fullscreen; sway_cmd cmd_gaps; sway_cmd cmd_hide_edge_borders; sway_cmd cmd_include; +sway_cmd cmd_inhibit_fullscreen; sway_cmd cmd_inhibit_idle; sway_cmd cmd_input; sway_cmd cmd_seat; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 136d618b2..0c4bc07aa 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -108,6 +108,9 @@ struct sway_container { enum sway_fullscreen_mode fullscreen_mode; + bool inhibit_fullscreen; + bool is_fullscreen; + enum sway_container_border border; // Used when the view changes to CSD unexpectedly. This will be a non-B_CSD @@ -269,6 +272,8 @@ void container_end_mouse_operation(struct sway_container *container); void container_set_fullscreen(struct sway_container *con, enum sway_fullscreen_mode mode); +void container_request_fullscreen(struct sway_container *con, bool enable); + /** * Convenience function. */ diff --git a/sway/commands.c b/sway/commands.c index fe1e98b53..11feabc62 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -114,6 +114,7 @@ static struct cmd_handler command_handlers[] = { { "exit", cmd_exit }, { "floating", cmd_floating }, { "fullscreen", cmd_fullscreen }, + { "inhibit_fullscreen", cmd_inhibit_fullscreen }, { "inhibit_idle", cmd_inhibit_idle }, { "kill", cmd_kill }, { "layout", cmd_layout }, diff --git a/sway/commands/inhibit_fullscreen.c b/sway/commands/inhibit_fullscreen.c new file mode 100644 index 000000000..11da7e297 --- /dev/null +++ b/sway/commands/inhibit_fullscreen.c @@ -0,0 +1,45 @@ +#include +#include "log.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/tree/arrange.h" +#include "sway/tree/container.h" +#include "sway/tree/view.h" +#include "sway/tree/workspace.h" +#include "util.h" + +// inhibit_fullscreen [toggle|enable|disable] +struct cmd_results *cmd_inhibit_fullscreen(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "inhibit_fullscreen", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (!root->outputs->length) { + return cmd_results_new(CMD_FAILURE, + "Can't run this command while there's no outputs connected."); + } + struct sway_node *node = config->handler_context.node; + struct sway_container *container = config->handler_context.container; + struct sway_workspace *workspace = config->handler_context.workspace; + if (node->type == N_WORKSPACE && workspace->tiling->length == 0) { + return cmd_results_new(CMD_FAILURE, + "Can't fullscreen an empty workspace"); + } + + // If in the scratchpad, operate on the highest container + if (container && !container->workspace) { + while (container->parent) { + container = container->parent; + } + } + + bool enable = false; + if (strcasecmp(argv[0], "toggle") == 0) { + enable = !container->inhibit_fullscreen; + } else { + enable = strcasecmp(argv[0], "enable") == 0; + } + + container->inhibit_fullscreen = enable; + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 03f372416..7d0a10c89 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -363,7 +363,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) } } - container_set_fullscreen(view->container, e->fullscreen); + container_request_fullscreen(view->container, e->fullscreen); arrange_root(); transaction_commit_dirty(); diff --git a/sway/meson.build b/sway/meson.build index 0db458362..64dbcaa09 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -65,6 +65,7 @@ sway_sources = files( 'commands/fullscreen.c', 'commands/gaps.c', 'commands/hide_edge_borders.c', + 'commands/inhibit_fullscreen.c', 'commands/inhibit_idle.c', 'commands/kill.c', 'commands/mark.c', diff --git a/sway/sway.5.scd b/sway/sway.5.scd index f608ad2e9..e913f3c58 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -161,6 +161,12 @@ set|plus|minus _right_, _bottom_, and _left_ or per direction with _horizontal_ and _vertical_. +*inhibit_fullscreen* toggle|enable|disable + Set/unset fullscreen inhibitor for for the container. If enabled, client + requests to fullscreen the container will be ignored. This can be used to + have clients transition to their fullscreen interface, while still + constraining them to their container. + *inhibit_idle* focus|fullscreen|open|none|visible Set/unset an idle inhibitor for the view. _focus_ will inhibit idle when the view is focused by any seat. _fullscreen_ will inhibit idle when the diff --git a/sway/tree/container.c b/sway/tree/container.c index fe622c7bf..b4c0e09ab 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -990,9 +990,11 @@ static void container_fullscreen_workspace(struct sway_container *con) { "Expected a non-fullscreen container")) { return; } - bool enable = true; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + if (!con->inhibit_fullscreen) { + bool enable = true; + set_fullscreen_iterator(con, &enable); + container_for_each_child(con, set_fullscreen_iterator, &enable); + } con->saved_x = con->x; con->saved_y = con->y; @@ -1017,6 +1019,7 @@ static void container_fullscreen_workspace(struct sway_container *con) { } con->fullscreen_mode = FULLSCREEN_WORKSPACE; + con->is_fullscreen = true; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); } @@ -1026,9 +1029,11 @@ static void container_fullscreen_global(struct sway_container *con) { "Expected a non-fullscreen container")) { return; } - bool enable = true; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + if (!con->inhibit_fullscreen) { + bool enable = true; + set_fullscreen_iterator(con, &enable); + container_for_each_child(con, set_fullscreen_iterator, &enable); + } root->fullscreen_global = con; con->saved_x = con->x; @@ -1045,6 +1050,7 @@ static void container_fullscreen_global(struct sway_container *con) { } con->fullscreen_mode = FULLSCREEN_GLOBAL; + con->is_fullscreen = true; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); } @@ -1054,9 +1060,11 @@ void container_fullscreen_disable(struct sway_container *con) { "Expected a fullscreen container")) { return; } - bool enable = false; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + if (!con->inhibit_fullscreen) { + bool enable = false; + set_fullscreen_iterator(con, &enable); + container_for_each_child(con, set_fullscreen_iterator, &enable); + } if (container_is_floating(con)) { con->x = con->saved_x; @@ -1088,6 +1096,7 @@ void container_fullscreen_disable(struct sway_container *con) { } con->fullscreen_mode = FULLSCREEN_NONE; + con->is_fullscreen = false; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); @@ -1134,6 +1143,20 @@ void container_set_fullscreen(struct sway_container *con, } } +void container_request_fullscreen(struct sway_container *con, bool enable) { + if (con->inhibit_fullscreen) { + set_fullscreen_iterator(con, &enable); + container_for_each_child(con, set_fullscreen_iterator, &enable); + if (con->workspace) { + arrange_workspace(con->workspace); + } + con->is_fullscreen = enable; + return; + } + + container_set_fullscreen(con, enable); +} + struct sway_container *container_toplevel_ancestor( struct sway_container *container) { while (container->parent) {