aboutsummaryrefslogtreecommitdiff
path: root/sway/commands
diff options
context:
space:
mode:
authorRyan Dwyer <RyanDwyer@users.noreply.github.com>2018-11-08 22:41:14 +1000
committerGitHub <noreply@github.com>2018-11-08 22:41:14 +1000
commitaad2f444f0bfc1cd7057bf55c9249dc36680af15 (patch)
tree843a3d538ae4176884b43f111b6330a4935496e3 /sway/commands
parente53b4813fe7a57f189c91e45355309567fb67b31 (diff)
parent9e8aa3953098adb6175c26aebd984a32a2beccb0 (diff)
Merge pull request #3087 from RedSoxFan/side-gaps
Implement per side and per direction outer gaps
Diffstat (limited to 'sway/commands')
-rw-r--r--sway/commands/gaps.c151
-rw-r--r--sway/commands/workspace.c124
2 files changed, 196 insertions, 79 deletions
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c
index 3f0ef155..faaeab37 100644
--- a/sway/commands/gaps.c
+++ b/sway/commands/gaps.c
@@ -16,73 +16,128 @@ enum gaps_op {
struct gaps_data {
bool inner;
+ struct {
+ bool top;
+ bool right;
+ bool bottom;
+ bool left;
+ } outer;
enum gaps_op operation;
int amount;
};
-// gaps inner|outer <px>
+// Prevent negative outer gaps from moving windows out of the workspace.
+static void prevent_invalid_outer_gaps(void) {
+ if (config->gaps_outer.top < -config->gaps_inner) {
+ config->gaps_outer.top = -config->gaps_inner;
+ }
+ if (config->gaps_outer.right < -config->gaps_inner) {
+ config->gaps_outer.right = -config->gaps_inner;
+ }
+ if (config->gaps_outer.bottom < -config->gaps_inner) {
+ config->gaps_outer.bottom = -config->gaps_inner;
+ }
+ if (config->gaps_outer.left < -config->gaps_inner) {
+ config->gaps_outer.left = -config->gaps_inner;
+ }
+}
+
+// gaps inner|outer|horizontal|vertical|top|right|bottom|left <px>
+static const char *expected_defaults =
+ "'gaps inner|outer|horizontal|vertical|top|right|bottom|left <px>'";
static struct cmd_results *gaps_set_defaults(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2);
if (error) {
return error;
}
- bool inner;
- if (strcasecmp(argv[0], "inner") == 0) {
- inner = true;
- } else if (strcasecmp(argv[0], "outer") == 0) {
- inner = false;
- } else {
- return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer <px>'");
- }
-
char *end;
int amount = strtol(argv[1], &end, 10);
if (strlen(end) && strcasecmp(end, "px") != 0) {
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer <px>'");
+ "Expected %s", expected_defaults);
}
- if (inner) {
+
+ bool valid = false;
+ if (!strcasecmp(argv[0], "inner")) {
+ valid = true;
config->gaps_inner = (amount >= 0) ? amount : 0;
} else {
- config->gaps_outer = amount;
- }
-
- // Prevent negative outer gaps from moving windows out of the workspace.
- if (config->gaps_outer < -config->gaps_inner) {
- config->gaps_outer = -config->gaps_inner;
+ if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical")
+ || !strcasecmp(argv[0], "top")) {
+ valid = true;
+ config->gaps_outer.top = amount;
+ }
+ if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal")
+ || !strcasecmp(argv[0], "right")) {
+ valid = true;
+ config->gaps_outer.right = amount;
+ }
+ if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical")
+ || !strcasecmp(argv[0], "bottom")) {
+ valid = true;
+ config->gaps_outer.bottom = amount;
+ }
+ if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal")
+ || !strcasecmp(argv[0], "left")) {
+ valid = true;
+ config->gaps_outer.left = amount;
+ }
+ }
+ if (!valid) {
+ return cmd_results_new(CMD_INVALID, "gaps",
+ "Expected %s", expected_defaults);
}
+ prevent_invalid_outer_gaps();
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
-static void configure_gaps(struct sway_workspace *ws, void *_data) {
- struct gaps_data *data = _data;
- int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer;
-
- switch (data->operation) {
+static void apply_gaps_op(int *prop, enum gaps_op op, int amount) {
+ switch (op) {
case GAPS_OP_SET:
- *prop = data->amount;
+ *prop = amount;
break;
case GAPS_OP_ADD:
- *prop += data->amount;
+ *prop += amount;
break;
case GAPS_OP_SUBTRACT:
- *prop -= data->amount;
+ *prop -= amount;
break;
}
+}
+
+static void configure_gaps(struct sway_workspace *ws, void *_data) {
+ // Apply operation to gaps
+ struct gaps_data *data = _data;
+ if (data->inner) {
+ apply_gaps_op(&ws->gaps_inner, data->operation, data->amount);
+ }
+ if (data->outer.top) {
+ apply_gaps_op(&(ws->gaps_outer.top), data->operation, data->amount);
+ }
+ if (data->outer.right) {
+ apply_gaps_op(&(ws->gaps_outer.right), data->operation, data->amount);
+ }
+ if (data->outer.bottom) {
+ apply_gaps_op(&(ws->gaps_outer.bottom), data->operation, data->amount);
+ }
+ if (data->outer.left) {
+ apply_gaps_op(&(ws->gaps_outer.left), data->operation, data->amount);
+ }
+
// Prevent invalid gaps configurations.
if (ws->gaps_inner < 0) {
ws->gaps_inner = 0;
}
- if (ws->gaps_outer < -ws->gaps_inner) {
- ws->gaps_outer = -ws->gaps_inner;
- }
+ prevent_invalid_outer_gaps();
arrange_workspace(ws);
}
-// gaps inner|outer current|all set|plus|minus <px>
+// gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all
+// set|plus|minus <px>
+static const char *expected_runtime = "'gaps inner|outer|horizontal|vertical|"
+ "top|right|bottom|left current|all set|plus|minus <px>'";
static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4);
if (error) {
@@ -93,15 +148,24 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
"Can't run this command while there's no outputs connected.");
}
- struct gaps_data data;
+ struct gaps_data data = {0};
if (strcasecmp(argv[0], "inner") == 0) {
data.inner = true;
- } else if (strcasecmp(argv[0], "outer") == 0) {
- data.inner = false;
} else {
+ data.outer.top = !strcasecmp(argv[0], "outer") ||
+ !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "top");
+ data.outer.right = !strcasecmp(argv[0], "outer") ||
+ !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "right");
+ data.outer.bottom = !strcasecmp(argv[0], "outer") ||
+ !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "bottom");
+ data.outer.left = !strcasecmp(argv[0], "outer") ||
+ !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "left");
+ }
+ if (!data.inner && !data.outer.top && !data.outer.right &&
+ !data.outer.bottom && !data.outer.left) {
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer current|all set|plus|minus <px>'");
+ "Expected %s", expected_runtime);
}
bool all;
@@ -111,7 +175,7 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
all = true;
} else {
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer current|all set|plus|minus <px>'");
+ "Expected %s", expected_runtime);
}
if (strcasecmp(argv[2], "set") == 0) {
@@ -122,14 +186,14 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
data.operation = GAPS_OP_SUBTRACT;
} else {
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer current|all set|plus|minus <px>'");
+ "Expected %s", expected_runtime);
}
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>'");
+ "Expected %s", expected_runtime);
}
if (all) {
@@ -141,8 +205,10 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
-// gaps inner|outer <px> - sets defaults for workspaces
-// gaps inner|outer current|all set|plus|minus <px> - runtime only
+// gaps inner|outer|<dir>|<side> <px> - sets defaults for workspaces
+// gaps inner|outer|<dir>|<side> current|all set|plus|minus <px> - runtime only
+// <dir> = horizontal|vertical
+// <side> = top|right|bottom|left
struct cmd_results *cmd_gaps(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2);
if (error) {
@@ -159,9 +225,8 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
}
if (config_loading) {
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer <px>'");
+ "Expected %s", expected_defaults);
}
return cmd_results_new(CMD_INVALID, "gaps",
- "Expected 'gaps inner|outer <px>' or "
- "'gaps inner|outer current|all set|plus|minus <px>'");
+ "Expected %s or %s", expected_runtime, expected_defaults);
}
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 5abbb676..168494d2 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -22,7 +22,10 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
}
wsc->workspace = strdup(ws_name);
wsc->gaps_inner = INT_MIN;
- wsc->gaps_outer = INT_MIN;
+ wsc->gaps_outer.top = INT_MIN;
+ wsc->gaps_outer.right = INT_MIN;
+ wsc->gaps_outer.bottom = INT_MIN;
+ wsc->gaps_outer.left = INT_MIN;
list_add(config->workspace_configs, wsc);
return wsc;
}
@@ -33,6 +36,89 @@ void free_workspace_config(struct workspace_config *wsc) {
free(wsc);
}
+static void prevent_invalid_outer_gaps(struct workspace_config *wsc) {
+ if (wsc->gaps_outer.top != INT_MIN &&
+ wsc->gaps_outer.top < -wsc->gaps_inner) {
+ wsc->gaps_outer.top = -wsc->gaps_inner;
+ }
+ if (wsc->gaps_outer.right != INT_MIN &&
+ wsc->gaps_outer.right < -wsc->gaps_inner) {
+ wsc->gaps_outer.right = -wsc->gaps_inner;
+ }
+ if (wsc->gaps_outer.bottom != INT_MIN &&
+ wsc->gaps_outer.bottom < -wsc->gaps_inner) {
+ wsc->gaps_outer.bottom = -wsc->gaps_inner;
+ }
+ if (wsc->gaps_outer.left != INT_MIN &&
+ wsc->gaps_outer.left < -wsc->gaps_inner) {
+ wsc->gaps_outer.left = -wsc->gaps_inner;
+ }
+}
+
+static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
+ int gaps_location) {
+ const char *expected = "Expected 'workspace <name> gaps "
+ "inner|outer|horizontal|vertical|top|right|bottom|left <px>'";
+ struct cmd_results *error = NULL;
+ 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");
+ }
+
+ char *end;
+ int amount = strtol(argv[gaps_location + 2], &end, 10);
+ if (strlen(end)) {
+ free(end);
+ return cmd_results_new(CMD_FAILURE, "workspace gaps", expected);
+ }
+
+ bool valid = false;
+ char *type = argv[gaps_location + 1];
+ if (!strcasecmp(type, "inner")) {
+ valid = true;
+ wsc->gaps_inner = (amount >= 0) ? amount : 0;
+ } else {
+ if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical")
+ || !strcasecmp(type, "top")) {
+ valid = true;
+ wsc->gaps_outer.top = amount;
+ }
+ if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal")
+ || !strcasecmp(type, "right")) {
+ valid = true;
+ wsc->gaps_outer.right = amount;
+ }
+ if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical")
+ || !strcasecmp(type, "bottom")) {
+ valid = true;
+ wsc->gaps_outer.bottom = amount;
+ }
+ if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal")
+ || !strcasecmp(type, "left")) {
+ valid = true;
+ wsc->gaps_outer.left = amount;
+ }
+ }
+ if (!valid) {
+ return cmd_results_new(CMD_INVALID, "workspace gaps", expected);
+ }
+
+ // Prevent invalid gaps configurations.
+ if (wsc->gaps_inner != INT_MIN && wsc->gaps_inner < 0) {
+ wsc->gaps_inner = 0;
+ }
+ prevent_invalid_outer_gaps(wsc);
+
+ return error;
+}
+
struct cmd_results *cmd_workspace(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) {
@@ -68,43 +154,9 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
free(wsc->output);
wsc->output = strdup(argv[output_location + 1]);
} else if (gaps_location >= 0) {
- if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) {
+ if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
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;
-
- // Prevent invalid gaps configurations.
- if (wsc->gaps_inner < 0) {
- wsc->gaps_inner = 0;
- }
- if (wsc->gaps_outer < -wsc->gaps_inner) {
- wsc->gaps_outer = -wsc->gaps_inner;
- }
-
} else {
if (config->reading || !config->active) {
return cmd_results_new(CMD_DEFER, "workspace", NULL);