diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-11-25 10:59:49 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2017-11-25 11:19:25 -0500 |
commit | ce1936bc65d01502e3a5f8681bb039cb95e82e0c (patch) | |
tree | fcdeb554df5aaf30aff7723171e0dfe0bf097420 /sway/tree/layout.c | |
parent | Remove IPC_GET_PIXELS (diff) | |
download | sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.gz sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.zst sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.zip |
Arrange windows on desktop
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r-- | sway/tree/layout.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 5a70c570..3d6b404d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -1,10 +1,14 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | #include <math.h> | ||
3 | #include <stdbool.h> | 4 | #include <stdbool.h> |
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
5 | #include <string.h> | 6 | #include <string.h> |
7 | #include <wlr/types/wlr_output.h> | ||
6 | #include <wlr/types/wlr_output_layout.h> | 8 | #include <wlr/types/wlr_output_layout.h> |
7 | #include "sway/container.h" | 9 | #include "sway/container.h" |
10 | #include "sway/output.h" | ||
11 | #include "sway/view.h" | ||
8 | #include "list.h" | 12 | #include "list.h" |
9 | #include "log.h" | 13 | #include "log.h" |
10 | 14 | ||
@@ -70,3 +74,204 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | |||
70 | void sort_workspaces(swayc_t *output) { | 74 | void sort_workspaces(swayc_t *output) { |
71 | list_stable_sort(output->children, sort_workspace_cmp_qsort); | 75 | list_stable_sort(output->children, sort_workspace_cmp_qsort); |
72 | } | 76 | } |
77 | |||
78 | static void apply_horiz_layout(swayc_t *container, const double x, | ||
79 | const double y, const double width, | ||
80 | const double height, const int start, | ||
81 | const int end); | ||
82 | |||
83 | static void apply_vert_layout(swayc_t *container, const double x, | ||
84 | const double y, const double width, | ||
85 | const double height, const int start, | ||
86 | const int end); | ||
87 | |||
88 | void arrange_windows(swayc_t *container, double width, double height) { | ||
89 | int i; | ||
90 | if (width == -1 || height == -1) { | ||
91 | width = container->width; | ||
92 | height = container->height; | ||
93 | } | ||
94 | // pixels are indivisible. if we don't round the pixels, then the view | ||
95 | // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's | ||
96 | // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y. | ||
97 | width = floor(width); | ||
98 | height = floor(height); | ||
99 | |||
100 | sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, | ||
101 | container->name, container->width, container->height, container->x, | ||
102 | container->y); | ||
103 | |||
104 | double x = 0, y = 0; | ||
105 | switch (container->type) { | ||
106 | case C_ROOT: | ||
107 | // TODO: wlr_output_layout probably | ||
108 | for (i = 0; i < container->children->length; ++i) { | ||
109 | swayc_t *output = container->children->items[i]; | ||
110 | sway_log(L_DEBUG, "Arranging output '%s' at %f,%f", | ||
111 | output->name, output->x, output->y); | ||
112 | arrange_windows(output, -1, -1); | ||
113 | } | ||
114 | return; | ||
115 | case C_OUTPUT: | ||
116 | { | ||
117 | int _width, _height; | ||
118 | wlr_output_effective_resolution( | ||
119 | container->sway_output->wlr_output, &_width, &_height); | ||
120 | width = container->width = _width; | ||
121 | height = container->height = _height; | ||
122 | } | ||
123 | // arrange all workspaces: | ||
124 | for (i = 0; i < container->children->length; ++i) { | ||
125 | swayc_t *child = container->children->items[i]; | ||
126 | arrange_windows(child, -1, -1); | ||
127 | } | ||
128 | return; | ||
129 | case C_WORKSPACE: | ||
130 | { | ||
131 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); | ||
132 | width = output->width, height = output->height; | ||
133 | container->x = x; | ||
134 | container->y = y; | ||
135 | width = container->width; | ||
136 | height = container->height; | ||
137 | sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", | ||
138 | container->name, container->x, container->y); | ||
139 | } | ||
140 | // children are properly handled below | ||
141 | break; | ||
142 | case C_VIEW: | ||
143 | { | ||
144 | container->width = width; | ||
145 | container->height = height; | ||
146 | container->sway_view->iface.set_dimensions(container->sway_view, | ||
147 | container->width, container->height); | ||
148 | sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", | ||
149 | container->width, container->height, | ||
150 | container->x, container->y); | ||
151 | } | ||
152 | return; | ||
153 | default: | ||
154 | container->width = width; | ||
155 | container->height = height; | ||
156 | x = container->x; | ||
157 | y = container->y; | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | switch (container->layout) { | ||
162 | case L_HORIZ: | ||
163 | apply_horiz_layout(container, x, y, width, height, 0, | ||
164 | container->children->length); | ||
165 | break; | ||
166 | case L_VERT: | ||
167 | apply_vert_layout(container, x, y, width, height, 0, | ||
168 | container->children->length); | ||
169 | break; | ||
170 | default: | ||
171 | sway_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); | ||
172 | apply_horiz_layout(container, x, y, width, height, 0, | ||
173 | container->children->length); | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static void apply_horiz_layout(swayc_t *container, | ||
179 | const double x, const double y, | ||
180 | const double width, const double height, | ||
181 | const int start, const int end) { | ||
182 | double scale = 0; | ||
183 | // Calculate total width | ||
184 | for (int i = start; i < end; ++i) { | ||
185 | double *old_width = &((swayc_t *)container->children->items[i])->width; | ||
186 | if (*old_width <= 0) { | ||
187 | if (end - start > 1) { | ||
188 | *old_width = width / (end - start - 1); | ||
189 | } else { | ||
190 | *old_width = width; | ||
191 | } | ||
192 | } | ||
193 | scale += *old_width; | ||
194 | } | ||
195 | scale = width / scale; | ||
196 | |||
197 | // Resize windows | ||
198 | double child_x = x; | ||
199 | if (scale > 0.1) { | ||
200 | sway_log(L_DEBUG, "Arranging %p horizontally", container); | ||
201 | for (int i = start; i < end; ++i) { | ||
202 | swayc_t *child = container->children->items[i]; | ||
203 | sway_log(L_DEBUG, | ||
204 | "Calculating arrangement for %p:%d (will scale %f by %f)", | ||
205 | child, child->type, width, scale); | ||
206 | child->x = child_x; | ||
207 | child->y = y; | ||
208 | |||
209 | if (i == end - 1) { | ||
210 | double remaining_width = x + width - child_x; | ||
211 | arrange_windows(child, remaining_width, height); | ||
212 | } else { | ||
213 | arrange_windows(child, child->width * scale, height); | ||
214 | } | ||
215 | child_x += child->width; | ||
216 | } | ||
217 | |||
218 | // update focused view border last because it may | ||
219 | // depend on the title bar geometry of its siblings. | ||
220 | /* TODO WLR | ||
221 | if (focused && container->children->length > 1) { | ||
222 | update_container_border(focused); | ||
223 | } | ||
224 | */ | ||
225 | } | ||
226 | } | ||
227 | |||
228 | void apply_vert_layout(swayc_t *container, | ||
229 | const double x, const double y, | ||
230 | const double width, const double height, const int start, | ||
231 | const int end) { | ||
232 | int i; | ||
233 | double scale = 0; | ||
234 | // Calculate total height | ||
235 | for (i = start; i < end; ++i) { | ||
236 | double *old_height = &((swayc_t *)container->children->items[i])->height; | ||
237 | if (*old_height <= 0) { | ||
238 | if (end - start > 1) { | ||
239 | *old_height = height / (end - start - 1); | ||
240 | } else { | ||
241 | *old_height = height; | ||
242 | } | ||
243 | } | ||
244 | scale += *old_height; | ||
245 | } | ||
246 | scale = height / scale; | ||
247 | |||
248 | // Resize | ||
249 | double child_y = y; | ||
250 | if (scale > 0.1) { | ||
251 | sway_log(L_DEBUG, "Arranging %p vertically", container); | ||
252 | for (i = start; i < end; ++i) { | ||
253 | swayc_t *child = container->children->items[i]; | ||
254 | sway_log(L_DEBUG, | ||
255 | "Calculating arrangement for %p:%d (will scale %f by %f)", | ||
256 | child, child->type, height, scale); | ||
257 | child->x = x; | ||
258 | child->y = child_y; | ||
259 | |||
260 | if (i == end - 1) { | ||
261 | double remaining_height = y + height - child_y; | ||
262 | arrange_windows(child, width, remaining_height); | ||
263 | } else { | ||
264 | arrange_windows(child, width, child->height * scale); | ||
265 | } | ||
266 | child_y += child->height; | ||
267 | } | ||
268 | |||
269 | // update focused view border last because it may | ||
270 | // depend on the title bar geometry of its siblings. | ||
271 | /* TODO WLR | ||
272 | if (focused && container->children->length > 1) { | ||
273 | update_container_border(focused); | ||
274 | } | ||
275 | */ | ||
276 | } | ||
277 | } | ||