summaryrefslogtreecommitdiff
path: root/src/platform/wayland
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 21:23:03 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 21:23:03 +0300
commitdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (patch)
tree3acc442bb4a3470364b74aa82ff67cb84d555c45 /src/platform/wayland
parentecb81aeea4c0c880b3a60a0dc8418c4bf2a7cf85 (diff)
public api refactor
Diffstat (limited to 'src/platform/wayland')
-rw-r--r--src/platform/wayland/api.h3
-rw-r--r--src/platform/wayland/backend.c78
-rw-r--r--src/platform/wayland/buffer.c15
-rw-r--r--src/platform/wayland/clipboard.c152
-rw-r--r--src/platform/wayland/clipboard.h9
-rw-r--r--src/platform/wayland/drag.c8
-rw-r--r--src/platform/wayland/ime.c5
-rw-r--r--src/platform/wayland/keyboard.c54
-rw-r--r--src/platform/wayland/pointer.c10
-rw-r--r--src/platform/wayland/shell.c7
-rw-r--r--src/platform/wayland/surface.c7
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;
}