From 624d1371304a5ae4b3429ad5e4267aac7cd03dfd Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Mon, 12 Oct 2026 00:09:38 +0300 Subject: missing impls and hardening --- src/wayland/buffer.c | 9 +++++++-- src/wayland/clipboard.c | 32 +++++++++++++++++++------------- src/wayland/clipboard.h | 5 +++-- src/wayland/drag.c | 12 ++++++------ src/wayland/internal.h | 34 ++-------------------------------- src/wayland/keyboard.c | 6 +++--- src/wayland/pointer.c | 8 ++++---- src/wayland/surface.c | 13 ++++++------- 8 files changed, 50 insertions(+), 69 deletions(-) (limited to 'src/wayland') diff --git a/src/wayland/buffer.c b/src/wayland/buffer.c index 76f6c0e..3f9cf84 100644 --- a/src/wayland/buffer.c +++ b/src/wayland/buffer.c @@ -278,8 +278,10 @@ static void frame_done(void *data, struct wl_callback *cb, uint32_t ms) w->frame_cb = NULL; uint64_t now = yasl_loop_now_ns(); - if (!w->conn->pres_clock_known) + if (!w->conn->pres_clock_known) { yasl_clock_presented(&w->clock, yasl_clock_extend_ms(ms, now), w->sample_refresh); + w->clock.source = YASL_TIMING_FRAME_CALLBACK; + } if (w->want_draw) wayland_surface_schedule_redraw(w); @@ -358,6 +360,7 @@ static void presented(void *data, struct wp_presentation_feedback *fb, (((uint64_t)tv_sec_hi << 32) | tv_sec_lo) * 1000000000ull + tv_nsec); if (refresh) w->clock.refresh_ns = refresh; w->clock.last_present_ns = ns; + w->clock.source = YASL_TIMING_PRESENTATION; } (void)fb; feedback_destroy(feedback); @@ -444,7 +447,7 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb if (!w || w->closed || !w->frame_active || w->frame_presented || !fb || !damage || fb->pixels != w->frame.target.pixels || fb->size.x != w->width || fb->size.y != w->height || - fb->buffer != w->cur) + fb->buffer != w->cur || fb->native_drawable || fb->transaction) return false; w->damage = *damage; @@ -485,6 +488,7 @@ void surface_draw_frame(struct wayland_surface *w) w->frame = (struct yasl_frame){ .surface = &w->base, .target = { + .generation = yasl_frame_begin(&w->base), .pixels = w->buffers[idx].pixels, .size = { .x = w->width, .y = w->height }, .buffer = idx, @@ -544,6 +548,7 @@ struct yasl_timing wayland_surface_timing(const struct wayland_surface *w) .last_present_ns = w->clock.last_present_ns, .next_present_ns = yasl_clock_next_present_ns(&w->clock), .frames_skipped = w->frames_skipped, + .source = w->clock.source, }; yasl_clock_resize_stats(&w->clock, &t.resize); return t; diff --git a/src/wayland/clipboard.c b/src/wayland/clipboard.c index 0e6ce33..7df1a70 100644 --- a/src/wayland/clipboard.c +++ b/src/wayland/clipboard.c @@ -134,10 +134,8 @@ static int transfer_io(int fd, short events, void *ud) memcpy(t->text + t->len, buf, (size_t)n); t->len += n; } else if (n == 0) { - if (t->len) { - t->owner->receive(t->text, t->len, t->uri_list, - t->drop_surface, t->owner->ud); - } + t->owner->receive(t->text ? t->text : "", t->len, t->uri_list, + t->drop_surface, t->owner->ud); transfer_end(t, true); } else if (errno != EAGAIN && errno != EINTR) transfer_destroy(t); } @@ -556,24 +554,22 @@ void clipboard_copy(struct clipboard *c, const char *text, uint32_t serial) wl_data_device_set_selection(c->device, c->source, serial); } -void clipboard_paste(struct clipboard *c) +void clipboard_paste(struct clipboard *c, struct wl_surface *target) { if (!c || !c->device || !c->selection || !c->selection->mime) return; int fds[2]; if (pipe2(fds, O_CLOEXEC) < 0) return; wl_data_offer_receive(c->selection->proxy, c->selection->mime, fds[1]); close(fds[1]); - start_transfer(c, fds[0], false, false); + struct transfer *t = start_transfer(c, fds[0], false, false); + if (t) t->drop_surface = target; wl_display_flush(c->display); } void clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t serial) { if (!c || !text || !serial) return; - if (!c->primary_device || !c->primary_manager) { - clipboard_copy(c, text, serial); - return; - } + if (!c->primary_device || !c->primary_manager) return; char *copy = strdup(text); if (!copy) return; if (c->primary_source) zwp_primary_selection_source_v1_destroy(c->primary_source); @@ -589,7 +585,7 @@ void clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t seri zwp_primary_selection_device_v1_set_selection(c->primary_device, c->primary_source, serial); } -void clipboard_paste_primary(struct clipboard *c) +void clipboard_paste_primary(struct clipboard *c, struct wl_surface *target) { if (!c) return; if (c->primary_device && c->primary_selection && c->primary_selection->mime) { @@ -598,11 +594,21 @@ void clipboard_paste_primary(struct clipboard *c) zwp_primary_selection_offer_v1_receive(c->primary_selection->proxy, c->primary_selection->mime, fds[1]); close(fds[1]); - start_transfer(c, fds[0], false, false); + struct transfer *t = start_transfer(c, fds[0], false, false); + if (t) t->drop_surface = target; wl_display_flush(c->display); return; } - clipboard_paste(c); +} + +void clipboard_forget_surface(struct clipboard *c, struct wl_surface *surface) +{ + if (!c || !surface) return; + for (struct transfer *t = c->transfers, *next; t; t = next) { + next = t->next; + if (t->drop_surface == surface) transfer_destroy(t); + } + if (c->drag_surface == surface) c->drag_surface = NULL; } void clipboard_destroy(struct clipboard *c) diff --git a/src/wayland/clipboard.h b/src/wayland/clipboard.h index 6ea75c6..9fefa8e 100644 --- a/src/wayland/clipboard.h +++ b/src/wayland/clipboard.h @@ -24,9 +24,10 @@ void clipboard_destroy(struct clipboard *); bool clipboard_set_seat(struct clipboard *, struct wl_seat *); void clipboard_set_primary_manager(struct clipboard *, struct zwp_primary_selection_device_manager_v1 *); void clipboard_copy(struct clipboard *, const char *, uint32_t); -void clipboard_paste(struct clipboard *); +void clipboard_paste(struct clipboard *, struct wl_surface *target); +void clipboard_forget_surface(struct clipboard *, struct wl_surface *); void clipboard_copy_primary(struct clipboard *, const char *, uint32_t); -void clipboard_paste_primary(struct clipboard *); +void clipboard_paste_primary(struct clipboard *, struct wl_surface *target); typedef void (*clipboard_drag_fn)(enum yasl_drag_event, struct wl_surface *on, double x, double y, void *); diff --git a/src/wayland/drag.c b/src/wayland/drag.c index 7c15002..989dbb6 100644 --- a/src/wayland/drag.c +++ b/src/wayland/drag.c @@ -90,11 +90,11 @@ static void drag_clear(struct wayland_display *c, bool ended) static void drag_finish(struct wayland_display *c, enum yasl_drag_end how, bool ended) { - const struct yasl_drag_listener *l = c->drag.listener; + struct yasl_drag_listener l = c->drag.listener; void *ud = c->drag.ud; drag_clear(c, ended); - if (l && l->end) - l->end(ud, how); + if (l.end) + l.end(ud, how); } void conn_drag_end(struct wayland_display *c) @@ -111,7 +111,7 @@ static void source_cancelled(void *ud, struct wl_data_source *s) { (void)s; struct wayland_display *c = ud; - bool released = c->drag.dropped || !c->drag.carrying; + bool released = c->drag.dropped; drag_finish(c, released ? YASL_DRAG_DROPPED : YASL_DRAG_CANCELLED, true); } @@ -171,7 +171,7 @@ bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surfac } c->drag.source = s; c->drag.seat = seat; - c->drag.listener = l; + c->drag.listener = *l; c->drag.ud = ud; wl_data_source_add_listener(s, &source_listener, c); wl_data_source_offer(s, clipboard_drag_mime()); @@ -190,7 +190,7 @@ bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surfac void wayland_display_drag_cancel(struct wayland_display *c) { if (c && c->drag.source) - drag_clear(c, false); + drag_finish(c, YASL_DRAG_CANCELLED, false); } bool wayland_surface_drag_carry(struct wayland_surface *w, struct yasl_vector2i offset) diff --git a/src/wayland/internal.h b/src/wayland/internal.h index cba5096..ccfd2dc 100644 --- a/src/wayland/internal.h +++ b/src/wayland/internal.h @@ -100,7 +100,7 @@ struct conn_drag { struct wl_data_source *source; struct xdg_toplevel_drag_v1 *toplevel; struct drag_icon icon; - const struct yasl_drag_listener *listener; + struct yasl_drag_listener listener; void *ud; struct seat *seat; uint32_t scale_120; @@ -192,36 +192,7 @@ struct seat { bool touch_scrolling; }; -#define YASL_QUEUE_CAP 256 -#define YASL_QUEUE_MASK (YASL_QUEUE_CAP - 1) -struct input_queue { - struct yasl_input_event events[YASL_QUEUE_CAP]; - int head; - int tail; - int count; -}; - -static inline void input_queue_push(struct input_queue *q, const struct yasl_input_event *ev) -{ - if (unlikely(q->count >= YASL_QUEUE_CAP)) return; - q->events[q->tail] = *ev; - q->tail = (q->tail + 1) & YASL_QUEUE_MASK; - q->count++; -} - -static inline bool input_queue_pop(struct input_queue *q, struct yasl_input_event *ev) -{ - if (unlikely(q->count <= 0)) return false; - *ev = q->events[q->head]; - q->head = (q->head + 1) & YASL_QUEUE_MASK; - q->count--; - return true; -} - -static inline void input_queue_clear(struct input_queue *q) -{ - q->head = q->tail = q->count = 0; -} +#include "common/input.h" struct wayland_display { struct yasl_display base; @@ -257,7 +228,6 @@ struct wayland_display { struct xdg_toplevel_drag_manager_v1 *toplevel_drag_mgr; struct conn_drag drag; struct wayland_surface *surfaces; - struct wayland_surface *paste_target; struct wayland_surface *dead; /* 4-byte integers */ diff --git a/src/wayland/keyboard.c b/src/wayland/keyboard.c index 6bdd58c..f7e2691 100644 --- a/src/wayland/keyboard.c +++ b/src/wayland/keyboard.c @@ -374,11 +374,11 @@ void wayland_display_paste(struct wayland_display *c, enum yasl_selection sel, s struct seat *s = c ? conn_active_seat(c) : NULL; if (!s || !s->clipboard) return; - c->paste_target = target; + if (!target || target->closed) return; if (sel == YASL_PRIMARY) - clipboard_paste_primary(s->clipboard); + clipboard_paste_primary(s->clipboard, target->surface); else - clipboard_paste(s->clipboard); + clipboard_paste(s->clipboard, target->surface); } bool wayland_surface_input_poll(struct wayland_surface *w, struct yasl_input_event *ev) diff --git a/src/wayland/pointer.c b/src/wayland/pointer.c index d434047..3b3ad73 100644 --- a/src/wayland/pointer.c +++ b/src/wayland/pointer.c @@ -1032,10 +1032,9 @@ static void clipboard_received(const char *text, size_t len, bool uri_list, { struct seat *s = ud; struct wayland_display *c = s->conn; - struct wayland_surface *w = on ? surface_root(conn_surface_for(c, on)) : NULL; - if (!w) - w = c->paste_target ? c->paste_target : s->keyboard_focus; - if (!len || !w) return; + struct wayland_surface *w = conn_surface_for(c, on); + if (uri_list) w = surface_root(w); + if (!w || w->closed) return; struct yasl_input_event ev = { .surface = &w->base, .kind = uri_list ? YASL_INPUT_DROP_FILES : YASL_INPUT_PASTE, @@ -1216,6 +1215,7 @@ void seat_bind(struct wayland_display *c, struct wl_registry *registry, void seat_forget_surface(struct seat *s, struct wayland_surface *w) { + clipboard_forget_surface(s->clipboard, w->surface); struct wayland_surface **refs[] = { &s->pointer_focus, &s->keyboard_focus, &s->tablet_focus, &s->ime_focus, &s->focus_leaving, &s->ptr_left, diff --git a/src/wayland/surface.c b/src/wayland/surface.c index 8de4992..ef355ab 100644 --- a/src/wayland/surface.c +++ b/src/wayland/surface.c @@ -128,7 +128,7 @@ static inline bool display_has_immediate_work(const struct wayland_display *c) if (unlikely(!c || c->lost)) return false; for (struct wayland_surface *w = c->surfaces; w; w = w->conn_next) { bool ready_draw = w->want_draw & (w->frame_cb == NULL) & w->configured; - bool has_input = (w->input.count > 0); + bool has_input = (w->input.count > 0 || w->input.reset_pending); if (unlikely((ready_draw | has_input) & !w->closed)) return true; } @@ -250,7 +250,8 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc } if (!c->loop) goto err; if (spec) { - c->cbs = spec->cbs; + c->base.callbacks = spec->cbs ? *spec->cbs : (struct yasl_display_cbs){0}; + c->cbs = &c->base.callbacks; c->ud = spec->ud; if (spec->app_id) c->app_id = strdup(spec->app_id); } @@ -288,7 +289,7 @@ void wayland_display_close(struct wayland_display *c) uint32_t wayland_display_caps(const struct wayland_display *c) { if (!c) return 0; - uint32_t caps = YASL_CAP_POPUPS | YASL_CAP_CSD; + uint32_t caps = YASL_CAP_POPUPS | YASL_CAP_CSD | YASL_CAP_FRAME_PACING; struct seat *s = conn_active_seat(c); const struct wl_data_device *device = s ? clipboard_data_device(s->clipboard) : NULL; if (device && wl_data_device_get_version((struct wl_data_device *)device) >= 3) @@ -318,8 +319,6 @@ static void conn_unlink(struct wayland_surface *w) break; } } - if (c->paste_target == w) - c->paste_target = NULL; for (struct seat *s = c->seats; s; s = s->next) seat_forget_surface(s, w); w->conn = NULL; @@ -397,8 +396,8 @@ err: void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_surface_cbs *cbs, void *ud) { if (w && !w->closed) { - static const struct yasl_surface_cbs no_callbacks = {0}; - w->cbs = cbs ? cbs : &no_callbacks; + w->base.callbacks = cbs ? *cbs : (struct yasl_surface_cbs){0}; + w->cbs = &w->base.callbacks; w->ud = ud; } } -- cgit v1.2.3