Merge pull request #2726 from RyanDwyer/overhaul-gaps

Make gaps implementation consistent with i3-gaps
master
Drew DeVault 6 years ago committed by GitHub
commit f1dbdce0b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -174,6 +174,8 @@ struct output_config {
struct workspace_config { struct workspace_config {
char *workspace; char *workspace;
char *output; char *output;
int gaps_inner;
int gaps_outer;
}; };
struct bar_config { struct bar_config {

@ -94,9 +94,6 @@ struct sway_container {
// The gaps currently applied to the container. // The gaps currently applied to the container.
double current_gaps; double current_gaps;
bool has_gaps;
double gaps_inner;
double gaps_outer;
struct sway_workspace *workspace; // NULL when hidden in the scratchpad struct sway_workspace *workspace; // NULL when hidden in the scratchpad
struct sway_container *parent; // NULL if container in root of workspace struct sway_container *parent; // NULL if container in root of workspace

@ -32,10 +32,9 @@ struct sway_workspace {
enum sway_container_layout layout; enum sway_container_layout layout;
enum sway_container_layout prev_split_layout; enum sway_container_layout prev_split_layout;
double current_gaps; int current_gaps;
bool has_gaps; int gaps_inner;
double gaps_inner; int gaps_outer;
double gaps_outer;
struct sway_output *output; // NULL if no outputs are connected struct sway_output *output; // NULL if no outputs are connected
list_t *floating; // struct sway_container list_t *floating; // struct sway_container

@ -1,4 +1,5 @@
#include <string.h> #include <string.h>
#include <strings.h>
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
@ -13,172 +14,173 @@ enum gaps_op {
GAPS_OP_SUBTRACT GAPS_OP_SUBTRACT
}; };
enum gaps_scope { struct gaps_data {
GAPS_SCOPE_ALL, bool inner;
GAPS_SCOPE_WORKSPACE, enum gaps_op operation;
GAPS_SCOPE_CURRENT int amount;
}; };
struct cmd_results *cmd_gaps(int argc, char **argv) { // gaps edge_gaps on|off|toggle
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1); static struct cmd_results *gaps_edge_gaps(int argc, char **argv) {
if (error) { struct cmd_results *error;
if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) {
return error; return error;
} }
if (strcmp(argv[0], "edge_gaps") == 0) { if (strcmp(argv[1], "on") == 0) {
if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) { config->edge_gaps = true;
return error; } else if (strcmp(argv[1], "off") == 0) {
} config->edge_gaps = false;
} else if (strcmp(argv[1], "toggle") == 0) {
if (strcmp(argv[1], "on") == 0) { if (!config->active) {
config->edge_gaps = true;
} else if (strcmp(argv[1], "off") == 0) {
config->edge_gaps = false;
} else if (strcmp(argv[1], "toggle") == 0) {
if (!config->active) {
return cmd_results_new(CMD_INVALID, "gaps",
"Cannot toggle gaps while not running.");
}
config->edge_gaps = !config->edge_gaps;
} else {
return cmd_results_new(CMD_INVALID, "gaps", return cmd_results_new(CMD_INVALID, "gaps",
"gaps edge_gaps on|off|toggle"); "Cannot toggle gaps while not running.");
} }
arrange_root(); config->edge_gaps = !config->edge_gaps;
} else { } else {
int amount_idx = 0; // the current index in argv return cmd_results_new(CMD_INVALID, "gaps",
enum gaps_op op = GAPS_OP_SET; "gaps edge_gaps on|off|toggle");
enum gaps_scope scope = GAPS_SCOPE_ALL; }
bool inner = true; arrange_root();
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
if (strcmp(argv[0], "inner") == 0) { }
amount_idx++;
inner = true;
} else if (strcmp(argv[0], "outer") == 0) {
amount_idx++;
inner = false;
}
// If one of the long variants of the gaps command is used // gaps inner|outer <px>
// (which starts with inner|outer) check the number of args static struct cmd_results *gaps_set_defaults(int argc, char **argv) {
if (amount_idx > 0) { // if we've seen inner|outer struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2);
if (argc > 2) { // check the longest variant if (error) {
error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); return error;
if (error) { }
return error;
}
} else { // check the next longest format
error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2);
if (error) {
return error;
}
}
} else {
error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 1);
if (error) {
return error;
}
}
if (argc == 4) { bool inner;
// Long format: all|workspace|current. if (strcasecmp(argv[0], "inner") == 0) {
if (strcmp(argv[amount_idx], "all") == 0) { inner = true;
amount_idx++; } else if (strcasecmp(argv[0], "outer") == 0) {
scope = GAPS_SCOPE_ALL; inner = false;
} else if (strcmp(argv[amount_idx], "workspace") == 0) { } else {
amount_idx++; return cmd_results_new(CMD_INVALID, "gaps",
scope = GAPS_SCOPE_WORKSPACE; "Expected 'gaps inner|outer <px>'");
} else if (strcmp(argv[amount_idx], "current") == 0) { }
amount_idx++;
scope = GAPS_SCOPE_CURRENT;
}
// Long format: set|plus|minus
if (strcmp(argv[amount_idx], "set") == 0) {
amount_idx++;
op = GAPS_OP_SET;
} else if (strcmp(argv[amount_idx], "plus") == 0) {
amount_idx++;
op = GAPS_OP_ADD;
} else if (strcmp(argv[amount_idx], "minus") == 0) {
amount_idx++;
op = GAPS_OP_SUBTRACT;
}
}
char *end; char *end;
double val = strtod(argv[amount_idx], &end); int amount = strtol(argv[1], &end, 10);
if (strlen(end) && strcasecmp(end, "px") != 0) {
if (strlen(end) && val == 0.0) { // invalid <amount> return cmd_results_new(CMD_INVALID, "gaps",
// guess which variant of the command was attempted "Expected 'gaps inner|outer <px>'");
if (argc == 1) { }
return cmd_results_new(CMD_INVALID, "gaps", "gaps <amount>"); if (amount < 0) {
} amount = 0;
if (argc == 2) { }
return cmd_results_new(CMD_INVALID, "gaps",
"gaps inner|outer <amount>");
}
return cmd_results_new(CMD_INVALID, "gaps",
"gaps inner|outer all|workspace|current set|plus|minus <amount>");
}
if (amount_idx == 0) { // gaps <amount> if (inner) {
config->gaps_inner = val; config->gaps_inner = amount;
config->gaps_outer = val; } else {
arrange_root(); config->gaps_outer = amount;
return cmd_results_new(CMD_SUCCESS, NULL, NULL); }
} return cmd_results_new(CMD_SUCCESS, NULL, NULL);
// Other variants. The middle-length variant (gaps inner|outer <amount>) }
// just defaults the scope to "all" and defaults the op to "set".
double total;
switch (op) {
case GAPS_OP_SUBTRACT: {
total = (inner ? config->gaps_inner : config->gaps_outer) - val;
if (total < 0) {
total = 0;
}
break;
}
case GAPS_OP_ADD: {
total = (inner ? config->gaps_inner : config->gaps_outer) + val;
break;
}
case GAPS_OP_SET: {
total = val;
break;
}
}
if (scope == GAPS_SCOPE_ALL) { static void configure_gaps(struct sway_workspace *ws, void *_data) {
if (inner) { struct gaps_data *data = _data;
config->gaps_inner = total; int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer;
} else {
config->gaps_outer = total; switch (data->operation) {
} case GAPS_OP_SET:
arrange_root(); *prop = data->amount;
} else { break;
if (scope == GAPS_SCOPE_WORKSPACE) { case GAPS_OP_ADD:
struct sway_workspace *ws = config->handler_context.workspace; *prop += data->amount;
ws->has_gaps = true; break;
if (inner) { case GAPS_OP_SUBTRACT:
ws->gaps_inner = total; *prop -= data->amount;
} else { break;
ws->gaps_outer = total; }
} if (*prop < 0) {
arrange_workspace(ws); *prop = 0;
} else { }
struct sway_container *c = config->handler_context.container; arrange_workspace(ws);
c->has_gaps = true; }
if (inner) {
c->gaps_inner = total; // gaps inner|outer current|all set|plus|minus <px>
} else { static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
c->gaps_outer = total; struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4);
} if (error) {
arrange_workspace(c->workspace); return error;
} }
}
struct gaps_data data;
if (strcasecmp(argv[0], "inner") == 0) {
data.inner = true;
} else if (strcasecmp(argv[0], "outer") == 0) {
data.inner = false;
} else {
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer current|all set|plus|minus <px>'");
}
bool all;
if (strcasecmp(argv[1], "current") == 0) {
all = false;
} else if (strcasecmp(argv[1], "all") == 0) {
all = true;
} else {
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer current|all set|plus|minus <px>'");
}
if (strcasecmp(argv[2], "set") == 0) {
data.operation = GAPS_OP_SET;
} else if (strcasecmp(argv[2], "plus") == 0) {
data.operation = GAPS_OP_ADD;
} else if (strcasecmp(argv[2], "minus") == 0) {
data.operation = GAPS_OP_SUBTRACT;
} else {
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer current|all set|plus|minus <px>'");
}
char *end;
data.amount = strtol(argv[3], &end, 10);
if (strlen(end) && strcasecmp(end, "px") != 0) {
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer current|all set|plus|minus <px>'");
}
if (all) {
root_for_each_workspace(configure_gaps, &data);
} else {
configure_gaps(config->handler_context.workspace, &data);
} }
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} }
// gaps edge_gaps on|off|toggle
// gaps inner|outer <px> - sets defaults for workspaces
// gaps inner|outer current|all set|plus|minus <px> - runtime only
struct cmd_results *cmd_gaps(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2);
if (error) {
return error;
}
if (strcmp(argv[0], "edge_gaps") == 0) {
return gaps_edge_gaps(argc, argv);
}
if (argc == 2) {
return gaps_set_defaults(argc, argv);
}
if (argc == 4) {
if (config->active) {
return gaps_set_runtime(argc, argv);
} else {
return cmd_results_new(CMD_INVALID, "gaps",
"This syntax can only be used when sway is running");
}
}
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer <px>' or "
"'gaps inner|outer current|all set|plus|minus <px>'");
}

@ -138,15 +138,14 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
} }
container->layout = new_layout; container->layout = new_layout;
container_update_representation(container); container_update_representation(container);
arrange_container(container);
} else { } else {
if (old_layout != L_TABBED && old_layout != L_STACKED) { if (old_layout != L_TABBED && old_layout != L_STACKED) {
workspace->prev_split_layout = old_layout; workspace->prev_split_layout = old_layout;
} }
workspace->layout = new_layout; workspace->layout = new_layout;
workspace_update_representation(workspace); workspace_update_representation(workspace);
arrange_workspace(workspace);
} }
arrange_workspace(workspace);
} }
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);

@ -20,6 +20,8 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
return NULL; return NULL;
} }
wsc->workspace = strdup(ws_name); wsc->workspace = strdup(ws_name);
wsc->gaps_inner = -1;
wsc->gaps_outer = -1;
list_add(config->workspace_configs, wsc); list_add(config->workspace_configs, wsc);
return wsc; return wsc;
} }
@ -37,6 +39,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
} }
int output_location = -1; int output_location = -1;
int gaps_location = -1;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if (strcasecmp(argv[i], "output") == 0) { if (strcasecmp(argv[i], "output") == 0) {
@ -44,6 +47,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
break; break;
} }
} }
for (int i = 0; i < argc; ++i) {
if (strcasecmp(argv[i], "gaps") == 0) {
gaps_location = i;
break;
}
}
if (output_location >= 0) { if (output_location >= 0) {
if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) {
return error; return error;
@ -57,6 +66,35 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
} }
free(wsc->output); free(wsc->output);
wsc->output = strdup(argv[output_location + 1]); wsc->output = strdup(argv[output_location + 1]);
} else if (gaps_location >= 0) {
if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) {
return error;
}
char *ws_name = join_args(argv, argc - 3);
struct workspace_config *wsc = workspace_config_find_or_create(ws_name);
free(ws_name);
if (!wsc) {
return cmd_results_new(CMD_FAILURE, "workspace gaps",
"Unable to allocate workspace output");
}
int *prop = NULL;
if (strcasecmp(argv[gaps_location + 1], "inner") == 0) {
prop = &wsc->gaps_inner;
} else if (strcasecmp(argv[gaps_location + 1], "outer") == 0) {
prop = &wsc->gaps_outer;
} else {
return cmd_results_new(CMD_FAILURE, "workspace gaps",
"Expected 'workspace <ws> gaps inner|outer <px>'");
}
char *end;
int val = strtol(argv[gaps_location + 2], &end, 10);
if (strlen(end)) {
free(end);
return cmd_results_new(CMD_FAILURE, "workspace gaps",
"Expected 'workspace <ws> gaps inner|outer <px>'");
}
*prop = val >= 0 ? val : 0;
} else { } else {
if (config->reading || !config->active) { if (config->reading || !config->active) {
return cmd_results_new(CMD_DEFER, "workspace", NULL); return cmd_results_new(CMD_DEFER, "workspace", NULL);

@ -419,19 +419,17 @@ The default colors are:
inner gap is nonzero. When _off_, gaps will only be added between views. inner gap is nonzero. When _off_, gaps will only be added between views.
_toggle_ cannot be used in the configuration file. _toggle_ cannot be used in the configuration file.
*gaps* <amount>
Sets _amount_ pixels of gap between windows and around each workspace.
*gaps* inner|outer <amount> *gaps* inner|outer <amount>
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the former Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
affects spacing between views and the latter affects the space around each affects spacing around each view and outer affects the spacing around each
workspace. workspace. Outer gaps are in addition to inner gaps.
This affects new workspaces only, and is used when the workspace doesn't
have its own gaps settings (see: workspace <ws> gaps inner|outer <amount>).
*gaps* inner|outer all|workspace|current set|plus|minus <amount> *gaps* inner|outer all|current set|plus|minus <amount>
Changes the gaps for the _inner_ or _outer_ gap. _all_ changes the gaps for Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the
all views or workspace, _workspace_ changes gaps for all views in current _current_ workspace.
workspace (or current workspace), and _current_ changes gaps for the current
view or workspace.
*hide\_edge\_borders* none|vertical|horizontal|both|smart *hide\_edge\_borders* none|vertical|horizontal|both|smart
Hides window borders adjacent to the screen edges. Default is _none_. Hides window borders adjacent to the screen edges. Default is _none_.
@ -580,6 +578,10 @@ match any output by using the output name "\*".
*workspace* back_and_forth *workspace* back_and_forth
Switches to the previously focused workspace. Switches to the previously focused workspace.
*workspace* <name> gaps inner|outer <amount>
Specifies that workspace _name_ should have the given gaps settings when it
is created.
*workspace* <name> output <output> *workspace* <name> output <output>
Specifies that workspace _name_ should be shown on the specified _output_. Specifies that workspace _name_ should be shown on the specified _output_.

@ -1029,7 +1029,7 @@ void container_add_gaps(struct sway_container *c) {
struct sway_workspace *ws = c->workspace; struct sway_workspace *ws = c->workspace;
c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner; c->current_gaps = ws->gaps_inner;
c->x += c->current_gaps; c->x += c->current_gaps;
c->y += c->current_gaps; c->y += c->current_gaps;
c->width -= 2 * c->current_gaps; c->width -= 2 * c->current_gaps;

@ -68,6 +68,20 @@ struct sway_workspace *workspace_create(struct sway_output *output,
ws->output_priority = create_list(); ws->output_priority = create_list();
workspace_output_add_priority(ws, output); workspace_output_add_priority(ws, output);
ws->gaps_outer = config->gaps_outer;
ws->gaps_inner = config->gaps_inner;
if (name) {
struct workspace_config *wsc = workspace_find_config(name);
if (wsc) {
if (wsc->gaps_outer != -1) {
ws->gaps_outer = wsc->gaps_outer;
}
if (wsc->gaps_inner != -1) {
ws->gaps_inner = wsc->gaps_inner;
}
}
}
output_add_workspace(output, ws); output_add_workspace(output, ws);
output_sort_workspaces(output); output_sort_workspaces(output);
@ -632,13 +646,13 @@ void workspace_add_gaps(struct sway_workspace *ws) {
return; return;
} }
ws->current_gaps = ws->has_gaps ? ws->gaps_outer : config->gaps_outer; ws->current_gaps = ws->gaps_outer;
if (ws->layout == L_TABBED || ws->layout == L_STACKED) { if (ws->layout == L_TABBED || ws->layout == L_STACKED) {
// We have to add inner gaps for this, because children of tabbed and // We have to add inner gaps for this, because children of tabbed and
// stacked containers don't apply their own gaps - they assume the // stacked containers don't apply their own gaps - they assume the
// tabbed/stacked container is using gaps. // tabbed/stacked container is using gaps.
ws->current_gaps += ws->has_gaps ? ws->gaps_inner : config->gaps_inner; ws->current_gaps += ws->gaps_inner;
} }
ws->x += ws->current_gaps; ws->x += ws->current_gaps;

Loading…
Cancel
Save