diff options
| author | Furkan Sahin <furkan-dev@proton.me> | 2025-03-12 16:35:41 +0100 |
|---|---|---|
| committer | Furkan Sahin <furkan-dev@proton.me> | 2025-03-12 16:35:41 +0100 |
| commit | faed8484c4e2cf9171b5fff1e4a449bcfc8f9930 (patch) | |
| tree | aefae9c2e9a8bc4f77fc60a51e612e7828bbff07 | |
| parent | c5cd4061854d51adc458a112ff16f015d8b48f73 (diff) | |
Avoid crashing on too many containers
If far too many containers are created, they can become so small that
their size calculations come out negative, leading to crashes on
asserts.
Instead, set a lower bound for sizes and disable the container entirely
if it goes below it, giving whatever space it used to the last
container.
The splits are not recalculated, so currently the effect is that if all
containers have the same width fraction, they keep getting narrower
until at some point they all round to zero and the last container will
be given all the available space.
A better behavior would have been if the additional container did not
contribute to size and fraction calculations at all, but it's an extreme
edge-case, anything is better than crashing, and this is easier to
implement.
| -rw-r--r-- | sway/desktop/transaction.c | 27 | ||||
| -rw-r--r-- | sway/tree/arrange.c | 18 |
2 files changed, 33 insertions, 12 deletions
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 52c03b18..16ce8e2e 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -312,9 +312,9 @@ static void arrange_children(enum sway_container_layout layout, list_t *children wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height); wlr_scene_node_reparent(&child->scene_tree->node, content); - if (activated) { - arrange_container(child, width, height - title_bar_height, - title_bar_height == 0, 0); + height -= title_bar_height; + if (activated && width > 0 && height > 0) { + arrange_container(child, width, height, title_bar_height == 0, 0); } else { disable_container(child); } @@ -341,9 +341,9 @@ static void arrange_children(enum sway_container_layout layout, list_t *children wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height); wlr_scene_node_reparent(&child->scene_tree->node, content); - if (activated) { - arrange_container(child, width, height - title_height, - title_bar_height == 0, 0); + height -= title_bar_height; + if (activated && width > 0 && height > 0) { + arrange_container(child, width, height, title_bar_height == 0, 0); } else { disable_container(child); } @@ -359,8 +359,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children wlr_scene_node_set_enabled(&child->border.tree->node, true); wlr_scene_node_set_position(&child->scene_tree->node, 0, off); wlr_scene_node_reparent(&child->scene_tree->node, content); - arrange_container(child, width, cheight, true, gaps); - off += cheight + gaps; + if (width > 0 && cheight > 0) { + arrange_container(child, width, cheight, true, gaps); + off += cheight + gaps; + } else { + disable_container(child); + } } } else if (layout == L_HORIZ) { int off = 0; @@ -372,7 +376,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children wlr_scene_node_set_position(&child->scene_tree->node, off, 0); wlr_scene_node_reparent(&child->scene_tree->node, content); arrange_container(child, cwidth, height, true, gaps); - off += cwidth + gaps; + if (cwidth > 0 && height > 0) { + arrange_container(child, cwidth, height, true, gaps); + off += cwidth + gaps; + } else { + disable_container(child); + } } } else { sway_assert(false, "unreachable"); diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 2b95a6dc..faf54d02 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -29,7 +29,7 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { } } - // Calculate each height fraction + // Calculate each width fraction double total_width_fraction = 0; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; @@ -82,12 +82,18 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { child->pending.y = parent->y; child->pending.width = round(child->width_fraction * child_total_width); child->pending.height = parent->height; - child_x += child->pending.width + inner_gap; // Make last child use remaining width of parent if (i == children->length - 1) { child->pending.width = parent->x + parent->width - child->pending.x; } + + // Arbitrary lower bound for window size + if (child->pending.width < 10 || child->pending.height < 10) { + child->pending.width = 0; + child->pending.height = 0; + } + child_x += child->pending.width + inner_gap; } } @@ -161,12 +167,18 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) { child->pending.y = child_y; child->pending.width = parent->width; child->pending.height = round(child->height_fraction * child_total_height); - child_y += child->pending.height + inner_gap; // Make last child use remaining height of parent if (i == children->length - 1) { child->pending.height = parent->y + parent->height - child->pending.y; } + + // Arbitrary lower bound for window size + if (child->pending.width < 10 || child->pending.height < 10) { + child->pending.width = 0; + child->pending.height = 0; + } + child_y += child->pending.height + inner_gap; } } |
