diff options
Diffstat (limited to 'sway/layout.c')
-rw-r--r-- | sway/layout.c | 186 |
1 files changed, 134 insertions, 52 deletions
diff --git a/sway/layout.c b/sway/layout.c index 9fdfd62a..a48f15c4 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "layout.h" | 4 | #include "layout.h" |
5 | #include "log.h" | 5 | #include "log.h" |
6 | #include "list.h" | 6 | #include "list.h" |
7 | #include "config.h" | ||
7 | #include "container.h" | 8 | #include "container.h" |
8 | #include "workspace.h" | 9 | #include "workspace.h" |
9 | #include "focus.h" | 10 | #include "focus.h" |
@@ -32,6 +33,21 @@ void add_child(swayc_t *parent, swayc_t *child) { | |||
32 | child->width, child->height, parent, parent->type, parent->width, parent->height); | 33 | child->width, child->height, parent, parent->type, parent->width, parent->height); |
33 | list_add(parent->children, child); | 34 | list_add(parent->children, child); |
34 | child->parent = parent; | 35 | child->parent = parent; |
36 | // set focus for this container | ||
37 | if (parent->children->length == 1) { | ||
38 | set_focused_container_for(parent, child); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void add_floating(swayc_t *ws, swayc_t *child) { | ||
43 | sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, | ||
44 | child->width, child->height, ws, ws->type, ws->width, ws->height); | ||
45 | list_add(ws->floating, child); | ||
46 | child->parent = ws; | ||
47 | child->is_floating = true; | ||
48 | if (!ws->focused) { | ||
49 | set_focused_container_for(ws, child); | ||
50 | } | ||
35 | } | 51 | } |
36 | 52 | ||
37 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { | 53 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { |
@@ -55,7 +71,7 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { | |||
55 | new_child->parent = child->parent; | 71 | new_child->parent = child->parent; |
56 | 72 | ||
57 | if (child->parent->focused == child) { | 73 | if (child->parent->focused == child) { |
58 | child->parent->focused = new_child; | 74 | set_focused_container_for(child->parent, new_child); |
59 | } | 75 | } |
60 | child->parent = NULL; | 76 | child->parent = NULL; |
61 | return parent; | 77 | return parent; |
@@ -72,6 +88,7 @@ swayc_t *remove_child(swayc_t *child) { | |||
72 | break; | 88 | break; |
73 | } | 89 | } |
74 | } | 90 | } |
91 | i = 0; | ||
75 | } else { | 92 | } else { |
76 | for (i = 0; i < parent->children->length; ++i) { | 93 | for (i = 0; i < parent->children->length; ++i) { |
77 | if (parent->children->items[i] == child) { | 94 | if (parent->children->items[i] == child) { |
@@ -80,7 +97,7 @@ swayc_t *remove_child(swayc_t *child) { | |||
80 | } | 97 | } |
81 | } | 98 | } |
82 | } | 99 | } |
83 | //Set focused to new container | 100 | // Set focused to new container |
84 | if (parent->focused == child) { | 101 | if (parent->focused == child) { |
85 | if (parent->children->length > 0) { | 102 | if (parent->children->length > 0) { |
86 | set_focused_container_for(parent, parent->children->items[i?i-1:0]); | 103 | set_focused_container_for(parent, parent->children->items[i?i-1:0]); |
@@ -104,7 +121,7 @@ void move_container(swayc_t *container,swayc_t* root,int direction){ | |||
104 | //Only one container, meh. | 121 | //Only one container, meh. |
105 | break; | 122 | break; |
106 | } | 123 | } |
107 | 124 | //TODO: Implement horizontal movement. | |
108 | //TODO: Implement move to a different workspace. | 125 | //TODO: Implement move to a different workspace. |
109 | if(direction == MOVE_LEFT && i > 0){ | 126 | if(direction == MOVE_LEFT && i > 0){ |
110 | temp = root->children->items[i-1]; | 127 | temp = root->children->items[i-1]; |
@@ -167,11 +184,11 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
167 | // y -= container->y; | 184 | // y -= container->y; |
168 | for (i = 0; i < container->children->length; ++i) { | 185 | for (i = 0; i < container->children->length; ++i) { |
169 | swayc_t *child = container->children->items[i]; | 186 | swayc_t *child = container->children->items[i]; |
170 | sway_log(L_DEBUG, "Arranging workspace #%d", i); | 187 | child->x = x + container->gaps; |
171 | child->x = x; | 188 | child->y = y + container->gaps; |
172 | child->y = y; | 189 | child->width = width - container->gaps * 2; |
173 | child->width = width; | 190 | child->height = height - container->gaps * 2; |
174 | child->height = height; | 191 | sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y); |
175 | arrange_windows(child, -1, -1); | 192 | arrange_windows(child, -1, -1); |
176 | } | 193 | } |
177 | return; | 194 | return; |
@@ -179,27 +196,24 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
179 | { | 196 | { |
180 | struct wlc_geometry geometry = { | 197 | struct wlc_geometry geometry = { |
181 | .origin = { | 198 | .origin = { |
182 | .x = container->x, | 199 | .x = container->x + container->gaps / 2, |
183 | .y = container->y | 200 | .y = container->y + container->gaps / 2 |
184 | }, | 201 | }, |
185 | .size = { | 202 | .size = { |
186 | .w = width, | 203 | .w = width - container->gaps, |
187 | .h = height | 204 | .h = height - container->gaps |
188 | } | 205 | } |
189 | }; | 206 | }; |
190 | if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { | 207 | if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { |
191 | swayc_t *parent = container; | 208 | swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); |
192 | while (parent->type != C_OUTPUT) { | ||
193 | parent = parent->parent; | ||
194 | } | ||
195 | geometry.origin.x = 0; | 209 | geometry.origin.x = 0; |
196 | geometry.origin.y = 0; | 210 | geometry.origin.y = 0; |
197 | geometry.size.w = parent->width; | 211 | geometry.size.w = parent->width; |
198 | geometry.size.h = parent->height; | 212 | geometry.size.h = parent->height; |
199 | wlc_view_set_geometry(container->handle, &geometry); | 213 | wlc_view_set_geometry(container->handle, 0, &geometry); |
200 | wlc_view_bring_to_front(container->handle); | 214 | wlc_view_bring_to_front(container->handle); |
201 | } else { | 215 | } else { |
202 | wlc_view_set_geometry(container->handle, &geometry); | 216 | wlc_view_set_geometry(container->handle, 0, &geometry); |
203 | container->width = width; | 217 | container->width = width; |
204 | container->height = height; | 218 | container->height = height; |
205 | } | 219 | } |
@@ -213,40 +227,62 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
213 | break; | 227 | break; |
214 | } | 228 | } |
215 | 229 | ||
216 | double total_weight = 0; | 230 | x = y = 0; |
217 | for (i = 0; i < container->children->length; ++i) { | 231 | double scale = 0; |
218 | swayc_t *child = container->children->items[i]; | ||
219 | total_weight += child->weight; | ||
220 | } | ||
221 | |||
222 | switch (container->layout) { | 232 | switch (container->layout) { |
223 | case L_HORIZ: | 233 | case L_HORIZ: |
224 | default: | 234 | default: |
225 | sway_log(L_DEBUG, "Arranging %p horizontally", container); | 235 | // Calculate total width |
226 | for (i = 0; i < container->children->length; ++i) { | 236 | for (i = 0; i < container->children->length; ++i) { |
227 | swayc_t *child = container->children->items[i]; | 237 | int *old_width = &((swayc_t *)container->children->items[i])->width; |
228 | double percent = child->weight / total_weight; | 238 | if (*old_width <= 0) { |
229 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width); | 239 | if (container->children->length > 1) { |
230 | child->x = x + container->x; | 240 | *old_width = width / (container->children->length - 1); |
231 | child->y = y + container->y; | 241 | } else { |
232 | int w = width * percent; | 242 | *old_width = width; |
233 | int h = height; | 243 | } |
234 | arrange_windows(child, w, h); | 244 | } |
235 | x += w; | 245 | scale += *old_width; |
246 | } | ||
247 | // Resize windows | ||
248 | if (scale > 0.1) { | ||
249 | scale = width / scale; | ||
250 | sway_log(L_DEBUG, "Arranging %p horizontally", container); | ||
251 | for (i = 0; i < container->children->length; ++i) { | ||
252 | swayc_t *child = container->children->items[i]; | ||
253 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale); | ||
254 | child->x = x + container->x; | ||
255 | child->y = y + container->y; | ||
256 | arrange_windows(child, child->width * scale, height); | ||
257 | x += child->width; | ||
258 | } | ||
236 | } | 259 | } |
237 | break; | 260 | break; |
238 | case L_VERT: | 261 | case L_VERT: |
239 | sway_log(L_DEBUG, "Arranging %p vertically", container); | 262 | // Calculate total height |
240 | for (i = 0; i < container->children->length; ++i) { | 263 | for (i = 0; i < container->children->length; ++i) { |
241 | swayc_t *child = container->children->items[i]; | 264 | int *old_height = &((swayc_t *)container->children->items[i])->height; |
242 | double percent = child->weight / total_weight; | 265 | if (*old_height <= 0) { |
243 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width); | 266 | if (container->children->length > 1) { |
244 | child->x = x + container->x; | 267 | *old_height = height / (container->children->length - 1); |
245 | child->y = y + container->y; | 268 | } else { |
246 | int w = width; | 269 | *old_height = height; |
247 | int h = height * percent; | 270 | } |
248 | arrange_windows(child, w, h); | 271 | } |
249 | y += h; | 272 | scale += *old_height; |
273 | } | ||
274 | // Resize | ||
275 | if (scale > 0.1) { | ||
276 | scale = height / scale; | ||
277 | sway_log(L_DEBUG, "Arranging %p vertically", container); | ||
278 | for (i = 0; i < container->children->length; ++i) { | ||
279 | swayc_t *child = container->children->items[i]; | ||
280 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale); | ||
281 | child->x = x + container->x; | ||
282 | child->y = y + container->y; | ||
283 | arrange_windows(child, width, child->height * scale); | ||
284 | y += child->height; | ||
285 | } | ||
250 | } | 286 | } |
251 | break; | 287 | break; |
252 | } | 288 | } |
@@ -268,20 +304,15 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
268 | } | 304 | } |
269 | }; | 305 | }; |
270 | if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { | 306 | if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { |
271 | swayc_t *parent = view; | 307 | swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); |
272 | while (parent->type != C_OUTPUT) { | ||
273 | parent = parent->parent; | ||
274 | } | ||
275 | geometry.origin.x = 0; | 308 | geometry.origin.x = 0; |
276 | geometry.origin.y = 0; | 309 | geometry.origin.y = 0; |
277 | geometry.size.w = parent->width; | 310 | geometry.size.w = parent->width; |
278 | geometry.size.h = parent->height; | 311 | geometry.size.h = parent->height; |
279 | wlc_view_set_geometry(view->handle, &geometry); | 312 | wlc_view_set_geometry(view->handle, 0, &geometry); |
280 | wlc_view_bring_to_front(view->handle); | 313 | wlc_view_bring_to_front(view->handle); |
281 | } else { | 314 | } else { |
282 | wlc_view_set_geometry(view->handle, &geometry); | 315 | wlc_view_set_geometry(view->handle, 0, &geometry); |
283 | view->width = width; | ||
284 | view->height = height; | ||
285 | // Bring the views to the front in order of the list, the list | 316 | // Bring the views to the front in order of the list, the list |
286 | // will be kept up to date so that more recently focused views | 317 | // will be kept up to date so that more recently focused views |
287 | // have higher indexes | 318 | // have higher indexes |
@@ -326,3 +357,54 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { | |||
326 | } | 357 | } |
327 | return NULL; | 358 | return NULL; |
328 | } | 359 | } |
360 | |||
361 | swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) { | ||
362 | swayc_t *parent = container->parent; | ||
363 | |||
364 | if (dir == MOVE_PARENT) { | ||
365 | if (parent->type == C_OUTPUT) { | ||
366 | return NULL; | ||
367 | } else { | ||
368 | return parent; | ||
369 | } | ||
370 | } | ||
371 | while (true) { | ||
372 | // Test if we can even make a difference here | ||
373 | bool can_move = false; | ||
374 | int diff = 0; | ||
375 | if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { | ||
376 | if (parent->layout == L_HORIZ || parent->type == C_ROOT) { | ||
377 | can_move = true; | ||
378 | diff = dir == MOVE_LEFT ? -1 : 1; | ||
379 | } | ||
380 | } else { | ||
381 | if (parent->layout == L_VERT) { | ||
382 | can_move = true; | ||
383 | diff = dir == MOVE_UP ? -1 : 1; | ||
384 | } | ||
385 | } | ||
386 | if (can_move) { | ||
387 | int i; | ||
388 | for (i = 0; i < parent->children->length; ++i) { | ||
389 | swayc_t *child = parent->children->items[i]; | ||
390 | if (child == container) { | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | int desired = i + diff; | ||
395 | if (desired < 0 || desired >= parent->children->length) { | ||
396 | can_move = false; | ||
397 | } else { | ||
398 | return parent->children->items[desired]; | ||
399 | } | ||
400 | } | ||
401 | if (!can_move) { | ||
402 | container = parent; | ||
403 | parent = parent->parent; | ||
404 | if (!parent) { | ||
405 | // Nothing we can do | ||
406 | return NULL; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | } | ||