Skip to content

Commit da901a2

Browse files
committed
Fix negative dimensions in scene rect sizing
During cross-output tiling drags, computed box dimensions can become negative due to coordinate transforms and thickness subtractions. This triggers the assertion in wlr_scene_rect_set_size() which requires width >= 0 && height >= 0, crashing the compositor. Clamp dimensions to zero in three locations: - resize_box() in seatop_move_tiling.c for the WLR_EDGE_NONE case - update_indicator() in seatop_move_tiling.c as a safety net - arrange_container() in transaction.c for border width (matching the existing vert_border_height clamping from 62fd8c4) - update_rect_list() in container.c for pixman region boxes This is the same class of bug fixed by 62fd8c4 (height clamping) and partially addressed by c2d6aff (too-many-containers guards).
1 parent 6d25b10 commit da901a2

3 files changed

Lines changed: 25 additions & 4 deletions

File tree

sway/desktop/transaction.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,10 @@ static void arrange_container(struct sway_container *con,
435435
int border_left = con->current.border_left ? border_width : 0;
436436
int border_right = con->current.border_right ? border_width : 0;
437437
int vert_border_height = MAX(0, height - border_top - border_bottom);
438+
int horiz_border_width = MAX(0, width);
438439

439-
wlr_scene_rect_set_size(con->border.top, width, border_top);
440-
wlr_scene_rect_set_size(con->border.bottom, width, border_bottom);
440+
wlr_scene_rect_set_size(con->border.top, horiz_border_width, border_top);
441+
wlr_scene_rect_set_size(con->border.bottom, horiz_border_width, border_bottom);
441442
wlr_scene_rect_set_size(con->border.left,
442443
border_left, vert_border_height);
443444
wlr_scene_rect_set_size(con->border.right,
@@ -449,7 +450,7 @@ static void arrange_container(struct sway_container *con,
449450
wlr_scene_node_set_position(&con->border.left->node,
450451
0, border_top);
451452
wlr_scene_node_set_position(&con->border.right->node,
452-
width - border_right, border_top);
453+
horiz_border_width - border_right, border_top);
453454

454455
// make sure to reparent, it's possible that the client just came out of
455456
// fullscreen mode where the parent of the surface is not the container

sway/input/seatop_move_tiling.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ static void resize_box(struct wlr_box *box, enum wlr_edges edge,
8181
box->y += thickness;
8282
box->width -= thickness * 2;
8383
box->height -= thickness * 2;
84+
if (box->width < 0) {
85+
box->width = 0;
86+
}
87+
if (box->height < 0) {
88+
box->height = 0;
89+
}
8490
break;
8591
}
8692
}
@@ -153,6 +159,12 @@ static bool split_titlebar(struct sway_node *node, struct sway_container *avoid,
153159
}
154160

155161
static void update_indicator(struct seatop_move_tiling_event *e, struct wlr_box *box) {
162+
if (box->width < 0) {
163+
box->width = 0;
164+
}
165+
if (box->height < 0) {
166+
box->height = 0;
167+
}
156168
wlr_scene_node_set_position(&e->indicator_rect->node, box->x, box->y);
157169
wlr_scene_rect_set_size(e->indicator_rect, box->width, box->height);
158170
}

sway/tree/container.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,15 @@ static void update_rect_list(struct wlr_scene_tree *tree, pixman_region32_t *reg
338338
if (i < len) {
339339
const pixman_box32_t *box = &rects[i++];
340340
wlr_scene_node_set_position(&rect->node, box->x1, box->y1);
341-
wlr_scene_rect_set_size(rect, box->x2 - box->x1, box->y2 - box->y1);
341+
int rect_width = box->x2 - box->x1;
342+
int rect_height = box->y2 - box->y1;
343+
if (rect_width < 0) {
344+
rect_width = 0;
345+
}
346+
if (rect_height < 0) {
347+
rect_height = 0;
348+
}
349+
wlr_scene_rect_set_size(rect, rect_width, rect_height);
342350
}
343351
}
344352
}

0 commit comments

Comments
 (0)