diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-14 14:16:42 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-14 14:17:37 +0300 |
| commit | 7e8bf8d2a81f37303e0c9ae430f1acbff106da22 (patch) | |
| tree | 274cc707238f930395f87e74322c7c139811fe46 /src/platform/wayland/drag.c | |
| parent | 26f644f51709cc9f6cdd8060e7561498f2bb465d (diff) | |
Wayland: fix GL thread races, reconnect ordering and sizing bugs
- GL swaps on a rendering thread no longer touch frame callbacks or
presentation feedback. They set a per-surface flag and wake the loop; the
owner thread arms both at its next flush and commits, so the frame callback
fires without waiting for the application's next swap.
- Clear the offline flag only after the reconnect rebuild succeeds, and not
when the connection was lost again during it.
- make_current fails with ENOTCONN for a window without a context. Detaching
is a no-op when nothing is current or the EGL display is gone.
- Window move, resize, window menu and drag start need a pointer button or
tablet tip that is still held; otherwise they fail with ESTALE and use that
press's serial. Popups fail with ESTALE without an input serial and with
ENOTCONN while the display is lost.
- An oversized device size shrinks to the buffer limits, keeping the aspect
ratio, instead of closing the window.
- FIXED_SIZE windows pin xdg min and max on every set_size. The 64px minimum
applies only to compositor-suggested sizes, not to application sizes.
- The keyboard-enter serial becomes the input serial. Clipboard copy with no
keyboard focus fails with ESTALE.
- Relative-pointer windows relock after a reconnect rebuild.
- errno: EBUSY for an active drag, ENOTSUP for place_under_pointer and for GL
without EGL, EINVAL for drag carry without a drag.
- Default window title and app ID are "YASL".
- Pointer motion and button events carry unrounded device-pixel positions in
precise_x/precise_y with precise_position set.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/platform/wayland/drag.c')
| -rw-r--r-- | src/platform/wayland/drag.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/src/platform/wayland/drag.c b/src/platform/wayland/drag.c index 07e31b5..4317d0d 100644 --- a/src/platform/wayland/drag.c +++ b/src/platform/wayland/drag.c @@ -136,15 +136,16 @@ static const struct wl_data_source_listener source_listener = { .action = source_action, }; +/* A seat whose press is still held over the origin window; its serial starts the drag. */ static struct seat *drag_seat(struct wayland_display *c, struct wayland_surface *origin) { struct wayland_surface *root = surface_root(origin); struct seat *active = c->active_seat ? c->active_seat : c->seats; - if (active && active->press_serial && + if (active && seat_held_press_serial(active) && surface_root(active->press_surface) == root) return active; for (struct seat *s = c->seats; s; s = s->next) - if (s->press_serial && surface_root(s->press_surface) == root) + if (seat_held_press_serial(s) && surface_root(s->press_surface) == root) return s; return NULL; } @@ -153,20 +154,33 @@ bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surfac const struct yasl_private_drag_image *image, const struct yasl_private_drag_listener *l, void *ud) { - if (!c || !origin || origin->conn != c || !l || c->drag.source) + if (!c || !origin || origin->conn != c || !l) { + errno = EINVAL; return false; + } + if (c->drag.source) { + errno = EBUSY; + return false; + } struct seat *seat = drag_seat(c, origin); - if (!seat) + if (!seat) { + errno = ESTALE; return false; + } struct wl_data_device *device = clipboard_data_device(seat->clipboard); - if (!device || wl_data_device_get_version(device) < 3) + if (!device || wl_data_device_get_version(device) < 3) { + errno = ENOTSUP; return false; + } c->drag.scale_120 = origin->scale_120; - if (image && !icon_create(c, image)) + if (image && !icon_create(c, image)) { + errno = ENOMEM; return false; + } struct wl_data_source *s = wl_data_device_manager_create_data_source(c->data_manager); if (!s) { icon_clear(&c->drag.icon); + errno = ENOMEM; return false; } c->drag.source = s; @@ -180,7 +194,7 @@ bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surfac c->drag.toplevel = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag( c->toplevel_drag_mgr, s); wl_data_device_start_drag(device, s, seat->press_surface->surface, - c->drag.icon.surface, seat->press_serial); + c->drag.icon.surface, seat_held_press_serial(seat)); if (image) icon_show(c, image); wl_display_flush(c->wl); @@ -196,8 +210,14 @@ void wayland_display_drag_cancel(struct wayland_display *c) bool wayland_surface_drag_carry(struct wayland_surface *w, struct yasl_private_vector2i offset) { struct wayland_display *c = w ? w->conn : NULL; - if (!c || !c->drag.source || !c->drag.toplevel || !w->toplevel) + if (!c || !c->drag.source || !w->toplevel) { + errno = EINVAL; + return false; + } + if (!c->drag.toplevel) { + errno = ENOTSUP; return false; + } uint32_t scale = c->drag.scale_120; xdg_toplevel_drag_v1_attach(c->drag.toplevel, w->toplevel, yasl_private_scale_to_logical(offset.x, scale), @@ -210,6 +230,7 @@ bool wayland_surface_place_under_pointer(struct wayland_surface *w, struct yasl_ { (void)w; (void)at; + errno = ENOTSUP; return false; } |
