From f3ab895916ca1a0f004b5ceaefa90eee90676532 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 4 May 2018 08:24:25 -0400 Subject: [PATCH] Implement `floating enable` --- include/sway/tree/container.h | 3 +++ include/sway/tree/layout.h | 3 +++ include/sway/tree/workspace.h | 1 + sway/commands.c | 3 ++- sway/commands/floating.c | 48 +++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + sway/tree/layout.c | 43 ++++++++++++++++++++++++++++--- sway/tree/workspace.c | 2 ++ 8 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 sway/commands/floating.c diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index bb6c04a6..fa2f9286 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -76,6 +76,9 @@ struct sway_container { enum sway_container_layout layout; enum sway_container_layout prev_layout; + // Saves us from searching the list of children/floating in the parent + bool is_floating; + // For C_ROOT, this has no meaning // For C_OUTPUT, this is the output position in layout coordinates // For other types, this is the position in output-local coordinates diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 2e0f2abf..33d0a5d0 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -46,6 +46,9 @@ struct sway_container *container_add_sibling(struct sway_container *parent, struct sway_container *container_remove_child(struct sway_container *child); +void container_add_floating(struct sway_container *workspace, + struct sway_container *child); + struct sway_container *container_replace_child(struct sway_container *child, struct sway_container *new_child); diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 35e1df3b..ece0ab5c 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -8,6 +8,7 @@ struct sway_view; struct sway_workspace { struct sway_container *swayc; struct sway_view *fullscreen; + list_t *floating; }; extern char *prev_workspace_name; diff --git a/sway/commands.c b/sway/commands.c index 6f5113f8..4a8d11ba 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -110,7 +110,6 @@ static struct cmd_handler handlers[] = { { "font", cmd_font }, { "for_window", cmd_for_window }, { "force_focus_wrapping", cmd_force_focus_wrapping }, - { "fullscreen", cmd_fullscreen }, { "hide_edge_borders", cmd_hide_edge_borders }, { "include", cmd_include }, { "input", cmd_input }, @@ -176,7 +175,9 @@ static struct cmd_handler config_handlers[] = { static struct cmd_handler command_handlers[] = { { "border", cmd_border }, { "exit", cmd_exit }, + { "floating", cmd_floating }, { "focus", cmd_focus }, + { "fullscreen", cmd_fullscreen }, { "kill", cmd_kill }, { "layout", cmd_layout }, { "mark", cmd_mark }, diff --git a/sway/commands/floating.c b/sway/commands/floating.c new file mode 100644 index 00000000..8432b0dc --- /dev/null +++ b/sway/commands/floating.c @@ -0,0 +1,48 @@ +#include +#include +#include "sway/commands.h" +#include "sway/input/seat.h" +#include "sway/ipc-server.h" +#include "sway/tree/arrange.h" +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "list.h" + +struct cmd_results *cmd_floating(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) { + return error; + } + struct sway_container *container = + config->handler_context.current_container; + if (container->type != C_VIEW) { + // TODO: This doesn't strictly speaking have to be true + return cmd_results_new(CMD_INVALID, "float", "Only views can float"); + } + + bool wants_floating; + if (strcasecmp(argv[0], "enable") == 0) { + wants_floating = true; + } else if (strcasecmp(argv[0], "disable") == 0) { + wants_floating = false; + } else if (strcasecmp(argv[0], "toggle") == 0) { + wants_floating = !container->is_floating; + } else { + return cmd_results_new(CMD_FAILURE, "floating", + "Expected 'floating "); + } + + // Change from tiled to floating + if (!container->is_floating && wants_floating) { + struct sway_container *workspace = container_parent( + container, C_WORKSPACE); + container_remove_child(container); + container_add_floating(workspace, container); + seat_set_focus(config->handler_context.seat, container); + arrange_workspace(workspace); + } else if (container->is_floating && !wants_floating) { + // TODO + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index 68675f67..5618a257 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -36,6 +36,7 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'commands/floating.c', 'commands/focus.c', 'commands/focus_follows_mouse.c', 'commands/focus_wrapping.c', diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 2f4ae667..7bbeb4b1 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -142,11 +142,26 @@ struct sway_container *container_remove_child(struct sway_container *child) { } struct sway_container *parent = child->parent; - for (int i = 0; i < parent->children->length; ++i) { - if (parent->children->items[i] == child) { - list_del(parent->children, i); - break; + if (!child->is_floating) { + for (int i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + list_del(parent->children, i); + break; + } } + } else { + if (!sway_assert(parent->type == C_WORKSPACE && child->type == C_VIEW, + "Found floating non-view and/or in non-workspace")) { + return parent; + } + struct sway_workspace *ws = parent->sway_workspace; + for (int i = 0; i < ws->floating->length; ++i) { + if (ws->floating->items[i] == child) { + list_del(ws->floating, i); + break; + } + } + child->is_floating = false; } child->parent = NULL; container_notify_subtree_changed(parent); @@ -154,6 +169,26 @@ struct sway_container *container_remove_child(struct sway_container *child) { return parent; } +void container_add_floating(struct sway_container *workspace, + struct sway_container *child) { + if (!sway_assert(workspace->type == C_WORKSPACE && child->type == C_VIEW, + "Attempted to float non-view and/or in non-workspace")) { + return; + } + if (!sway_assert(!child->parent, + "child already has a parent (invalid call)")) { + return; + } + if (!sway_assert(!child->is_floating, + "child is already floating (invalid state)")) { + return; + } + struct sway_workspace *ws = workspace->sway_workspace; + list_add(ws->floating, child); + child->parent = workspace; + child->is_floating = true; +} + void container_move_to(struct sway_container *container, struct sway_container *destination) { if (container == destination diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index f34baa9e..c4f8ac5e 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -12,6 +12,7 @@ #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" +#include "list.h" #include "log.h" #include "util.h" @@ -64,6 +65,7 @@ struct sway_container *workspace_create(struct sway_container *output, return NULL; } swayws->swayc = workspace; + swayws->floating = create_list(); workspace->sway_workspace = swayws; container_add_child(output, workspace);