diff options
Diffstat (limited to 'src/platform/wayland')
| -rw-r--r-- | src/platform/wayland/api.h | 3 | ||||
| -rw-r--r-- | src/platform/wayland/backend.c | 78 | ||||
| -rw-r--r-- | src/platform/wayland/buffer.c | 15 | ||||
| -rw-r--r-- | src/platform/wayland/clipboard.c | 152 | ||||
| -rw-r--r-- | src/platform/wayland/clipboard.h | 9 | ||||
| -rw-r--r-- | src/platform/wayland/drag.c | 8 | ||||
| -rw-r--r-- | src/platform/wayland/ime.c | 5 | ||||
| -rw-r--r-- | src/platform/wayland/keyboard.c | 54 | ||||
| -rw-r--r-- | src/platform/wayland/pointer.c | 10 | ||||
| -rw-r--r-- | src/platform/wayland/shell.c | 7 | ||||
| -rw-r--r-- | src/platform/wayland/surface.c | 7 |
11 files changed, 285 insertions, 63 deletions
diff --git a/src/platform/wayland/api.h b/src/platform/wayland/api.h index 9f290f5..0f935b2 100644 --- a/src/platform/wayland/api.h +++ b/src/platform/wayland/api.h @@ -14,6 +14,9 @@ void wayland_display_flush(struct wayland_display *d); int wayland_display_modifiers(const struct wayland_display *d); void wayland_display_copy(struct wayland_display *d, enum yasl_selection sel, const char *text); void wayland_display_paste(struct wayland_display *d, enum yasl_selection sel, struct wayland_surface *target); +bool wayland_display_copy_text(struct wayland_display *d, enum yasl_selection sel, const char *text); +bool wayland_display_request_paste(struct wayland_display *d, enum yasl_selection sel, + struct wayland_surface *target, uint64_t request_id); bool wayland_display_drag_start(struct wayland_display *d, struct wayland_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud); void wayland_display_drag_cancel(struct wayland_display *d); struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *d, diff --git a/src/platform/wayland/backend.c b/src/platform/wayland/backend.c index 4585cd6..7026a8c 100644 --- a/src/platform/wayland/backend.c +++ b/src/platform/wayland/backend.c @@ -1,5 +1,6 @@ #include "platform/wayland/internal.h" #include "platform/freedesktop/dbus.h" +#include <errno.h> static struct yasl_display *impl_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec) { @@ -44,11 +45,28 @@ static void impl_display_copy(struct yasl_display *d, enum yasl_selection sel, c wayland_display_copy((struct wayland_display *)d, sel, text); } +static bool impl_display_copy_text(struct yasl_display *d, enum yasl_selection sel, + const char *text) +{ + bool ok = wayland_display_copy_text((struct wayland_display *)d, sel, text); + if (!ok && errno == 0) errno = ENOTSUP; + return ok; +} + static void impl_display_paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target) { wayland_display_paste((struct wayland_display *)d, sel, (struct wayland_surface *)target); } +static bool impl_display_request_paste(struct yasl_display *d, enum yasl_selection sel, + struct yasl_surface *target, uint64_t request_id) +{ + bool ok = wayland_display_request_paste((struct wayland_display *)d, sel, + (struct wayland_surface *)target, request_id); + if (!ok && errno == 0) errno = ENOTSUP; + return ok; +} + static bool impl_display_drag_start(struct yasl_display *d, struct yasl_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud) { return wayland_display_drag_start((struct wayland_display *)d, (struct wayland_surface *)origin, image, l, ud); @@ -82,6 +100,59 @@ static void impl_surface_destroy(struct yasl_surface *s) wayland_surface_destroy((struct wayland_surface *)s); } +static struct input_queue *impl_surface_input_queue(struct yasl_surface *s) +{ + struct wayland_surface *w = (struct wayland_surface *)s; + return w ? &w->input : NULL; +} + +static bool impl_surface_set_size(struct yasl_surface *s, struct yasl_vector2i size) +{ + struct wayland_surface *w = (struct wayland_surface *)s; + if (!w || w->closed || w->destroyed || !w->toplevel || + size.x <= 0 || size.y <= 0) { + errno = EINVAL; + return false; + } + errno = ENOTSUP; + return false; +} + +static bool impl_surface_set_fullscreen(struct yasl_surface *s, bool enabled) +{ + struct wayland_surface *w = (struct wayland_surface *)s; + if (!w || w->closed || w->destroyed || !w->toplevel) { + errno = EINVAL; + return false; + } + if (enabled) xdg_toplevel_set_fullscreen(w->toplevel, NULL); + else xdg_toplevel_unset_fullscreen(w->toplevel); + return true; +} + +static bool impl_surface_set_maximized(struct yasl_surface *s, bool enabled) +{ + struct wayland_surface *w = (struct wayland_surface *)s; + if (!w || w->closed || w->destroyed || !w->toplevel) { + errno = EINVAL; + return false; + } + if (enabled) xdg_toplevel_set_maximized(w->toplevel); + else xdg_toplevel_unset_maximized(w->toplevel); + return true; +} + +static bool impl_surface_minimize(struct yasl_surface *s) +{ + struct wayland_surface *w = (struct wayland_surface *)s; + if (!w || w->closed || w->destroyed || !w->toplevel) { + errno = EINVAL; + return false; + } + xdg_toplevel_set_minimized(w->toplevel); + return true; +} + static struct yasl_display *impl_surface_display(const struct yasl_surface *s) { const struct wayland_surface *w = (const struct wayland_surface *)s; @@ -219,12 +290,19 @@ const struct yasl_backend_ops yasl_wayland_backend = { .display_double_click_ms = impl_display_double_click_ms, .display_copy = impl_display_copy, .display_paste = impl_display_paste, + .display_copy_text = impl_display_copy_text, + .display_request_paste = impl_display_request_paste, .display_drag_start = impl_display_drag_start, .display_drag_cancel = impl_display_drag_cancel, .surface_create_toplevel = impl_surface_create_toplevel, .surface_create_popup = impl_surface_create_popup, .surface_popup_reposition = impl_surface_popup_reposition, .surface_destroy = impl_surface_destroy, + .surface_input_queue = impl_surface_input_queue, + .surface_set_size = impl_surface_set_size, + .surface_set_fullscreen = impl_surface_set_fullscreen, + .surface_set_maximized = impl_surface_set_maximized, + .surface_minimize = impl_surface_minimize, .surface_display = impl_surface_display, .surface_set_callbacks = impl_surface_set_callbacks, .surface_set_title = impl_surface_set_title, diff --git a/src/platform/wayland/buffer.c b/src/platform/wayland/buffer.c index b906f4f..874cc76 100644 --- a/src/platform/wayland/buffer.c +++ b/src/platform/wayland/buffer.c @@ -182,10 +182,13 @@ int apply_pending_geometry(struct wayland_surface *w) w->buffers[i].presented = false; } publish_surface_scale(w); - if (w->cbs->configure && (resized || rescaled)) - w->cbs->configure(&w->base, (struct yasl_geometry){ + if (resized || rescaled) { + yasl_surface_notify_configure(&w->base, (struct yasl_geometry){ .size = { .x = width, .y = height }, .scale_120 = w->scale_120, - }, w->ud); + }); + if (w->closed || w->destroyed) + return -1; + } return 0; } @@ -525,9 +528,11 @@ void surface_draw_frame(struct wayland_surface *w) }; w->frame_active = true; w->frame_presented = false; - w->cbs->draw(&w->base, &w->frame, w->ud); + yasl_surface_draw(&w->base, &w->frame); + if (w->closed || w->destroyed) + return; w->frame_active = false; - if (!w->closed && !w->frame_presented) + if (!w->frame_presented) w->frames_skipped++; } diff --git a/src/platform/wayland/clipboard.c b/src/platform/wayland/clipboard.c index 353e993..8ca9b93 100644 --- a/src/platform/wayland/clipboard.c +++ b/src/platform/wayland/clipboard.c @@ -5,6 +5,7 @@ #include <errno.h> #define CLIPBOARD_TEXT_MAX (256u * 1024) +#define CLIPBOARD_TRANSFER_TIMEOUT_NS (30ull * 1000000000ull) struct offer { struct offer *next; @@ -24,10 +25,14 @@ struct transfer { struct offer *drop; struct wl_surface *drop_surface; int fd, id; + yasl_timer_id timeout; char *text; size_t len, offset, capacity; + uint64_t request_id; bool sending; bool uri_list; + bool paste; + bool cancelled; }; struct clipboard { struct wl_display *display; @@ -82,20 +87,48 @@ static void drop_event(struct clipboard *c, enum yasl_drop_event ev) static void free_offer(struct offer *o); +static void transfer_end(struct transfer *t, bool complete); + +static uint64_t transfer_timeout(void *ud, yasl_timer_id id, uint64_t interval) +{ + (void)interval; + struct transfer *t = ud; + if (t->timeout != id) + return 0; + t->timeout = 0; + transfer_end(t, false); + return 0; +} + static void transfer_end(struct transfer *t, bool complete) { - struct transfer **p = &t->owner->transfers; + struct clipboard *owner = t->owner; + struct transfer **p = &owner->transfers; while (*p && *p != t) p = &(*p)->next; if (*p) *p = t->next; - yasl_loop_del_fd(t->owner->loop, t->id); + yasl_loop_del_fd(owner->loop, t->id); + if (t->timeout) + yasl_loop_del_timer(owner->loop, t->timeout); close(t->fd); if (t->drop) { if (complete && wl_data_offer_get_version(t->drop->proxy) >= WL_DATA_OFFER_FINISH_SINCE_VERSION) wl_data_offer_finish(t->drop->proxy); free_offer(t->drop); - wl_display_flush(t->owner->display); + wl_display_flush(owner->display); } + bool notify = owner->receive && !t->cancelled && + ((!t->sending && complete) || (t->paste && !complete)); + clipboard_receive_fn receive = owner->receive; + void *receive_ud = owner->ud; + struct wl_surface *surface = t->drop_surface; + uint64_t request_id = t->request_id; + bool uri_list = t->uri_list; + enum yasl_transfer_status status = complete ? YASL_TRANSFER_OK : YASL_TRANSFER_FAILED; + const char *text = complete ? (t->text ? t->text : "") : NULL; + size_t len = complete ? t->len : 0; + if (notify) + receive(text, len, uri_list, surface, request_id, status, receive_ud); free(t->text); free(t); } @@ -124,9 +157,6 @@ static int transfer_io(int fd, short events, void *ud) t->len += (size_t)n; } else if (n == 0) { bool valid = yasl_utf8_validate(t->text, t->len); - if (valid) - t->owner->receive(t->text ? t->text : "", t->len, t->uri_list, - t->drop_surface, t->owner->ud); transfer_end(t, valid); } else if (errno != EAGAIN && errno != EINTR) transfer_end(t, false); } @@ -148,10 +178,31 @@ static struct transfer *start_transfer_text(struct clipboard *c, int fd, bool se } t->id = yasl_loop_add_fd(c->loop, fd, sending ? POLLOUT : POLLIN, transfer_io, t); if (t->id < 0) { close(fd); free(t->text); free(t); return NULL; } + t->timeout = yasl_loop_add_timer(c->loop, CLIPBOARD_TRANSFER_TIMEOUT_NS, + transfer_timeout, t); + if (!t->timeout) { + yasl_loop_del_fd(c->loop, t->id); + close(fd); + free(t->text); + free(t); + return NULL; + } t->next = c->transfers; c->transfers = t; return t; } +static struct transfer *start_transfer_paste(struct clipboard *c, int fd, + struct wl_surface *target, uint64_t request_id) +{ + struct transfer *t = start_transfer_text(c, fd, false, false, NULL); + if (t) { + t->drop_surface = target; + t->request_id = request_id; + t->paste = true; + } + return t; +} + static const char *match_text_mime(const char *mime) { if (unlikely(!mime)) return NULL; @@ -528,15 +579,17 @@ bool clipboard_set_seat(struct clipboard *c, struct wl_seat *seat) return true; } -void clipboard_copy(struct clipboard *c, const char *text, uint32_t serial) +bool clipboard_copy(struct clipboard *c, const char *text, uint32_t serial) { - if (!c || !c->device || !text || !serial) return; + if (!c || !c->device) { errno = ENOTSUP; return false; } + if (!text) { errno = EINVAL; return false; } + if (!serial) { errno = EAGAIN; return false; } char *copy = strdup(text); - if (!copy) return; + if (!copy) { errno = ENOMEM; return false; } if (c->source) wl_data_source_destroy(c->source); free(c->text); c->text = copy; c->source = wl_data_device_manager_create_data_source(c->manager); - if (!c->source) return; + if (!c->source) { errno = ENOMEM; return false; } wl_data_source_add_listener(c->source, &source_listener, c); wl_data_source_offer(c->source, "text/plain;charset=utf-8"); wl_data_source_offer(c->source, "text/plain"); @@ -544,30 +597,26 @@ void clipboard_copy(struct clipboard *c, const char *text, uint32_t serial) wl_data_source_offer(c->source, "STRING"); wl_data_source_offer(c->source, "TEXT"); wl_data_device_set_selection(c->device, c->source, serial); + return true; } 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]); - struct transfer *t = start_transfer_text(c, fds[0], false, false, c->text); - if (t) t->drop_surface = target; - wl_display_flush(c->display); + if (c && target) + (void)clipboard_request_paste(c, YASL_CLIPBOARD, target, 0); } -void clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t serial) +bool clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t serial) { - if (!c || !text || !serial) return; - if (!c->primary_device || !c->primary_manager) return; + if (!c || !c->primary_device || !c->primary_manager) { errno = ENOTSUP; return false; } + if (!text) { errno = EINVAL; return false; } + if (!serial) { errno = EAGAIN; return false; } char *copy = strdup(text); - if (!copy) return; + if (!copy) { errno = ENOMEM; return false; } if (c->primary_source) zwp_primary_selection_source_v1_destroy(c->primary_source); free(c->primary_text); c->primary_text = copy; c->primary_source = zwp_primary_selection_device_manager_v1_create_source(c->primary_manager); - if (!c->primary_source) return; + if (!c->primary_source) { errno = ENOMEM; return false; } zwp_primary_selection_source_v1_add_listener(c->primary_source, &primary_source_listener, c); zwp_primary_selection_source_v1_offer(c->primary_source, "text/plain;charset=utf-8"); zwp_primary_selection_source_v1_offer(c->primary_source, "text/plain"); @@ -575,22 +624,58 @@ void clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t seri zwp_primary_selection_source_v1_offer(c->primary_source, "STRING"); zwp_primary_selection_source_v1_offer(c->primary_source, "TEXT"); zwp_primary_selection_device_v1_set_selection(c->primary_device, c->primary_source, serial); + return true; } 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) { - int fds[2]; - if (pipe2(fds, O_CLOEXEC) < 0) return; + if (c && target) + (void)clipboard_request_paste(c, YASL_PRIMARY, target, 0); +} + +bool clipboard_request_paste(struct clipboard *c, enum yasl_selection selection, + struct wl_surface *target, uint64_t request_id) +{ + if (!c || !target || !c->receive) + return false; + int fds[2]; + if (selection == YASL_PRIMARY) { + if (!c->primary_device || !c->primary_selection || !c->primary_selection->mime) { + c->receive(NULL, 0, false, target, request_id, + YASL_TRANSFER_UNAVAILABLE, c->ud); + return true; + } + if (pipe2(fds, O_CLOEXEC) < 0) { + c->receive(NULL, 0, false, target, request_id, + YASL_TRANSFER_FAILED, c->ud); + return true; + } zwp_primary_selection_offer_v1_receive(c->primary_selection->proxy, c->primary_selection->mime, fds[1]); close(fds[1]); - struct transfer *t = start_transfer_text(c, fds[0], false, false, c->text); - if (t) t->drop_surface = target; - wl_display_flush(c->display); - return; + } else { + if (!c->device || !c->selection || !c->selection->mime) { + c->receive(NULL, 0, false, target, request_id, + YASL_TRANSFER_UNAVAILABLE, c->ud); + return true; + } + if (pipe2(fds, O_CLOEXEC) < 0) { + c->receive(NULL, 0, false, target, request_id, + YASL_TRANSFER_FAILED, c->ud); + return true; + } + wl_data_offer_receive(c->selection->proxy, c->selection->mime, fds[1]); + close(fds[1]); + } + struct transfer *transfer = start_transfer_paste(c, fds[0], target, request_id); + if (!transfer) { + c->receive(NULL, 0, false, target, request_id, + YASL_TRANSFER_FAILED, c->ud); + return true; } + if (wl_display_flush(c->display) < 0 && errno != EAGAIN) + transfer_end(transfer, false); + return true; } void clipboard_forget_surface(struct clipboard *c, struct wl_surface *surface) @@ -598,7 +683,10 @@ 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_end(t, false); + if (t->drop_surface == surface) { + t->cancelled = true; + transfer_end(t, false); + } } if (c->drag_surface == surface) c->drag_surface = NULL; } diff --git a/src/platform/wayland/clipboard.h b/src/platform/wayland/clipboard.h index 9fefa8e..133cc14 100644 --- a/src/platform/wayland/clipboard.h +++ b/src/platform/wayland/clipboard.h @@ -15,7 +15,8 @@ struct clipboard; struct zwp_primary_selection_device_manager_v1; typedef void (*clipboard_receive_fn)(const char *, size_t, bool uri_list, - struct wl_surface *on, void *); + struct wl_surface *on, uint64_t request_id, + enum yasl_transfer_status, void *); struct clipboard *clipboard_create(struct wl_display *, struct wl_data_device_manager *, struct wl_seat *, struct yasl_loop *, @@ -23,10 +24,12 @@ struct clipboard *clipboard_create(struct wl_display *, struct wl_data_device_ma 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); +bool clipboard_copy(struct clipboard *, const char *, uint32_t); void clipboard_paste(struct clipboard *, struct wl_surface *target); +bool clipboard_request_paste(struct clipboard *, enum yasl_selection, + struct wl_surface *target, uint64_t request_id); void clipboard_forget_surface(struct clipboard *, struct wl_surface *); -void clipboard_copy_primary(struct clipboard *, const char *, uint32_t); +bool clipboard_copy_primary(struct clipboard *, const char *, uint32_t); void clipboard_paste_primary(struct clipboard *, struct wl_surface *target); typedef void (*clipboard_drag_fn)(enum yasl_drag_event, struct wl_surface *on, diff --git a/src/platform/wayland/drag.c b/src/platform/wayland/drag.c index 2cfd432..1f4a78b 100644 --- a/src/platform/wayland/drag.c +++ b/src/platform/wayland/drag.c @@ -228,9 +228,9 @@ void conn_drop_target(struct wayland_display *c, enum yasl_drop_event ev, (void)c; struct wayland_surface *w = on ? (struct wayland_surface *)wl_surface_get_user_data(on) : NULL; - if (!w || w->parent || !w->cbs->drop) + if (!w || w->parent || w->closed) return; - w->cbs->drop(&w->base, ev, drag_device_pos(w, x, y), w->ud); + yasl_surface_notify_drop(&w->base, ev, drag_device_pos(w, x, y)); } void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev, @@ -239,7 +239,7 @@ void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev, (void)c; struct wayland_surface *w = on ? (struct wayland_surface *)wl_surface_get_user_data(on) : NULL; - if (!w || w->parent || !w->cbs->drag) + if (!w || w->parent || w->closed) return; - w->cbs->drag(&w->base, ev, drag_device_pos(w, x, y), w->ud); + yasl_surface_notify_drag(&w->base, ev, drag_device_pos(w, x, y)); } diff --git a/src/platform/wayland/ime.c b/src/platform/wayland/ime.c index 9f1b27d..4a091d8 100644 --- a/src/platform/wayland/ime.c +++ b/src/platform/wayland/ime.c @@ -11,8 +11,11 @@ static void show_preedit(struct wayland_surface *w, char *text, int begin, int e w->ime_shown = text; w->ime_shown_begin = begin; w->ime_shown_end = end; - if (changed) + if (changed) { + yasl_surface_notify_composition(&w->base, w->ime_shown, + w->ime_shown_begin, w->ime_shown_end); wayland_surface_schedule_redraw(w); + } } void ime_reset(struct wayland_surface *w) diff --git a/src/platform/wayland/keyboard.c b/src/platform/wayland/keyboard.c index 038ba78..7f8274d 100644 --- a/src/platform/wayland/keyboard.c +++ b/src/platform/wayland/keyboard.c @@ -1,7 +1,7 @@ #include "internal.h" +#include <errno.h> #include "common/keyboard.h" #include "keymap.h" -#include <errno.h> #define XKB_EVDEV_OFFSET 8 #define KEYMAP_MAX_BYTES (8u * 1024 * 1024) @@ -427,27 +427,65 @@ int wayland_display_modifiers(const struct wayland_display *c) void wayland_display_copy(struct wayland_display *c, enum yasl_selection sel, const char *text) { + (void)wayland_display_copy_text(c, sel, text); +} + +bool wayland_display_copy_text(struct wayland_display *c, enum yasl_selection sel, + const char *text) +{ struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL; - if (!s || !s->clipboard) - return; - if (sel == YASL_PRIMARY) - clipboard_copy_primary(s->clipboard, text, s->input_serial); - else + if (!text) { + errno = EINVAL; + return false; + } + if (!s || !s->clipboard) { + errno = ENOTSUP; + return false; + } + if (!s->input_serial) { + errno = EAGAIN; + return false; + } + errno = 0; + bool ok = sel == YASL_PRIMARY ? + clipboard_copy_primary(s->clipboard, text, s->input_serial) : clipboard_copy(s->clipboard, text, s->input_serial); + return ok; } void wayland_display_paste(struct wayland_display *c, enum yasl_selection sel, struct wayland_surface *target) { struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL; - if (!s || !s->clipboard) + if (!target || target->closed || target->destroyed) return; + if (!s || !s->clipboard) { + yasl_surface_complete_paste(&target->base, 0, + YASL_TRANSFER_UNAVAILABLE, NULL, 0); return; - if (!target || target->closed) return; + } if (sel == YASL_PRIMARY) clipboard_paste_primary(s->clipboard, target->surface); else clipboard_paste(s->clipboard, target->surface); } +bool wayland_display_request_paste(struct wayland_display *c, enum yasl_selection sel, + struct wayland_surface *target, uint64_t request_id) +{ + struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL; + if (!target || target->closed || target->destroyed || !request_id) { + errno = EINVAL; + return false; + } + if (!s || !s->clipboard) { + errno = ENOTSUP; + return false; + } + errno = 0; + bool ok = clipboard_request_paste(s->clipboard, sel, target->surface, request_id); + if (!ok) errno = ENOMEM; + return ok; +} + bool wayland_surface_poll_event(struct wayland_surface *w, struct yasl_event *ev) { return w && ev && input_queue_pop(&w->input, ev); diff --git a/src/platform/wayland/pointer.c b/src/platform/wayland/pointer.c index cdc5780..da666da 100644 --- a/src/platform/wayland/pointer.c +++ b/src/platform/wayland/pointer.c @@ -1034,13 +1034,19 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { }; static void clipboard_received(const char *text, size_t len, bool uri_list, - struct wl_surface *on, void *ud) + struct wl_surface *on, uint64_t request_id, + enum yasl_transfer_status status, void *ud) { (void)ud; struct wayland_surface *w = on ? (struct wayland_surface *)wl_surface_get_user_data(on) : NULL; if (uri_list) w = surface_root(w); - if (!w || w->closed) return; + if (!w || w->closed || w->destroyed) return; + if (!uri_list) { + yasl_surface_complete_paste(&w->base, request_id, status, text, len); + return; + } + if (status != YASL_TRANSFER_OK) return; struct yasl_event ev = { .surface = &w->base, .type = uri_list ? YASL_EVENT_DROP : YASL_EVENT_PASTE, diff --git a/src/platform/wayland/shell.c b/src/platform/wayland/shell.c index 8795989..fc2ce2e 100644 --- a/src/platform/wayland/shell.c +++ b/src/platform/wayland/shell.c @@ -277,8 +277,7 @@ static void set_state(struct wayland_surface *w, uint32_t state) { if (state == w->base.state) return; w->base.state = state; - if (w->cbs && w->cbs->state) - w->cbs->state(&w->base, state, w->ud); + yasl_surface_notify_state(&w->base, state); } static void toplevel_configure(void *data, struct xdg_toplevel *toplevel, @@ -316,8 +315,8 @@ static void toplevel_close(void *data, struct xdg_toplevel *toplevel) { (void)toplevel; struct wayland_surface *w = data; - if (w && w->cbs && w->cbs->close) - w->cbs->close(&w->base, w->ud); + if (w && !w->closed) + yasl_surface_notify_close(&w->base); } static void toplevel_configure_bounds(void *data, struct xdg_toplevel *toplevel, diff --git a/src/platform/wayland/surface.c b/src/platform/wayland/surface.c index cf1877d..2e85e2b 100644 --- a/src/platform/wayland/surface.c +++ b/src/platform/wayland/surface.c @@ -52,8 +52,7 @@ static void display_lose(struct wayland_display *c) surface_fail(w); } display_leave(c); - if (c->cbs && c->cbs->lost) - c->cbs->lost(c->ud); + yasl_display_notify_event(&c->base, YASL_EVENT_DISPLAY_LOST); } void surface_fail(struct wayland_surface *w) @@ -61,8 +60,7 @@ void surface_fail(struct wayland_surface *w) if (w->closed) return; w->closed = true; - if (w->cbs->close) - w->cbs->close(&w->base, w->ud); + yasl_surface_notify_close(&w->base); } static int display_ready(int fd, short revents, void *ud) @@ -395,6 +393,7 @@ void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_ { if (w && !w->closed) { w->base.callbacks = cbs ? *cbs : (struct yasl_window_cbs){0}; + w->base.ud = ud; w->cbs = &w->base.callbacks; w->ud = ud; } |
