diff options
-rw-r--r-- | sway/layout.c | 136 |
1 files changed, 108 insertions, 28 deletions
diff --git a/sway/layout.c b/sway/layout.c index 4b30f729..e3de3354 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -71,6 +71,14 @@ void add_child(swayc_t *parent, swayc_t *child) { | |||
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | static double *get_height(swayc_t *cont) { | ||
75 | return &cont->height; | ||
76 | } | ||
77 | |||
78 | static double *get_width(swayc_t *cont) { | ||
79 | return &cont->width; | ||
80 | } | ||
81 | |||
74 | void insert_child(swayc_t *parent, swayc_t *child, int index) { | 82 | void insert_child(swayc_t *parent, swayc_t *child, int index) { |
75 | if (index > parent->children->length) { | 83 | if (index > parent->children->length) { |
76 | index = parent->children->length; | 84 | index = parent->children->length; |
@@ -86,7 +94,44 @@ void insert_child(swayc_t *parent, swayc_t *child, int index) { | |||
86 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { | 94 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { |
87 | child = new_container(child, parent->workspace_layout); | 95 | child = new_container(child, parent->workspace_layout); |
88 | } | 96 | } |
89 | 97 | if (is_auto_layout(parent->layout)) { | |
98 | /* go through each group, adjust the size of the first child of each group */ | ||
99 | double *(*get_maj_dim)(swayc_t *cont); | ||
100 | double *(*get_min_dim)(swayc_t *cont); | ||
101 | if (parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT) { | ||
102 | get_maj_dim = get_width; | ||
103 | get_min_dim = get_height; | ||
104 | } else { | ||
105 | get_maj_dim = get_height; | ||
106 | get_min_dim = get_width; | ||
107 | } | ||
108 | for (int i = index; i < parent->children->length;) { | ||
109 | int start = auto_group_start_index(parent, i); | ||
110 | int end = auto_group_end_index(parent, i); | ||
111 | swayc_t *first = parent->children->items[start]; | ||
112 | if (start + 1 < parent->children->length) { | ||
113 | /* preserve the group's dimension along major axis */ | ||
114 | *get_maj_dim(first) = *get_maj_dim(parent->children->items[start + 1]); | ||
115 | } else { | ||
116 | /* new group, let the apply_layout handle it */ | ||
117 | first->height = first->width = 0; | ||
118 | break; | ||
119 | } | ||
120 | double remaining = *get_min_dim(parent); | ||
121 | for (int j = end - 1; j > start; --j) { | ||
122 | swayc_t *sibling = parent->children->items[j]; | ||
123 | if (sibling == child) { | ||
124 | /* the inserted child won't yet have its minor | ||
125 | dimension set */ | ||
126 | remaining -= *get_min_dim(parent) / (end - start); | ||
127 | } else { | ||
128 | remaining -= *get_min_dim(sibling); | ||
129 | } | ||
130 | } | ||
131 | *get_min_dim(first) = remaining; | ||
132 | i = end; | ||
133 | } | ||
134 | } | ||
90 | } | 135 | } |
91 | 136 | ||
92 | void add_floating(swayc_t *ws, swayc_t *child) { | 137 | void add_floating(swayc_t *ws, swayc_t *child) { |
@@ -185,6 +230,42 @@ swayc_t *remove_child(swayc_t *child) { | |||
185 | break; | 230 | break; |
186 | } | 231 | } |
187 | } | 232 | } |
233 | if (is_auto_layout(parent->layout) && parent->children->length) { | ||
234 | /* go through each group, adjust the size of the last child of each group */ | ||
235 | double *(*get_maj_dim)(swayc_t *cont); | ||
236 | double *(*get_min_dim)(swayc_t *cont); | ||
237 | if (parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT) { | ||
238 | get_maj_dim = get_width; | ||
239 | get_min_dim = get_height; | ||
240 | } else { | ||
241 | get_maj_dim = get_height; | ||
242 | get_min_dim = get_width; | ||
243 | } | ||
244 | for (int j = parent->children->length - 1; j >= i;) { | ||
245 | int start = auto_group_start_index(parent, j); | ||
246 | int end = auto_group_end_index(parent, j); | ||
247 | swayc_t *first = parent->children->items[start]; | ||
248 | if (i == start) { | ||
249 | /* removed element was first child in the current group, | ||
250 | use its size along the major axis */ | ||
251 | *get_maj_dim(first) = *get_maj_dim(child); | ||
252 | } else if (start > i) { | ||
253 | /* preserve the group's dimension along major axis */ | ||
254 | *get_maj_dim(first) = *get_maj_dim(parent->children->items[start - 1]); | ||
255 | } | ||
256 | if (end != parent->children->length) { | ||
257 | double remaining = *get_min_dim(parent); | ||
258 | for (int k = start; k < end - 1; ++k) { | ||
259 | swayc_t *sibling = parent->children->items[k]; | ||
260 | remaining -= *get_min_dim(sibling); | ||
261 | } | ||
262 | /* last element of the group gets remaining size, elements | ||
263 | that don't change groups keep their ratio */ | ||
264 | *get_min_dim((swayc_t *) parent->children->items[end - 1]) = remaining; | ||
265 | } /* else last group, let apply_layout handle it */ | ||
266 | j = start - 1; | ||
267 | } | ||
268 | } | ||
188 | } | 269 | } |
189 | // Set focused to new container | 270 | // Set focused to new container |
190 | if (parent->focused == child) { | 271 | if (parent->focused == child) { |
@@ -250,6 +331,24 @@ void swap_geometry(swayc_t *a, swayc_t *b) { | |||
250 | b->height = h; | 331 | b->height = h; |
251 | } | 332 | } |
252 | 333 | ||
334 | static void swap_children(swayc_t *container, int a, int b) { | ||
335 | if (a >= 0 && b >= 0 && a < container->children->length | ||
336 | && b < container->children->length | ||
337 | && a != b) { | ||
338 | swayc_t *pa = (swayc_t *)container->children->items[a]; | ||
339 | swayc_t *pb = (swayc_t *)container->children->items[b]; | ||
340 | container->children->items[a] = container->children->items[b]; | ||
341 | container->children->items[b] = pa; | ||
342 | if (is_auto_layout(container->layout)) { | ||
343 | size_t ga = auto_group_index(container, a); | ||
344 | size_t gb = auto_group_index(container, b); | ||
345 | if (ga != gb) { | ||
346 | swap_geometry(pa, pb); | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | |||
253 | void move_container(swayc_t *container, enum movement_direction dir) { | 352 | void move_container(swayc_t *container, enum movement_direction dir) { |
254 | enum swayc_layouts layout = L_NONE; | 353 | enum swayc_layouts layout = L_NONE; |
255 | swayc_t *parent = container->parent; | 354 | swayc_t *parent = container->parent; |
@@ -319,29 +418,6 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
319 | } else if (desired >= parent->children->length) { | 418 | } else if (desired >= parent->children->length) { |
320 | desired = 0; | 419 | desired = 0; |
321 | } | 420 | } |
322 | // if move command makes container change from master to slave | ||
323 | // (or the contrary), reset its geometry an the one of the replaced item. | ||
324 | if (parent->nb_master | ||
325 | && (size_t)parent->children->length > parent->nb_master) { | ||
326 | swayc_t *swap_geom = NULL; | ||
327 | // if child is being promoted/demoted, it will swap geometry | ||
328 | // with the sibling being demoted/promoted. | ||
329 | if ((dir == MOVE_NEXT && desired == 0) | ||
330 | || (dir == MOVE_PREV && (size_t)desired == parent->nb_master - 1)) { | ||
331 | swap_geom = parent->children->items[parent->nb_master - 1]; | ||
332 | } else if ((dir == MOVE_NEXT && (size_t)desired == parent->nb_master) | ||
333 | || (dir == MOVE_PREV && desired == parent->children->length - 1)) { | ||
334 | swap_geom = parent->children->items[parent->nb_master]; | ||
335 | } | ||
336 | if (swap_geom) { | ||
337 | double h = child->height; | ||
338 | double w = child->width; | ||
339 | child->width = swap_geom->width; | ||
340 | child->height = swap_geom->height; | ||
341 | swap_geom->width = w; | ||
342 | swap_geom->height = h; | ||
343 | } | ||
344 | } | ||
345 | } | 421 | } |
346 | // when it has ascended, legal insertion position is 0:len | 422 | // when it has ascended, legal insertion position is 0:len |
347 | // when it has not, legal insertion position is 0:len-1 | 423 | // when it has not, legal insertion position is 0:len-1 |
@@ -365,10 +441,14 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
365 | container->width = container->height = 0; | 441 | container->width = container->height = 0; |
366 | } | 442 | } |
367 | } | 443 | } |
368 | swayc_t *old_parent = remove_child(container); | 444 | if (container->parent == parent) { |
369 | insert_child(parent, container, desired); | 445 | swap_children(parent, idx, desired); |
370 | destroy_container(old_parent); | 446 | } else { |
371 | sway_log(L_DEBUG,"Moving to %p %d", parent, desired); | 447 | swayc_t *old_parent = remove_child(container); |
448 | insert_child(parent, container, desired); | ||
449 | destroy_container(old_parent); | ||
450 | sway_log(L_DEBUG,"Moving to %p %d", parent, desired); | ||
451 | } | ||
372 | break; | 452 | break; |
373 | } | 453 | } |
374 | } | 454 | } |