Compare configure serials across wraparound

dc74e0b4055325b5c643abce66b391612969f0ba
A resize issued near the end of the Wayland serial range could remain
pending after the display counter wrapped to zero. Compare serials by
their wrapping difference so acknowledgements after rollover still
complete the resize.
Alexis Sellier committed ago 1 parent 1fd76d4b
swm.c +7 -1
1164 1164
static inline void client_set_scale(struct wlr_surface *s, float scale) {
1165 1165
    wlr_fractional_scale_v1_notify_scale(s, scale);
1166 1166
    wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
1167 1167
}
1168 1168
1169 +
/* Compare Wayland serials while preserving their wraparound ordering. */
1170 +
static inline bool serial_at_least(uint32_t serial, uint32_t target) {
1171 +
    return (int32_t)(serial - target) >= 0;
1172 +
}
1173 +
1169 1174
/* Configure the client surface size. */
1170 1175
static inline uint32_t client_set_size(client_t *c, uint32_t width, uint32_t height) {
1171 1176
    if (client_is_x11(c)) {
1172 1177
        wlr_xwayland_surface_configure(
1173 1178
            c->surface.xwayland, c->geom.x + c->bw, c->geom.y + c->bw, width, height
2279 2284
            (struct swm_box *)&c->geom, geom.width, geom.height, c->bw, c->resize_edges
2280 2285
        );
2281 2286
    }
2282 2287
    if (c->resize && c->mon) {
2283 2288
        uint32_t resize_serial = c->resize;
2284 -
        int      latest        = resize_serial <= c->surface.xdg->current.configure_serial;
2289 +
        int      latest =
2290 +
            serial_at_least(c->surface.xdg->current.configure_serial, resize_serial);
2285 2291
2286 2292
        apply_bounds(c, &c->mon->w);
2287 2293
        resize_apply(c);
2288 2294
2289 2295
        if (latest)
test/unit.c +5 -0
543 543
    struct wlr_seat    fake_seat = {};
544 544
545 545
    apply_bounds(&client, &bounds);
546 546
    assert(client.geom.x == 0 && client.geom.y == 55);
547 547
    assert(client.geom.width == 5 && client.geom.height == 5);
548 +
    assert(serial_at_least(10, 10));
549 +
    assert(serial_at_least(11, 10));
550 +
    assert(!serial_at_least(9, 10));
551 +
    assert(serial_at_least(1, UINT32_MAX));
552 +
    assert(!serial_at_least(UINT32_MAX, 1));
548 553
    seat = &fake_seat;
549 554
    assert(shortcuts_inhibited() == 0);
550 555
    assert(focus_close(nullptr) == nullptr);
551 556
    slot = pool_take(&static_listener_pool);
552 557
    assert(slot);