From 81a456d68d897567d6b1ece6f2283692df2988a1 Mon Sep 17 00:00:00 2001 From: Nate Symer Date: Sat, 26 May 2018 13:23:00 -0400 Subject: [PATCH] gaps & smart_gaps commands + de-hardcode gaps --- include/sway/tree/container.h | 4 + sway/commands.c | 2 + sway/commands/gaps.c | 133 ++++++++++++++++++++++++++++++++++ sway/commands/smart_gaps.c | 28 +++++++ sway/config.c | 4 +- sway/tree/arrange.c | 29 ++++++-- sway/tree/container.c | 4 + 7 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 sway/commands/gaps.c create mode 100644 sway/commands/smart_gaps.c diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index a5f591ce5..ff16821f6 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -84,6 +84,10 @@ struct sway_container { double width, height; double saved_width, saved_height; + bool has_gaps; + double gaps_inner; + double gaps_outer; + list_t *children; struct sway_container *parent; diff --git a/sway/commands.c b/sway/commands.c index 6cba0a1c5..40f80a83c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -109,6 +109,7 @@ static struct cmd_handler handlers[] = { { "font", cmd_font }, { "for_window", cmd_for_window }, { "fullscreen", cmd_fullscreen }, + { "gaps", cmd_gaps }, { "hide_edge_borders", cmd_hide_edge_borders }, { "include", cmd_include }, { "input", cmd_input }, @@ -117,6 +118,7 @@ static struct cmd_handler handlers[] = { { "output", cmd_output }, { "seat", cmd_seat }, { "show_marks", cmd_show_marks }, + { "smart_gaps", cmd_smart_gaps }, { "workspace", cmd_workspace }, { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, }; diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c new file mode 100644 index 000000000..329d784c0 --- /dev/null +++ b/sway/commands/gaps.c @@ -0,0 +1,133 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/tree/arrange.h" +#include "log.h" +#include "stringop.h" + +int read_double(char *str, double *out) { + char *end; + double v = strtod(str, &end); + if (v == -HUGE_VAL || v == HUGE_VAL || strlen(end) > 0) { + *out = 0.0; + return 1; + } + *out = v; + return 0; +} + +struct cmd_results *cmd_gaps(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (strcmp(argv[0], "edge_gaps") == 0) { + if (strcmp(argv[1], "on") == 0) { + config->edge_gaps = true; + arrange_root(); + } else if (strcmp(argv[1], "off") == 0) { + config->edge_gaps = false; + arrange_root(); + } else if (strcmp(argv[1], "toggle") == 0) { + if (config->active) { + config->edge_gaps = !(config->edge_gaps); + arrange_root(); + } else { + return cmd_results_new(CMD_INVALID, "gaps", "Cannot toggle gaps while not running."); + } + } else { + return cmd_results_new(CMD_INVALID, "gaps", ""); + } + } else { + int amount_idx = 0; + char op = '='; + char scope = 'a'; + bool inner = true; + + if (strcmp(argv[amount_idx], "inner") == 0) { + amount_idx++; + inner = true; + } else if (strcmp(argv[amount_idx], "outer") == 0) { + amount_idx++; + inner = false; + } + + if (amount_idx > 0) { + if (strcmp(argv[0], "all") == 0) { + amount_idx++; + scope = 'a'; + } else if (strcmp(argv[0], "workspace") == 0) { + amount_idx++; + scope = 'w'; + } else if (strcmp(argv[0], "current") == 0) { + amount_idx++; + scope = 'c'; + } + + if (strcmp(argv[amount_idx], "set") == 0) { + amount_idx++; + op = '='; + } else if (strcmp(argv[amount_idx], "plus") == 0) { + amount_idx++; + op = '+'; + } else if (strcmp(argv[amount_idx], "minus") == 0) { + amount_idx++; + op = '-'; + } + } + + double val; + if (read_double(argv[amount_idx], &val) == 0) { + if (amount_idx == 0) { + config->gaps_inner = val; + config->gaps_outer = val; + arrange_root(); + } else { + double total = val; + if (op == '-') { + total = (inner ? config->gaps_inner : config->gaps_outer) - val; + if (total < 0) { + total = 0; + } + } else if (op == '+') { + total = (inner ? config->gaps_inner : config->gaps_inner) + val; + } + + if (scope == 'a') { + if (inner) { + config->gaps_inner = total; + } else { + config->gaps_outer = total; + } + arrange_root(); + } else if (scope == 'w') { + struct sway_container *workspace = + config->handler_context.current_container; + if (workspace->type != C_WORKSPACE) { + workspace = container_parent(workspace, C_WORKSPACE); + } + workspace->has_gaps = true; + if (inner) { + workspace->gaps_inner = total; + } else { + workspace->gaps_outer = total; + } + arrange_workspace(workspace); + } else if (scope == 'c') { + struct sway_container *container = + config->handler_context.current_container; + container->has_gaps = true; + if (inner) { + container->gaps_inner = total; + } else { + container->gaps_outer = total; + } + arrange_workspace(container_parent(container, C_WORKSPACE)); + } + } + } + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c new file mode 100644 index 000000000..976b3f252 --- /dev/null +++ b/sway/commands/smart_gaps.c @@ -0,0 +1,28 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/tree/arrange.h" +#include "sway/tree/view.h" +#include "sway/tree/container.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *cmd_smart_gaps(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "smart_gaps", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (strcmp(argv[0], "on") == 0) { + config->smart_gaps = true; + arrange_root(); + } else if (strcmp(argv[0], "off") == 0) { + config->smart_gaps = false; + arrange_root(); + } else { + return cmd_results_new(CMD_INVALID, "smart_gaps", + "Expected 'smart_gaps ' "); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 34c8a2802..b524b7dcc 100644 --- a/sway/config.c +++ b/sway/config.c @@ -193,8 +193,8 @@ static void config_defaults(struct sway_config *config) { config->edge_gaps = true; config->smart_gaps = false; - config->gaps_inner = 0; - config->gaps_outer = 0; + config->gaps_inner = 20;//0; + config->gaps_outer = 20;//0; if (!(config->active_bar_modifiers = create_list())) goto cleanup; diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 8424460cb..ab8b57df8 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -59,8 +59,6 @@ void arrange_output(struct sway_container *output) { container_damage_whole(output); } -static double GAPS = 20.0; - void arrange_workspace(struct sway_container *workspace) { if (config->reloading) { return; @@ -73,10 +71,18 @@ void arrange_workspace(struct sway_container *workspace) { struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); - workspace->width = area->width - (2 * GAPS); - workspace->height = area->height - (2 * GAPS); - workspace->x = area->x + GAPS; - workspace->y = area->y + GAPS; + if (config->edge_gaps || (config->smart_gaps && workspace->children->length > 1)) { + double gaps = workspace->has_gaps ? workspace->gaps_outer : config->gaps_outer; + workspace->width = area->width - (2 * gaps); + workspace->height = area->height - (2 * gaps); + workspace->x = area->x + gaps; + workspace->y = area->y + gaps; + } else { + workspace->width = area->width; + workspace->height = area->height; + workspace->x = area->x; + workspace->y = area->y; + } wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, workspace->x, workspace->y); arrange_children_of(workspace); @@ -118,6 +124,7 @@ static void apply_horiz_layout(struct sway_container *parent) { struct sway_container *child; for (size_t i = 0; i < num_children; ++i) { child = parent->children->items[i]; + double gaps = child->has_gaps ? child->gaps_inner : config->gaps_inner; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, child->width, scale); @@ -125,7 +132,7 @@ static void apply_horiz_layout(struct sway_container *parent) { child->y = parent->y + parent_offset; child->width = floor(child->width * scale); child->height = parent_height; - child_x += child->width + GAPS; + child_x += child->width + gaps; } // Make last child use remaining width of parent child->width = parent->x + parent->width - child->x; @@ -166,6 +173,7 @@ static void apply_vert_layout(struct sway_container *parent) { struct sway_container *child; for (size_t i = 0; i < num_children; ++i) { child = parent->children->items[i]; + double gaps = child->has_gaps ? child->gaps_inner : config->gaps_inner; wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, child->height, scale); @@ -173,7 +181,7 @@ static void apply_vert_layout(struct sway_container *parent) { child->y = child_y; child->width = parent->width; child->height = floor(child->height * scale); - child_y += child->height + GAPS; + child_y += child->height + gaps; } // Make last child use remaining height of parent child->height = parent->y + parent_offset + parent_height - child->y; @@ -246,6 +254,11 @@ void arrange_children_of(struct sway_container *parent) { if (child->type == C_VIEW) { view_autoconfigure(child->sway_view); } else { + if (parent->has_gaps && !child->has_gaps) { + child->has_gaps = true; + child->gaps_inner = parent->gaps_inner; + child->gaps_outer = parent->gaps_outer; + } arrange_children_of(child); } } diff --git a/sway/tree/container.c b/sway/tree/container.c index f29a9adc0..bf2381639 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -134,6 +134,10 @@ struct sway_container *container_create(enum sway_container_type type) { wl_signal_add(&c->events.reparent, &c->reparent); c->reparent.notify = handle_reparent; + c->has_gaps = false; + c->gaps_inner = 0; + c->gaps_outer = 0; + return c; }