aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/arrange.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-26 10:16:49 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-28 23:50:41 +1000
commitf5b9815128b6c000bb5d47c339480fa481a5e99d (patch)
tree24b533a7579dde0f65392afbba5f3982fe5e79c6 /sway/tree/arrange.c
parentMerge pull request #2523 from RedSoxFan/fix-floating-drag-outputs (diff)
downloadsway-f5b9815128b6c000bb5d47c339480fa481a5e99d.tar.gz
sway-f5b9815128b6c000bb5d47c339480fa481a5e99d.tar.zst
sway-f5b9815128b6c000bb5d47c339480fa481a5e99d.zip
Prepare arrange code for type safe arguments
This commit changes the arrange code in a way that will support type safe arguments. The arrange_output et al functions are now public, however I opted not to use them directly yet. I've kept the generic arrange_windows there for convenience until type safety is fully implemented. This means this patch has much less risk of breaking things as it would otherwise. To be type safe, arrange_children_of cannot exist in its previous form because the thing passed to it could be either a workspace or a container. So it's now renamed to arrange_children and accepts a list_t, as well as the parent layout and parent's box. There was some code which checked the grandparent's layout to see if it was tabbed or stacked and adjusted the Y offset of the grandchild accordingly. Accessing the grandparent layout isn't easy when using type safe arguments, and it seemed odd to even need to do this. I determined that this was needed because a child of a tabbed container would have a swayc Y matching the top of the tab bar. I've changed this so a child of a tabbed container will have a swayc Y matching the bottom of the tab bar, which means we don't need to access the grandparent layout. Some tweaks to the rendering and autoconfigure code have been made to implement this, and the container_at code appears to work without needing any changes. arrange_children_of (now arrange_children) would check if the parent had gaps and would copy them to the child, effectively making the workspace's gaps recurse into all children. We can't do this any more without passing has_gaps, gaps_inner and gaps_outer as arguments to arrange_children, so I've changed the add_gaps function to retrieve it from the workspace directly. apply_tabbed_or_stacked_layout has been split into two functions, as it had different logic depending on the layout. Lastly, arrange.h had an unnecessary include of transaction.h. I've removed it, which means I've had to add it to several other files.
Diffstat (limited to 'sway/tree/arrange.c')
-rw-r--r--sway/tree/arrange.c197
1 files changed, 90 insertions, 107 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 8d67116a..92f20fcc 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -13,27 +13,18 @@
13#include "list.h" 13#include "list.h"
14#include "log.h" 14#include "log.h"
15 15
16static void apply_horiz_layout(struct sway_container *parent) { 16static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
17 size_t num_children = parent->children->length; 17 if (!children->length) {
18 if (!num_children) {
19 return; 18 return;
20 } 19 }
21 size_t parent_offset = 0;
22 if (parent->parent->layout == L_TABBED) {
23 parent_offset = container_titlebar_height();
24 } else if (parent->parent->layout == L_STACKED) {
25 parent_offset = container_titlebar_height() *
26 parent->parent->children->length;
27 }
28 size_t parent_height = parent->height - parent_offset;
29 20
30 // Calculate total width of children 21 // Calculate total width of children
31 double total_width = 0; 22 double total_width = 0;
32 for (size_t i = 0; i < num_children; ++i) { 23 for (int i = 0; i < children->length; ++i) {
33 struct sway_container *child = parent->children->items[i]; 24 struct sway_container *child = children->items[i];
34 if (child->width <= 0) { 25 if (child->width <= 0) {
35 if (num_children > 1) { 26 if (children->length > 1) {
36 child->width = parent->width / (num_children - 1); 27 child->width = parent->width / (children->length - 1);
37 } else { 28 } else {
38 child->width = parent->width; 29 child->width = parent->width;
39 } 30 }
@@ -46,63 +37,48 @@ static void apply_horiz_layout(struct sway_container *parent) {
46 // Resize windows 37 // Resize windows
47 wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent); 38 wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent);
48 double child_x = parent->x; 39 double child_x = parent->x;
49 for (size_t i = 0; i < num_children; ++i) { 40 for (int i = 0; i < children->length; ++i) {
50 struct sway_container *child = parent->children->items[i]; 41 struct sway_container *child = children->items[i];
51 wlr_log(WLR_DEBUG,
52 "Calculating arrangement for %p:%d (will scale %f by %f)",
53 child, child->type, child->width, scale);
54 child->x = child_x; 42 child->x = child_x;
55 child->y = parent->y + parent_offset; 43 child->y = parent->y;
56 child->width = floor(child->width * scale); 44 child->width = floor(child->width * scale);
57 child->height = parent_height; 45 child->height = parent->height;
58 child_x += child->width; 46 child_x += child->width;
59 47
60 // Make last child use remaining width of parent 48 // Make last child use remaining width of parent
61 if (i == num_children - 1) { 49 if (i == children->length - 1) {
62 child->width = parent->x + parent->width - child->x; 50 child->width = parent->x + parent->width - child->x;
63 } 51 }
64 container_add_gaps(child); 52 container_add_gaps(child);
65 } 53 }
66} 54}
67 55
68static void apply_vert_layout(struct sway_container *parent) { 56static void apply_vert_layout(list_t *children, struct wlr_box *parent) {
69 size_t num_children = parent->children->length; 57 if (!children->length) {
70 if (!num_children) {
71 return; 58 return;
72 } 59 }
73 size_t parent_offset = 0;
74 if (parent->parent->layout == L_TABBED) {
75 parent_offset = container_titlebar_height();
76 } else if (parent->parent->layout == L_STACKED) {
77 parent_offset =
78 container_titlebar_height() * parent->parent->children->length;
79 }
80 size_t parent_height = parent->height + parent_offset;
81 60
82 // Calculate total height of children 61 // Calculate total height of children
83 double total_height = 0; 62 double total_height = 0;
84 for (size_t i = 0; i < num_children; ++i) { 63 for (int i = 0; i < children->length; ++i) {
85 struct sway_container *child = parent->children->items[i]; 64 struct sway_container *child = children->items[i];
86 if (child->height <= 0) { 65 if (child->height <= 0) {
87 if (num_children > 1) { 66 if (children->length > 1) {
88 child->height = parent_height / (num_children - 1); 67 child->height = parent->height / (children->length - 1);
89 } else { 68 } else {
90 child->height = parent_height; 69 child->height = parent->height;
91 } 70 }
92 } 71 }
93 container_remove_gaps(child); 72 container_remove_gaps(child);
94 total_height += child->height; 73 total_height += child->height;
95 } 74 }
96 double scale = parent_height / total_height; 75 double scale = parent->height / total_height;
97 76
98 // Resize 77 // Resize
99 wlr_log(WLR_DEBUG, "Arranging %p vertically", parent); 78 wlr_log(WLR_DEBUG, "Arranging %p vertically", parent);
100 double child_y = parent->y + parent_offset; 79 double child_y = parent->y;
101 for (size_t i = 0; i < num_children; ++i) { 80 for (int i = 0; i < children->length; ++i) {
102 struct sway_container *child = parent->children->items[i]; 81 struct sway_container *child = children->items[i];
103 wlr_log(WLR_DEBUG,
104 "Calculating arrangement for %p:%d (will scale %f by %f)",
105 child, child->type, child->height, scale);
106 child->x = parent->x; 82 child->x = parent->x;
107 child->y = child_y; 83 child->y = child_y;
108 child->width = parent->width; 84 child->width = parent->width;
@@ -110,28 +86,21 @@ static void apply_vert_layout(struct sway_container *parent) {
110 child_y += child->height; 86 child_y += child->height;
111 87
112 // Make last child use remaining height of parent 88 // Make last child use remaining height of parent
113 if (i == num_children - 1) { 89 if (i == children->length - 1) {
114 child->height = 90 child->height = parent->y + parent->height - child->y;
115 parent->y + parent_offset + parent_height - child->y;
116 } 91 }
117 container_add_gaps(child); 92 container_add_gaps(child);
118 } 93 }
119} 94}
120 95
121static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { 96static void apply_tabbed_layout(list_t *children, struct wlr_box *parent) {
122 if (!parent->children->length) { 97 if (!children->length) {
123 return; 98 return;
124 } 99 }
125 size_t parent_offset = 0; 100 size_t parent_offset = container_titlebar_height();
126 if (parent->parent->layout == L_TABBED) {
127 parent_offset = container_titlebar_height();
128 } else if (parent->parent->layout == L_STACKED) {
129 parent_offset =
130 container_titlebar_height() * parent->parent->children->length;
131 }
132 size_t parent_height = parent->height - parent_offset; 101 size_t parent_height = parent->height - parent_offset;
133 for (int i = 0; i < parent->children->length; ++i) { 102 for (int i = 0; i < children->length; ++i) {
134 struct sway_container *child = parent->children->items[i]; 103 struct sway_container *child = children->items[i];
135 container_remove_gaps(child); 104 container_remove_gaps(child);
136 child->x = parent->x; 105 child->x = parent->x;
137 child->y = parent->y + parent_offset; 106 child->y = parent->y + parent_offset;
@@ -141,65 +110,83 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) {
141 } 110 }
142} 111}
143 112
144static void arrange_children_of(struct sway_container *parent); 113static void apply_stacked_layout(list_t *children, struct wlr_box *parent) {
114 if (!children->length) {
115 return;
116 }
117 size_t parent_offset = container_titlebar_height() * children->length;
118 size_t parent_height = parent->height - parent_offset;
119 for (int i = 0; i < children->length; ++i) {
120 struct sway_container *child = children->items[i];
121 container_remove_gaps(child);
122 child->x = parent->x;
123 child->y = parent->y + parent_offset;
124 child->width = parent->width;
125 child->height = parent_height;
126 container_add_gaps(child);
127 }
128}
145 129
146static void arrange_floating(list_t *floating) { 130static void arrange_floating(list_t *floating) {
147 for (int i = 0; i < floating->length; ++i) { 131 for (int i = 0; i < floating->length; ++i) {
148 struct sway_container *floater = floating->items[i]; 132 struct sway_container *floater = floating->items[i];
149 if (floater->type == C_VIEW) { 133 arrange_container(floater);
150 view_autoconfigure(floater->sway_view);
151 } else {
152 arrange_children_of(floater);
153 }
154 container_set_dirty(floater);
155 } 134 }
156} 135}
157 136
158static void arrange_children_of(struct sway_container *parent) { 137static void arrange_children(list_t *children,
159 if (config->reloading) { 138 enum sway_container_layout layout, struct wlr_box *parent) {
160 return;
161 }
162 wlr_log(WLR_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
163 parent->name, parent->width, parent->height, parent->x, parent->y);
164
165 // Calculate x, y, width and height of children 139 // Calculate x, y, width and height of children
166 switch (parent->layout) { 140 switch (layout) {
167 case L_HORIZ: 141 case L_HORIZ:
168 apply_horiz_layout(parent); 142 apply_horiz_layout(children, parent);
169 break; 143 break;
170 case L_VERT: 144 case L_VERT:
171 apply_vert_layout(parent); 145 apply_vert_layout(children, parent);
172 break; 146 break;
173 case L_TABBED: 147 case L_TABBED:
148 apply_tabbed_layout(children, parent);
149 break;
174 case L_STACKED: 150 case L_STACKED:
175 apply_tabbed_or_stacked_layout(parent); 151 apply_stacked_layout(children, parent);
176 break; 152 break;
177 case L_NONE: 153 case L_NONE:
178 apply_horiz_layout(parent); 154 apply_horiz_layout(children, parent);
179 break; 155 break;
180 } 156 }
181 157
182 // Recurse into child containers 158 // Recurse into child containers
183 for (int i = 0; i < parent->children->length; ++i) { 159 for (int i = 0; i < children->length; ++i) {
184 struct sway_container *child = parent->children->items[i]; 160 struct sway_container *child = children->items[i];
185 if (parent->has_gaps && !child->has_gaps) { 161 arrange_container(child);
186 child->has_gaps = true; 162 }
187 child->gaps_inner = parent->gaps_inner; 163}
188 child->gaps_outer = parent->gaps_outer; 164
189 } 165void arrange_container(struct sway_container *container) {
190 if (child->type == C_VIEW) { 166 if (config->reloading) {
191 view_autoconfigure(child->sway_view); 167 return;
192 } else { 168 }
193 arrange_children_of(child); 169 if (container->type == C_VIEW) {
194 } 170 view_autoconfigure(container->sway_view);
195 container_set_dirty(child); 171 container_set_dirty(container);
172 return;
196 } 173 }
174 if (!sway_assert(container->type == C_CONTAINER, "Expected a container")) {
175 return;
176 }
177 struct wlr_box box;
178 container_get_box(container, &box);
179 arrange_children(container->children, container->layout, &box);
180 container_set_dirty(container);
197} 181}
198 182
199static void arrange_workspace(struct sway_container *workspace) { 183void arrange_workspace(struct sway_container *workspace) {
200 if (config->reloading) { 184 if (config->reloading) {
201 return; 185 return;
202 } 186 }
187 if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
188 return;
189 }
203 struct sway_container *output = workspace->parent; 190 struct sway_container *output = workspace->parent;
204 struct wlr_box *area = &output->sway_output->usable_area; 191 struct wlr_box *area = &output->sway_output->usable_area;
205 wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d", 192 wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d",
@@ -241,22 +228,22 @@ static void arrange_workspace(struct sway_container *workspace) {
241 fs->y = workspace->parent->y; 228 fs->y = workspace->parent->y;
242 fs->width = workspace->parent->width; 229 fs->width = workspace->parent->width;
243 fs->height = workspace->parent->height; 230 fs->height = workspace->parent->height;
244 if (fs->type == C_VIEW) { 231 arrange_container(fs);
245 view_autoconfigure(fs->sway_view);
246 } else {
247 arrange_children_of(fs);
248 }
249 container_set_dirty(fs);
250 } else { 232 } else {
233 struct wlr_box box;
234 container_get_box(workspace, &box);
235 arrange_children(workspace->children, workspace->layout, &box);
251 arrange_floating(workspace->sway_workspace->floating); 236 arrange_floating(workspace->sway_workspace->floating);
252 arrange_children_of(workspace);
253 } 237 }
254} 238}
255 239
256static void arrange_output(struct sway_container *output) { 240void arrange_output(struct sway_container *output) {
257 if (config->reloading) { 241 if (config->reloading) {
258 return; 242 return;
259 } 243 }
244 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
245 return;
246 }
260 const struct wlr_box *output_box = wlr_output_layout_get_box( 247 const struct wlr_box *output_box = wlr_output_layout_get_box(
261 root_container.sway_root->output_layout, 248 root_container.sway_root->output_layout,
262 output->sway_output->wlr_output); 249 output->sway_output->wlr_output);
@@ -273,7 +260,7 @@ static void arrange_output(struct sway_container *output) {
273 } 260 }
274} 261}
275 262
276static void arrange_root() { 263void arrange_root(void) {
277 if (config->reloading) { 264 if (config->reloading) {
278 return; 265 return;
279 } 266 }
@@ -304,12 +291,8 @@ void arrange_windows(struct sway_container *container) {
304 arrange_workspace(container); 291 arrange_workspace(container);
305 break; 292 break;
306 case C_CONTAINER: 293 case C_CONTAINER:
307 arrange_children_of(container);
308 container_set_dirty(container);
309 break;
310 case C_VIEW: 294 case C_VIEW:
311 view_autoconfigure(container->sway_view); 295 arrange_container(container);
312 container_set_dirty(container);
313 break; 296 break;
314 case C_TYPES: 297 case C_TYPES:
315 break; 298 break;