diff options
author | Ryan Dwyer <RyanDwyer@users.noreply.github.com> | 2018-11-08 22:41:14 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-08 22:41:14 +1000 |
commit | aad2f444f0bfc1cd7057bf55c9249dc36680af15 (patch) | |
tree | 843a3d538ae4176884b43f111b6330a4935496e3 /sway | |
parent | Merge pull request #3086 from RedSoxFan/fix-dup-inner-gaps (diff) | |
parent | Implement per side and per direction outer gaps (diff) | |
download | sway-aad2f444f0bfc1cd7057bf55c9249dc36680af15.tar.gz sway-aad2f444f0bfc1cd7057bf55c9249dc36680af15.tar.zst sway-aad2f444f0bfc1cd7057bf55c9249dc36680af15.zip |
Merge pull request #3087 from RedSoxFan/side-gaps
Implement per side and per direction outer gaps
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/gaps.c | 151 | ||||
-rw-r--r-- | sway/commands/workspace.c | 124 | ||||
-rw-r--r-- | sway/config.c | 5 | ||||
-rw-r--r-- | sway/sway.5.scd | 18 | ||||
-rw-r--r-- | sway/tree/view.c | 3 | ||||
-rw-r--r-- | sway/tree/workspace.c | 65 |
6 files changed, 264 insertions, 102 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 { | |||
16 | 16 | ||
17 | struct gaps_data { | 17 | struct gaps_data { |
18 | bool inner; | 18 | bool inner; |
19 | struct { | ||
20 | bool top; | ||
21 | bool right; | ||
22 | bool bottom; | ||
23 | bool left; | ||
24 | } outer; | ||
19 | enum gaps_op operation; | 25 | enum gaps_op operation; |
20 | int amount; | 26 | int amount; |
21 | }; | 27 | }; |
22 | 28 | ||
23 | // gaps inner|outer <px> | 29 | // Prevent negative outer gaps from moving windows out of the workspace. |
30 | static void prevent_invalid_outer_gaps(void) { | ||
31 | if (config->gaps_outer.top < -config->gaps_inner) { | ||
32 | config->gaps_outer.top = -config->gaps_inner; | ||
33 | } | ||
34 | if (config->gaps_outer.right < -config->gaps_inner) { | ||
35 | config->gaps_outer.right = -config->gaps_inner; | ||
36 | } | ||
37 | if (config->gaps_outer.bottom < -config->gaps_inner) { | ||
38 | config->gaps_outer.bottom = -config->gaps_inner; | ||
39 | } | ||
40 | if (config->gaps_outer.left < -config->gaps_inner) { | ||
41 | config->gaps_outer.left = -config->gaps_inner; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // gaps inner|outer|horizontal|vertical|top|right|bottom|left <px> | ||
46 | static const char *expected_defaults = | ||
47 | "'gaps inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; | ||
24 | static struct cmd_results *gaps_set_defaults(int argc, char **argv) { | 48 | static struct cmd_results *gaps_set_defaults(int argc, char **argv) { |
25 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); | 49 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); |
26 | if (error) { | 50 | if (error) { |
27 | return error; | 51 | return error; |
28 | } | 52 | } |
29 | 53 | ||
30 | bool inner; | ||
31 | if (strcasecmp(argv[0], "inner") == 0) { | ||
32 | inner = true; | ||
33 | } else if (strcasecmp(argv[0], "outer") == 0) { | ||
34 | inner = false; | ||
35 | } else { | ||
36 | return cmd_results_new(CMD_INVALID, "gaps", | ||
37 | "Expected 'gaps inner|outer <px>'"); | ||
38 | } | ||
39 | |||
40 | char *end; | 54 | char *end; |
41 | int amount = strtol(argv[1], &end, 10); | 55 | int amount = strtol(argv[1], &end, 10); |
42 | if (strlen(end) && strcasecmp(end, "px") != 0) { | 56 | if (strlen(end) && strcasecmp(end, "px") != 0) { |
43 | return cmd_results_new(CMD_INVALID, "gaps", | 57 | return cmd_results_new(CMD_INVALID, "gaps", |
44 | "Expected 'gaps inner|outer <px>'"); | 58 | "Expected %s", expected_defaults); |
45 | } | 59 | } |
46 | if (inner) { | 60 | |
61 | bool valid = false; | ||
62 | if (!strcasecmp(argv[0], "inner")) { | ||
63 | valid = true; | ||
47 | config->gaps_inner = (amount >= 0) ? amount : 0; | 64 | config->gaps_inner = (amount >= 0) ? amount : 0; |
48 | } else { | 65 | } else { |
49 | config->gaps_outer = amount; | 66 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") |
50 | } | 67 | || !strcasecmp(argv[0], "top")) { |
51 | 68 | valid = true; | |
52 | // Prevent negative outer gaps from moving windows out of the workspace. | 69 | config->gaps_outer.top = amount; |
53 | if (config->gaps_outer < -config->gaps_inner) { | 70 | } |
54 | config->gaps_outer = -config->gaps_inner; | 71 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") |
72 | || !strcasecmp(argv[0], "right")) { | ||
73 | valid = true; | ||
74 | config->gaps_outer.right = amount; | ||
75 | } | ||
76 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") | ||
77 | || !strcasecmp(argv[0], "bottom")) { | ||
78 | valid = true; | ||
79 | config->gaps_outer.bottom = amount; | ||
80 | } | ||
81 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") | ||
82 | || !strcasecmp(argv[0], "left")) { | ||
83 | valid = true; | ||
84 | config->gaps_outer.left = amount; | ||
85 | } | ||
86 | } | ||
87 | if (!valid) { | ||
88 | return cmd_results_new(CMD_INVALID, "gaps", | ||
89 | "Expected %s", expected_defaults); | ||
55 | } | 90 | } |
56 | 91 | ||
92 | prevent_invalid_outer_gaps(); | ||
57 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 93 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
58 | } | 94 | } |
59 | 95 | ||
60 | static void configure_gaps(struct sway_workspace *ws, void *_data) { | 96 | static void apply_gaps_op(int *prop, enum gaps_op op, int amount) { |
61 | struct gaps_data *data = _data; | 97 | switch (op) { |
62 | int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer; | ||
63 | |||
64 | switch (data->operation) { | ||
65 | case GAPS_OP_SET: | 98 | case GAPS_OP_SET: |
66 | *prop = data->amount; | 99 | *prop = amount; |
67 | break; | 100 | break; |
68 | case GAPS_OP_ADD: | 101 | case GAPS_OP_ADD: |
69 | *prop += data->amount; | 102 | *prop += amount; |
70 | break; | 103 | break; |
71 | case GAPS_OP_SUBTRACT: | 104 | case GAPS_OP_SUBTRACT: |
72 | *prop -= data->amount; | 105 | *prop -= amount; |
73 | break; | 106 | break; |
74 | } | 107 | } |
108 | } | ||
109 | |||
110 | static void configure_gaps(struct sway_workspace *ws, void *_data) { | ||
111 | // Apply operation to gaps | ||
112 | struct gaps_data *data = _data; | ||
113 | if (data->inner) { | ||
114 | apply_gaps_op(&ws->gaps_inner, data->operation, data->amount); | ||
115 | } | ||
116 | if (data->outer.top) { | ||
117 | apply_gaps_op(&(ws->gaps_outer.top), data->operation, data->amount); | ||
118 | } | ||
119 | if (data->outer.right) { | ||
120 | apply_gaps_op(&(ws->gaps_outer.right), data->operation, data->amount); | ||
121 | } | ||
122 | if (data->outer.bottom) { | ||
123 | apply_gaps_op(&(ws->gaps_outer.bottom), data->operation, data->amount); | ||
124 | } | ||
125 | if (data->outer.left) { | ||
126 | apply_gaps_op(&(ws->gaps_outer.left), data->operation, data->amount); | ||
127 | } | ||
128 | |||
75 | // Prevent invalid gaps configurations. | 129 | // Prevent invalid gaps configurations. |
76 | if (ws->gaps_inner < 0) { | 130 | if (ws->gaps_inner < 0) { |
77 | ws->gaps_inner = 0; | 131 | ws->gaps_inner = 0; |
78 | } | 132 | } |
79 | if (ws->gaps_outer < -ws->gaps_inner) { | 133 | prevent_invalid_outer_gaps(); |
80 | ws->gaps_outer = -ws->gaps_inner; | ||
81 | } | ||
82 | arrange_workspace(ws); | 134 | arrange_workspace(ws); |
83 | } | 135 | } |
84 | 136 | ||
85 | // gaps inner|outer current|all set|plus|minus <px> | 137 | // gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all |
138 | // set|plus|minus <px> | ||
139 | static const char *expected_runtime = "'gaps inner|outer|horizontal|vertical|" | ||
140 | "top|right|bottom|left current|all set|plus|minus <px>'"; | ||
86 | static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | 141 | static struct cmd_results *gaps_set_runtime(int argc, char **argv) { |
87 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); | 142 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); |
88 | if (error) { | 143 | if (error) { |
@@ -93,15 +148,24 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
93 | "Can't run this command while there's no outputs connected."); | 148 | "Can't run this command while there's no outputs connected."); |
94 | } | 149 | } |
95 | 150 | ||
96 | struct gaps_data data; | 151 | struct gaps_data data = {0}; |
97 | 152 | ||
98 | if (strcasecmp(argv[0], "inner") == 0) { | 153 | if (strcasecmp(argv[0], "inner") == 0) { |
99 | data.inner = true; | 154 | data.inner = true; |
100 | } else if (strcasecmp(argv[0], "outer") == 0) { | ||
101 | data.inner = false; | ||
102 | } else { | 155 | } else { |
156 | data.outer.top = !strcasecmp(argv[0], "outer") || | ||
157 | !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "top"); | ||
158 | data.outer.right = !strcasecmp(argv[0], "outer") || | ||
159 | !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "right"); | ||
160 | data.outer.bottom = !strcasecmp(argv[0], "outer") || | ||
161 | !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "bottom"); | ||
162 | data.outer.left = !strcasecmp(argv[0], "outer") || | ||
163 | !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "left"); | ||
164 | } | ||
165 | if (!data.inner && !data.outer.top && !data.outer.right && | ||
166 | !data.outer.bottom && !data.outer.left) { | ||
103 | return cmd_results_new(CMD_INVALID, "gaps", | 167 | return cmd_results_new(CMD_INVALID, "gaps", |
104 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 168 | "Expected %s", expected_runtime); |
105 | } | 169 | } |
106 | 170 | ||
107 | bool all; | 171 | bool all; |
@@ -111,7 +175,7 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
111 | all = true; | 175 | all = true; |
112 | } else { | 176 | } else { |
113 | return cmd_results_new(CMD_INVALID, "gaps", | 177 | return cmd_results_new(CMD_INVALID, "gaps", |
114 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 178 | "Expected %s", expected_runtime); |
115 | } | 179 | } |
116 | 180 | ||
117 | if (strcasecmp(argv[2], "set") == 0) { | 181 | if (strcasecmp(argv[2], "set") == 0) { |
@@ -122,14 +186,14 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
122 | data.operation = GAPS_OP_SUBTRACT; | 186 | data.operation = GAPS_OP_SUBTRACT; |
123 | } else { | 187 | } else { |
124 | return cmd_results_new(CMD_INVALID, "gaps", | 188 | return cmd_results_new(CMD_INVALID, "gaps", |
125 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 189 | "Expected %s", expected_runtime); |
126 | } | 190 | } |
127 | 191 | ||
128 | char *end; | 192 | char *end; |
129 | data.amount = strtol(argv[3], &end, 10); | 193 | data.amount = strtol(argv[3], &end, 10); |
130 | if (strlen(end) && strcasecmp(end, "px") != 0) { | 194 | if (strlen(end) && strcasecmp(end, "px") != 0) { |
131 | return cmd_results_new(CMD_INVALID, "gaps", | 195 | return cmd_results_new(CMD_INVALID, "gaps", |
132 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 196 | "Expected %s", expected_runtime); |
133 | } | 197 | } |
134 | 198 | ||
135 | if (all) { | 199 | if (all) { |
@@ -141,8 +205,10 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
141 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 205 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
142 | } | 206 | } |
143 | 207 | ||
144 | // gaps inner|outer <px> - sets defaults for workspaces | 208 | // gaps inner|outer|<dir>|<side> <px> - sets defaults for workspaces |
145 | // gaps inner|outer current|all set|plus|minus <px> - runtime only | 209 | // gaps inner|outer|<dir>|<side> current|all set|plus|minus <px> - runtime only |
210 | // <dir> = horizontal|vertical | ||
211 | // <side> = top|right|bottom|left | ||
146 | struct cmd_results *cmd_gaps(int argc, char **argv) { | 212 | struct cmd_results *cmd_gaps(int argc, char **argv) { |
147 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); | 213 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); |
148 | if (error) { | 214 | if (error) { |
@@ -159,9 +225,8 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
159 | } | 225 | } |
160 | if (config_loading) { | 226 | if (config_loading) { |
161 | return cmd_results_new(CMD_INVALID, "gaps", | 227 | return cmd_results_new(CMD_INVALID, "gaps", |
162 | "Expected 'gaps inner|outer <px>'"); | 228 | "Expected %s", expected_defaults); |
163 | } | 229 | } |
164 | return cmd_results_new(CMD_INVALID, "gaps", | 230 | return cmd_results_new(CMD_INVALID, "gaps", |
165 | "Expected 'gaps inner|outer <px>' or " | 231 | "Expected %s or %s", expected_runtime, expected_defaults); |
166 | "'gaps inner|outer current|all set|plus|minus <px>'"); | ||
167 | } | 232 | } |
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) { | |||
22 | } | 22 | } |
23 | wsc->workspace = strdup(ws_name); | 23 | wsc->workspace = strdup(ws_name); |
24 | wsc->gaps_inner = INT_MIN; | 24 | wsc->gaps_inner = INT_MIN; |
25 | wsc->gaps_outer = INT_MIN; | 25 | wsc->gaps_outer.top = INT_MIN; |
26 | wsc->gaps_outer.right = INT_MIN; | ||
27 | wsc->gaps_outer.bottom = INT_MIN; | ||
28 | wsc->gaps_outer.left = INT_MIN; | ||
26 | list_add(config->workspace_configs, wsc); | 29 | list_add(config->workspace_configs, wsc); |
27 | return wsc; | 30 | return wsc; |
28 | } | 31 | } |
@@ -33,6 +36,89 @@ void free_workspace_config(struct workspace_config *wsc) { | |||
33 | free(wsc); | 36 | free(wsc); |
34 | } | 37 | } |
35 | 38 | ||
39 | static void prevent_invalid_outer_gaps(struct workspace_config *wsc) { | ||
40 | if (wsc->gaps_outer.top != INT_MIN && | ||
41 | wsc->gaps_outer.top < -wsc->gaps_inner) { | ||
42 | wsc->gaps_outer.top = -wsc->gaps_inner; | ||
43 | } | ||
44 | if (wsc->gaps_outer.right != INT_MIN && | ||
45 | wsc->gaps_outer.right < -wsc->gaps_inner) { | ||
46 | wsc->gaps_outer.right = -wsc->gaps_inner; | ||
47 | } | ||
48 | if (wsc->gaps_outer.bottom != INT_MIN && | ||
49 | wsc->gaps_outer.bottom < -wsc->gaps_inner) { | ||
50 | wsc->gaps_outer.bottom = -wsc->gaps_inner; | ||
51 | } | ||
52 | if (wsc->gaps_outer.left != INT_MIN && | ||
53 | wsc->gaps_outer.left < -wsc->gaps_inner) { | ||
54 | wsc->gaps_outer.left = -wsc->gaps_inner; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, | ||
59 | int gaps_location) { | ||
60 | const char *expected = "Expected 'workspace <name> gaps " | ||
61 | "inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; | ||
62 | struct cmd_results *error = NULL; | ||
63 | if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, | ||
64 | gaps_location + 3))) { | ||
65 | return error; | ||
66 | } | ||
67 | char *ws_name = join_args(argv, argc - 3); | ||
68 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | ||
69 | free(ws_name); | ||
70 | if (!wsc) { | ||
71 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
72 | "Unable to allocate workspace output"); | ||
73 | } | ||
74 | |||
75 | char *end; | ||
76 | int amount = strtol(argv[gaps_location + 2], &end, 10); | ||
77 | if (strlen(end)) { | ||
78 | free(end); | ||
79 | return cmd_results_new(CMD_FAILURE, "workspace gaps", expected); | ||
80 | } | ||
81 | |||
82 | bool valid = false; | ||
83 | char *type = argv[gaps_location + 1]; | ||
84 | if (!strcasecmp(type, "inner")) { | ||
85 | valid = true; | ||
86 | wsc->gaps_inner = (amount >= 0) ? amount : 0; | ||
87 | } else { | ||
88 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") | ||
89 | || !strcasecmp(type, "top")) { | ||
90 | valid = true; | ||
91 | wsc->gaps_outer.top = amount; | ||
92 | } | ||
93 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") | ||
94 | || !strcasecmp(type, "right")) { | ||
95 | valid = true; | ||
96 | wsc->gaps_outer.right = amount; | ||
97 | } | ||
98 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") | ||
99 | || !strcasecmp(type, "bottom")) { | ||
100 | valid = true; | ||
101 | wsc->gaps_outer.bottom = amount; | ||
102 | } | ||
103 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") | ||
104 | || !strcasecmp(type, "left")) { | ||
105 | valid = true; | ||
106 | wsc->gaps_outer.left = amount; | ||
107 | } | ||
108 | } | ||
109 | if (!valid) { | ||
110 | return cmd_results_new(CMD_INVALID, "workspace gaps", expected); | ||
111 | } | ||
112 | |||
113 | // Prevent invalid gaps configurations. | ||
114 | if (wsc->gaps_inner != INT_MIN && wsc->gaps_inner < 0) { | ||
115 | wsc->gaps_inner = 0; | ||
116 | } | ||
117 | prevent_invalid_outer_gaps(wsc); | ||
118 | |||
119 | return error; | ||
120 | } | ||
121 | |||
36 | struct cmd_results *cmd_workspace(int argc, char **argv) { | 122 | struct cmd_results *cmd_workspace(int argc, char **argv) { |
37 | struct cmd_results *error = NULL; | 123 | struct cmd_results *error = NULL; |
38 | if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { | 124 | if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { |
@@ -68,43 +154,9 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
68 | free(wsc->output); | 154 | free(wsc->output); |
69 | wsc->output = strdup(argv[output_location + 1]); | 155 | wsc->output = strdup(argv[output_location + 1]); |
70 | } else if (gaps_location >= 0) { | 156 | } else if (gaps_location >= 0) { |
71 | if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) { | 157 | if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { |
72 | return error; | 158 | return error; |
73 | } | 159 | } |
74 | char *ws_name = join_args(argv, argc - 3); | ||
75 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | ||
76 | free(ws_name); | ||
77 | if (!wsc) { | ||
78 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
79 | "Unable to allocate workspace output"); | ||
80 | } | ||
81 | int *prop = NULL; | ||
82 | if (strcasecmp(argv[gaps_location + 1], "inner") == 0) { | ||
83 | prop = &wsc->gaps_inner; | ||
84 | } else if (strcasecmp(argv[gaps_location + 1], "outer") == 0) { | ||
85 | prop = &wsc->gaps_outer; | ||
86 | } else { | ||
87 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
88 | "Expected 'workspace <ws> gaps inner|outer <px>'"); | ||
89 | } | ||
90 | char *end; | ||
91 | int val = strtol(argv[gaps_location + 2], &end, 10); | ||
92 | |||
93 | if (strlen(end)) { | ||
94 | free(end); | ||
95 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
96 | "Expected 'workspace <ws> gaps inner|outer <px>'"); | ||
97 | } | ||
98 | *prop = val; | ||
99 | |||
100 | // Prevent invalid gaps configurations. | ||
101 | if (wsc->gaps_inner < 0) { | ||
102 | wsc->gaps_inner = 0; | ||
103 | } | ||
104 | if (wsc->gaps_outer < -wsc->gaps_inner) { | ||
105 | wsc->gaps_outer = -wsc->gaps_inner; | ||
106 | } | ||
107 | |||
108 | } else { | 160 | } else { |
109 | if (config->reading || !config->active) { | 161 | if (config->reading || !config->active) { |
110 | return cmd_results_new(CMD_DEFER, "workspace", NULL); | 162 | return cmd_results_new(CMD_DEFER, "workspace", NULL); |
diff --git a/sway/config.c b/sway/config.c index 64653024..0fdd1723 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -234,7 +234,10 @@ static void config_defaults(struct sway_config *config) { | |||
234 | 234 | ||
235 | config->smart_gaps = false; | 235 | config->smart_gaps = false; |
236 | config->gaps_inner = 0; | 236 | config->gaps_inner = 0; |
237 | config->gaps_outer = 0; | 237 | config->gaps_outer.top = 0; |
238 | config->gaps_outer.right = 0; | ||
239 | config->gaps_outer.bottom = 0; | ||
240 | config->gaps_outer.left = 0; | ||
238 | 241 | ||
239 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; | 242 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; |
240 | 243 | ||
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 4a645837..3bf6233d 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -133,9 +133,12 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). | |||
133 | *fullscreen* | 133 | *fullscreen* |
134 | Toggles fullscreen for the focused view. | 134 | Toggles fullscreen for the focused view. |
135 | 135 | ||
136 | *gaps* inner|outer all|current set|plus|minus <amount> | 136 | *gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current |
137 | set|plus|minus <amount> | ||
137 | Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the | 138 | Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the |
138 | _current_ workspace. | 139 | _current_ workspace. _outer_ gaps can be altered per side with _top_, |
140 | _right_, _bottom_, and _left_ or per direction with _horizontal_ and | ||
141 | _vertical_. | ||
139 | 142 | ||
140 | *layout* default|splith|splitv|stacking|tabbed | 143 | *layout* default|splith|splitv|stacking|tabbed |
141 | Sets the layout mode of the focused container. | 144 | Sets the layout mode of the focused container. |
@@ -429,14 +432,16 @@ The default colors are: | |||
429 | _focus\_wrapping force_. This is only available for convenience. Please | 432 | _focus\_wrapping force_. This is only available for convenience. Please |
430 | use _focus\_wrapping_ instead when possible. | 433 | use _focus\_wrapping_ instead when possible. |
431 | 434 | ||
432 | *gaps* inner|outer <amount> | 435 | *gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount> |
433 | Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner | 436 | Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner |
434 | affects spacing around each view and outer affects the spacing around each | 437 | affects spacing around each view and outer affects the spacing around each |
435 | workspace. Outer gaps are in addition to inner gaps. To reduce or remove | 438 | workspace. Outer gaps are in addition to inner gaps. To reduce or remove |
436 | outer gaps, outer gaps can be set to a negative value. | 439 | outer gaps, outer gaps can be set to a negative value. _outer_ gaps can |
440 | also be specified per side with _top_, _right_, _bottom_, and _left_ or | ||
441 | per direction with _horizontal_ and _vertical_. | ||
437 | 442 | ||
438 | This affects new workspaces only, and is used when the workspace doesn't | 443 | This affects new workspaces only, and is used when the workspace doesn't |
439 | have its own gaps settings (see: workspace <ws> gaps inner|outer <amount>). | 444 | have its own gaps settings (see: workspace <ws> gaps ...). |
440 | 445 | ||
441 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps | 446 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps |
442 | Hides window borders adjacent to the screen edges. Default is _none_. | 447 | Hides window borders adjacent to the screen edges. Default is _none_. |
@@ -549,7 +554,8 @@ The default colors are: | |||
549 | *workspace* back\_and\_forth | 554 | *workspace* back\_and\_forth |
550 | Switches to the previously focused workspace. | 555 | Switches to the previously focused workspace. |
551 | 556 | ||
552 | *workspace* <name> gaps inner|outer <amount> | 557 | *workspace* <name> gaps inner|outer|horizontal|vertical|top|right|bottom|left |
558 | <amount> | ||
553 | Specifies that workspace _name_ should have the given gaps settings when it | 559 | Specifies that workspace _name_ should have the given gaps settings when it |
554 | is created. | 560 | is created. |
555 | 561 | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 03bb01d3..21b32649 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -191,7 +191,8 @@ static bool gaps_to_edge(struct sway_view *view) { | |||
191 | } | 191 | } |
192 | con = con->parent; | 192 | con = con->parent; |
193 | } | 193 | } |
194 | return view->container->workspace->current_gaps > 0; | 194 | struct side_gaps gaps = view->container->workspace->current_gaps; |
195 | return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0; | ||
195 | } | 196 | } |
196 | 197 | ||
197 | void view_autoconfigure(struct sway_view *view) { | 198 | void view_autoconfigure(struct sway_view *view) { |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 05cda5c0..93ce50de 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -49,6 +49,21 @@ struct sway_output *workspace_get_initial_output(const char *name) { | |||
49 | return focus->output; | 49 | return focus->output; |
50 | } | 50 | } |
51 | 51 | ||
52 | static void prevent_invalid_outer_gaps(struct sway_workspace *ws) { | ||
53 | if (ws->gaps_outer.top < -ws->gaps_inner) { | ||
54 | ws->gaps_outer.top = -ws->gaps_inner; | ||
55 | } | ||
56 | if (ws->gaps_outer.right < -ws->gaps_inner) { | ||
57 | ws->gaps_outer.right = -ws->gaps_inner; | ||
58 | } | ||
59 | if (ws->gaps_outer.bottom < -ws->gaps_inner) { | ||
60 | ws->gaps_outer.bottom = -ws->gaps_inner; | ||
61 | } | ||
62 | if (ws->gaps_outer.left < -ws->gaps_inner) { | ||
63 | ws->gaps_outer.left = -ws->gaps_inner; | ||
64 | } | ||
65 | } | ||
66 | |||
52 | struct sway_workspace *workspace_create(struct sway_output *output, | 67 | struct sway_workspace *workspace_create(struct sway_output *output, |
53 | const char *name) { | 68 | const char *name) { |
54 | if (output == NULL) { | 69 | if (output == NULL) { |
@@ -77,12 +92,24 @@ struct sway_workspace *workspace_create(struct sway_output *output, | |||
77 | if (name) { | 92 | if (name) { |
78 | struct workspace_config *wsc = workspace_find_config(name); | 93 | struct workspace_config *wsc = workspace_find_config(name); |
79 | if (wsc) { | 94 | if (wsc) { |
80 | if (wsc->gaps_outer != INT_MIN) { | 95 | if (wsc->gaps_outer.top != INT_MIN) { |
81 | ws->gaps_outer = wsc->gaps_outer; | 96 | ws->gaps_outer.top = wsc->gaps_outer.top; |
97 | } | ||
98 | if (wsc->gaps_outer.right != INT_MIN) { | ||
99 | ws->gaps_outer.right = wsc->gaps_outer.right; | ||
100 | } | ||
101 | if (wsc->gaps_outer.bottom != INT_MIN) { | ||
102 | ws->gaps_outer.bottom = wsc->gaps_outer.bottom; | ||
103 | } | ||
104 | if (wsc->gaps_outer.left != INT_MIN) { | ||
105 | ws->gaps_outer.left = wsc->gaps_outer.left; | ||
82 | } | 106 | } |
83 | if (wsc->gaps_inner != INT_MIN) { | 107 | if (wsc->gaps_inner != INT_MIN) { |
84 | ws->gaps_inner = wsc->gaps_inner; | 108 | ws->gaps_inner = wsc->gaps_inner; |
85 | } | 109 | } |
110 | // Since default outer gaps can be smaller than the negation of | ||
111 | // workspace specific inner gaps, check outer gaps again | ||
112 | prevent_invalid_outer_gaps(ws); | ||
86 | } | 113 | } |
87 | } | 114 | } |
88 | 115 | ||
@@ -615,19 +642,25 @@ void workspace_insert_tiling(struct sway_workspace *workspace, | |||
615 | } | 642 | } |
616 | 643 | ||
617 | void workspace_remove_gaps(struct sway_workspace *ws) { | 644 | void workspace_remove_gaps(struct sway_workspace *ws) { |
618 | if (ws->current_gaps == 0) { | 645 | if (ws->current_gaps.top == 0 && ws->current_gaps.right == 0 && |
646 | ws->current_gaps.bottom == 0 && ws->current_gaps.left == 0) { | ||
619 | return; | 647 | return; |
620 | } | 648 | } |
621 | 649 | ||
622 | ws->width += ws->current_gaps * 2; | 650 | ws->width += ws->current_gaps.left + ws->current_gaps.right; |
623 | ws->height += ws->current_gaps * 2; | 651 | ws->height += ws->current_gaps.top + ws->current_gaps.bottom; |
624 | ws->x -= ws->current_gaps; | 652 | ws->x -= ws->current_gaps.left; |
625 | ws->y -= ws->current_gaps; | 653 | ws->y -= ws->current_gaps.top; |
626 | ws->current_gaps = 0; | 654 | |
655 | ws->current_gaps.top = 0; | ||
656 | ws->current_gaps.right = 0; | ||
657 | ws->current_gaps.bottom = 0; | ||
658 | ws->current_gaps.left = 0; | ||
627 | } | 659 | } |
628 | 660 | ||
629 | void workspace_add_gaps(struct sway_workspace *ws) { | 661 | void workspace_add_gaps(struct sway_workspace *ws) { |
630 | if (ws->current_gaps > 0) { | 662 | if (ws->current_gaps.top > 0 || ws->current_gaps.right > 0 || |
663 | ws->current_gaps.bottom > 0 || ws->current_gaps.left > 0) { | ||
631 | return; | 664 | return; |
632 | } | 665 | } |
633 | if (config->smart_gaps) { | 666 | if (config->smart_gaps) { |
@@ -643,18 +676,20 @@ void workspace_add_gaps(struct sway_workspace *ws) { | |||
643 | } | 676 | } |
644 | 677 | ||
645 | ws->current_gaps = ws->gaps_outer; | 678 | ws->current_gaps = ws->gaps_outer; |
646 | |||
647 | if (ws->layout == L_TABBED || ws->layout == L_STACKED) { | 679 | if (ws->layout == L_TABBED || ws->layout == L_STACKED) { |
648 | // We have to add inner gaps for this, because children of tabbed and | 680 | // We have to add inner gaps for this, because children of tabbed and |
649 | // stacked containers don't apply their own gaps - they assume the | 681 | // stacked containers don't apply their own gaps - they assume the |
650 | // tabbed/stacked container is using gaps. | 682 | // tabbed/stacked container is using gaps. |
651 | ws->current_gaps += ws->gaps_inner; | 683 | ws->current_gaps.top += ws->gaps_inner; |
684 | ws->current_gaps.right += ws->gaps_inner; | ||
685 | ws->current_gaps.bottom += ws->gaps_inner; | ||
686 | ws->current_gaps.left += ws->gaps_inner; | ||
652 | } | 687 | } |
653 | 688 | ||
654 | ws->x += ws->current_gaps; | 689 | ws->x += ws->current_gaps.left; |
655 | ws->y += ws->current_gaps; | 690 | ws->y += ws->current_gaps.top; |
656 | ws->width -= 2 * ws->current_gaps; | 691 | ws->width -= ws->current_gaps.left + ws->current_gaps.right; |
657 | ws->height -= 2 * ws->current_gaps; | 692 | ws->height -= ws->current_gaps.top + ws->current_gaps.bottom; |
658 | } | 693 | } |
659 | 694 | ||
660 | struct sway_container *workspace_split(struct sway_workspace *workspace, | 695 | struct sway_container *workspace_split(struct sway_workspace *workspace, |