diff options
-rw-r--r-- | include/sway/config.h | 14 | ||||
-rw-r--r-- | include/sway/tree/container.h | 7 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 4 | ||||
-rw-r--r-- | sway/commands/gaps.c | 151 | ||||
-rw-r--r-- | sway/commands/resize.c | 47 | ||||
-rw-r--r-- | sway/commands/swap.c | 2 | ||||
-rw-r--r-- | sway/commands/workspace.c | 124 | ||||
-rw-r--r-- | sway/config.c | 5 | ||||
-rw-r--r-- | sway/sway.5.scd | 46 | ||||
-rw-r--r-- | sway/tree/container.c | 34 | ||||
-rw-r--r-- | sway/tree/view.c | 14 | ||||
-rw-r--r-- | sway/tree/workspace.c | 65 |
12 files changed, 363 insertions, 150 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 0912bc73..cd56c3dc 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -168,6 +168,16 @@ struct output_config { | |||
168 | }; | 168 | }; |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * Stores size of gaps for each side | ||
172 | */ | ||
173 | struct side_gaps { | ||
174 | int top; | ||
175 | int right; | ||
176 | int bottom; | ||
177 | int left; | ||
178 | }; | ||
179 | |||
180 | /** | ||
171 | * Stores configuration for a workspace, regardless of whether the workspace | 181 | * Stores configuration for a workspace, regardless of whether the workspace |
172 | * exists. | 182 | * exists. |
173 | */ | 183 | */ |
@@ -175,7 +185,7 @@ struct workspace_config { | |||
175 | char *workspace; | 185 | char *workspace; |
176 | char *output; | 186 | char *output; |
177 | int gaps_inner; | 187 | int gaps_inner; |
178 | int gaps_outer; | 188 | struct side_gaps gaps_outer; |
179 | }; | 189 | }; |
180 | 190 | ||
181 | struct bar_config { | 191 | struct bar_config { |
@@ -398,7 +408,7 @@ struct sway_config { | |||
398 | 408 | ||
399 | bool smart_gaps; | 409 | bool smart_gaps; |
400 | int gaps_inner; | 410 | int gaps_inner; |
401 | int gaps_outer; | 411 | struct side_gaps gaps_outer; |
402 | 412 | ||
403 | list_t *config_chain; | 413 | list_t *config_chain; |
404 | const char *current_config_path; | 414 | const char *current_config_path; |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 4366a010..d3155eb3 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -104,7 +104,12 @@ struct sway_container { | |||
104 | bool border_right; | 104 | bool border_right; |
105 | 105 | ||
106 | // The gaps currently applied to the container. | 106 | // The gaps currently applied to the container. |
107 | double current_gaps; | 107 | struct { |
108 | int top; | ||
109 | int right; | ||
110 | int bottom; | ||
111 | int left; | ||
112 | } current_gaps; | ||
108 | 113 | ||
109 | struct sway_workspace *workspace; // NULL when hidden in the scratchpad | 114 | struct sway_workspace *workspace; // NULL when hidden in the scratchpad |
110 | struct sway_container *parent; // NULL if container in root of workspace | 115 | struct sway_container *parent; // NULL if container in root of workspace |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index b5ae92f3..7abfbff1 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -32,9 +32,9 @@ struct sway_workspace { | |||
32 | enum sway_container_layout layout; | 32 | enum sway_container_layout layout; |
33 | enum sway_container_layout prev_split_layout; | 33 | enum sway_container_layout prev_split_layout; |
34 | 34 | ||
35 | int current_gaps; | 35 | struct side_gaps current_gaps; |
36 | int gaps_inner; | 36 | int gaps_inner; |
37 | int gaps_outer; | 37 | struct side_gaps gaps_outer; |
38 | 38 | ||
39 | struct sway_output *output; // NULL if no outputs are connected | 39 | struct sway_output *output; // NULL if no outputs are connected |
40 | list_t *floating; // struct sway_container | 40 | list_t *floating; // struct sway_container |
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/resize.c b/sway/commands/resize.c index 8635b309..a82bec20 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c | |||
@@ -499,7 +499,7 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, | |||
499 | } | 499 | } |
500 | if (height->unit == RESIZE_UNIT_PX) { | 500 | if (height->unit == RESIZE_UNIT_PX) { |
501 | resize_tiled(con, height->amount - con->height, | 501 | resize_tiled(con, height->amount - con->height, |
502 | RESIZE_AXIS_HORIZONTAL); | 502 | RESIZE_AXIS_VERTICAL); |
503 | } | 503 | } |
504 | } | 504 | } |
505 | 505 | ||
@@ -538,34 +538,45 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, | |||
538 | /** | 538 | /** |
539 | * resize set <args> | 539 | * resize set <args> |
540 | * | 540 | * |
541 | * args: <width> [px|ppt] <height> [px|ppt] | 541 | * args: [width] <width> [px|ppt] |
542 | * : height <height> [px|ppt] | ||
543 | * : [width] <width> [px|ppt] [height] <height> [px|ppt] | ||
542 | */ | 544 | */ |
543 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { | 545 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { |
544 | struct cmd_results *error; | 546 | struct cmd_results *error; |
545 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { | 547 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 1))) { |
546 | return error; | 548 | return error; |
547 | } | 549 | } |
548 | const char *usage = "Expected 'resize set <width> <height>'"; | 550 | const char *usage = "Expected 'resize set [width] <width> [px|ppt]' or " |
551 | "'resize set height <height> [px|ppt]' or " | ||
552 | "'resize set [width] <width> [px|ppt] [height] <height> [px|ppt]'"; | ||
549 | 553 | ||
550 | // Width | 554 | // Width |
551 | struct resize_amount width; | 555 | struct resize_amount width = {0}; |
552 | int num_consumed_args = parse_resize_amount(argc, argv, &width); | 556 | if (argc >= 2 && !strcmp(argv[0], "width") && strcmp(argv[1], "height")) { |
553 | argc -= num_consumed_args; | 557 | argc--; argv++; |
554 | argv += num_consumed_args; | ||
555 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
556 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
557 | } | 558 | } |
558 | if (!argc) { | 559 | if (strcmp(argv[0], "height")) { |
559 | return cmd_results_new(CMD_INVALID, "resize", usage); | 560 | int num_consumed_args = parse_resize_amount(argc, argv, &width); |
561 | argc -= num_consumed_args; | ||
562 | argv += num_consumed_args; | ||
563 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
564 | return cmd_results_new(CMD_INVALID, "resize set", usage); | ||
565 | } | ||
560 | } | 566 | } |
561 | 567 | ||
562 | // Height | 568 | // Height |
563 | struct resize_amount height; | 569 | struct resize_amount height = {0}; |
564 | num_consumed_args = parse_resize_amount(argc, argv, &height); | 570 | if (argc) { |
565 | argc -= num_consumed_args; | 571 | if (argc >= 2 && !strcmp(argv[0], "height")) { |
566 | argv += num_consumed_args; | 572 | argc--; argv++; |
567 | if (height.unit == RESIZE_UNIT_INVALID) { | 573 | } |
568 | return cmd_results_new(CMD_INVALID, "resize", usage); | 574 | int num_consumed_args = parse_resize_amount(argc, argv, &height); |
575 | argc -= num_consumed_args; | ||
576 | argv += num_consumed_args; | ||
577 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
578 | return cmd_results_new(CMD_INVALID, "resize set", usage); | ||
579 | } | ||
569 | } | 580 | } |
570 | 581 | ||
571 | // If 0, don't resize that dimension | 582 | // If 0, don't resize that dimension |
diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 23e8d583..99051395 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c | |||
@@ -181,7 +181,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) { | |||
181 | } | 181 | } |
182 | 182 | ||
183 | struct sway_container *current = config->handler_context.container; | 183 | struct sway_container *current = config->handler_context.container; |
184 | struct sway_container *other; | 184 | struct sway_container *other = NULL; |
185 | 185 | ||
186 | char *value = join_args(argv + 3, argc - 3); | 186 | char *value = join_args(argv + 3, argc - 3); |
187 | if (strcasecmp(argv[2], "id") == 0) { | 187 | if (strcasecmp(argv[2], "id") == 0) { |
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 2a2841a7..c1320acf 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..8f6b35f1 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. |
@@ -207,11 +210,23 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). | |||
207 | percentage points. If the units are omitted, floating containers are resized | 210 | percentage points. If the units are omitted, floating containers are resized |
208 | in px and tiled containers by ppt. _amount_ will default to 10 if omitted. | 211 | in px and tiled containers by ppt. _amount_ will default to 10 if omitted. |
209 | 212 | ||
210 | *resize set* <width> [px|ppt] <height> [px|ppt] | 213 | *resize set* height <height> [px|ppt] |
211 | Sets the width and height of the currently focused container to _width_ and | 214 | Sets the height of the container to _height_, specified in pixels or |
212 | _height_, specified in pixels or percentage points. If the units are | 215 | percentage points. If the units are omitted, floating containers are |
213 | omitted, floating containers are resized in px and tiled containers by ppt. | 216 | resized in px and tiled containers by ppt. If _height_ is 0, the container |
214 | If _width_ or _height_ is 0, no resize is done on that axis. | 217 | will not be resized. |
218 | |||
219 | *resize set* [width] <width> [px|ppt] | ||
220 | Sets the width of the container to _width_, specified in pixels or | ||
221 | percentage points. If the units are omitted, floating containers are | ||
222 | resized in px and tiled containers by ppt. If _width_ is 0, the container | ||
223 | will not be resized. | ||
224 | |||
225 | *resize set* [width] <width> [px|ppt] [height] <height> [px|ppt] | ||
226 | Sets the width and height of the container to _width_ and _height_, | ||
227 | specified in pixels or percentage points. If the units are omitted, | ||
228 | floating containers are resized in px and tiled containers by ppt. If | ||
229 | _width_ or _height_ is 0, the container will not be resized on that axis. | ||
215 | 230 | ||
216 | *scratchpad show* | 231 | *scratchpad show* |
217 | Shows a window from the scratchpad. Repeatedly using this command will | 232 | Shows a window from the scratchpad. Repeatedly using this command will |
@@ -404,8 +419,10 @@ The default colors are: | |||
404 | specified direction while holding the floating modifier. Resets the | 419 | specified direction while holding the floating modifier. Resets the |
405 | command, when given no arguments. | 420 | command, when given no arguments. |
406 | 421 | ||
407 | *focus\_follows\_mouse* yes|no | 422 | *focus\_follows\_mouse* yes|no|always |
408 | If set to _yes_, moving your mouse over a window will focus that window. | 423 | If set to _yes_, moving your mouse over a window will focus that window. If |
424 | set to _always_, the window under the cursor will always be focused, even | ||
425 | after switching between workspaces. | ||
409 | 426 | ||
410 | *focus\_wrapping* yes|no|force | 427 | *focus\_wrapping* yes|no|force |
411 | This option determines what to do when attempting to focus over the edge | 428 | This option determines what to do when attempting to focus over the edge |
@@ -429,14 +446,16 @@ The default colors are: | |||
429 | _focus\_wrapping force_. This is only available for convenience. Please | 446 | _focus\_wrapping force_. This is only available for convenience. Please |
430 | use _focus\_wrapping_ instead when possible. | 447 | use _focus\_wrapping_ instead when possible. |
431 | 448 | ||
432 | *gaps* inner|outer <amount> | 449 | *gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount> |
433 | Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner | 450 | 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 | 451 | 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 | 452 | 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. | 453 | outer gaps, outer gaps can be set to a negative value. _outer_ gaps can |
454 | also be specified per side with _top_, _right_, _bottom_, and _left_ or | ||
455 | per direction with _horizontal_ and _vertical_. | ||
437 | 456 | ||
438 | This affects new workspaces only, and is used when the workspace doesn't | 457 | 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>). | 458 | have its own gaps settings (see: workspace <ws> gaps ...). |
440 | 459 | ||
441 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps | 460 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps |
442 | Hides window borders adjacent to the screen edges. Default is _none_. | 461 | Hides window borders adjacent to the screen edges. Default is _none_. |
@@ -549,7 +568,8 @@ The default colors are: | |||
549 | *workspace* back\_and\_forth | 568 | *workspace* back\_and\_forth |
550 | Switches to the previously focused workspace. | 569 | Switches to the previously focused workspace. |
551 | 570 | ||
552 | *workspace* <name> gaps inner|outer <amount> | 571 | *workspace* <name> gaps inner|outer|horizontal|vertical|top|right|bottom|left |
572 | <amount> | ||
553 | Specifies that workspace _name_ should have the given gaps settings when it | 573 | Specifies that workspace _name_ should have the given gaps settings when it |
554 | is created. | 574 | is created. |
555 | 575 | ||
diff --git a/sway/tree/container.c b/sway/tree/container.c index 458ed7ff..3740cb53 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -1009,19 +1009,25 @@ void container_discover_outputs(struct sway_container *con) { | |||
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | void container_remove_gaps(struct sway_container *c) { | 1011 | void container_remove_gaps(struct sway_container *c) { |
1012 | if (c->current_gaps == 0) { | 1012 | if (c->current_gaps.top == 0 && c->current_gaps.right == 0 && |
1013 | c->current_gaps.bottom == 0 && c->current_gaps.left == 0) { | ||
1013 | return; | 1014 | return; |
1014 | } | 1015 | } |
1015 | 1016 | ||
1016 | c->width += c->current_gaps * 2; | 1017 | c->width += c->current_gaps.left + c->current_gaps.right; |
1017 | c->height += c->current_gaps * 2; | 1018 | c->height += c->current_gaps.top + c->current_gaps.bottom; |
1018 | c->x -= c->current_gaps; | 1019 | c->x -= c->current_gaps.left; |
1019 | c->y -= c->current_gaps; | 1020 | c->y -= c->current_gaps.top; |
1020 | c->current_gaps = 0; | 1021 | |
1022 | c->current_gaps.top = 0; | ||
1023 | c->current_gaps.right = 0; | ||
1024 | c->current_gaps.bottom = 0; | ||
1025 | c->current_gaps.left = 0; | ||
1021 | } | 1026 | } |
1022 | 1027 | ||
1023 | void container_add_gaps(struct sway_container *c) { | 1028 | void container_add_gaps(struct sway_container *c) { |
1024 | if (c->current_gaps > 0) { | 1029 | if (c->current_gaps.top > 0 || c->current_gaps.right > 0 || |
1030 | c->current_gaps.bottom > 0 || c->current_gaps.left > 0) { | ||
1025 | return; | 1031 | return; |
1026 | } | 1032 | } |
1027 | // Linear containers don't have gaps because it'd create double gaps | 1033 | // Linear containers don't have gaps because it'd create double gaps |
@@ -1054,11 +1060,15 @@ void container_add_gaps(struct sway_container *c) { | |||
1054 | 1060 | ||
1055 | struct sway_workspace *ws = c->workspace; | 1061 | struct sway_workspace *ws = c->workspace; |
1056 | 1062 | ||
1057 | c->current_gaps = ws->gaps_inner; | 1063 | c->current_gaps.top = c->y == ws->y ? ws->gaps_inner : 0; |
1058 | c->x += c->current_gaps; | 1064 | c->current_gaps.right = ws->gaps_inner; |
1059 | c->y += c->current_gaps; | 1065 | c->current_gaps.bottom = ws->gaps_inner; |
1060 | c->width -= 2 * c->current_gaps; | 1066 | c->current_gaps.left = c->x == ws->x ? ws->gaps_inner : 0; |
1061 | c->height -= 2 * c->current_gaps; | 1067 | |
1068 | c->x += c->current_gaps.left; | ||
1069 | c->y += c->current_gaps.top; | ||
1070 | c->width -= c->current_gaps.left + c->current_gaps.right; | ||
1071 | c->height -= c->current_gaps.top + c->current_gaps.bottom; | ||
1062 | } | 1072 | } |
1063 | 1073 | ||
1064 | enum sway_container_layout container_parent_layout(struct sway_container *con) { | 1074 | enum sway_container_layout container_parent_layout(struct sway_container *con) { |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 1aa59e68..21b32649 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -185,12 +185,14 @@ bool view_is_only_visible(struct sway_view *view) { | |||
185 | static bool gaps_to_edge(struct sway_view *view) { | 185 | static bool gaps_to_edge(struct sway_view *view) { |
186 | struct sway_container *con = view->container; | 186 | struct sway_container *con = view->container; |
187 | while (con) { | 187 | while (con) { |
188 | if (con->current_gaps > 0) { | 188 | if (con->current_gaps.top > 0 || con->current_gaps.right > 0 || |
189 | con->current_gaps.bottom > 0 || con->current_gaps.left > 0) { | ||
189 | return true; | 190 | return true; |
190 | } | 191 | } |
191 | con = con->parent; | 192 | con = con->parent; |
192 | } | 193 | } |
193 | 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; | ||
194 | } | 196 | } |
195 | 197 | ||
196 | void view_autoconfigure(struct sway_view *view) { | 198 | void view_autoconfigure(struct sway_view *view) { |
@@ -222,15 +224,15 @@ void view_autoconfigure(struct sway_view *view) { | |||
222 | if (config->hide_edge_borders == E_BOTH | 224 | if (config->hide_edge_borders == E_BOTH |
223 | || config->hide_edge_borders == E_VERTICAL | 225 | || config->hide_edge_borders == E_VERTICAL |
224 | || (smart && !other_views && no_gaps)) { | 226 | || (smart && !other_views && no_gaps)) { |
225 | con->border_left = con->x - con->current_gaps != ws->x; | 227 | con->border_left = con->x - con->current_gaps.left != ws->x; |
226 | int right_x = con->x + con->width + con->current_gaps; | 228 | int right_x = con->x + con->width + con->current_gaps.right; |
227 | con->border_right = right_x != ws->x + ws->width; | 229 | con->border_right = right_x != ws->x + ws->width; |
228 | } | 230 | } |
229 | if (config->hide_edge_borders == E_BOTH | 231 | if (config->hide_edge_borders == E_BOTH |
230 | || config->hide_edge_borders == E_HORIZONTAL | 232 | || config->hide_edge_borders == E_HORIZONTAL |
231 | || (smart && !other_views && no_gaps)) { | 233 | || (smart && !other_views && no_gaps)) { |
232 | con->border_top = con->y - con->current_gaps != ws->y; | 234 | con->border_top = con->y - con->current_gaps.top != ws->y; |
233 | int bottom_y = con->y + con->height + con->current_gaps; | 235 | int bottom_y = con->y + con->height + con->current_gaps.bottom; |
234 | con->border_bottom = bottom_y != ws->y + ws->height; | 236 | con->border_bottom = bottom_y != ws->y + ws->height; |
235 | } | 237 | } |
236 | 238 | ||
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, |