summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-15 20:38:14 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-15 20:38:14 +0300
commitc2832a63547e6328afde25bb3b8145267eadef47 (patch)
treebf03ace79f01df10ddaffd70bea74678ab4ca219 /tests
parent3d012d707d0242780cd386868ab511846dc9b0af (diff)
Make the loop public and let the display drive it
An application that has its own descriptors and timers needed a second loop next to yasl's, and could not see yasl's key-repeat timer, clipboard pipes or reconnect timer. Now there is one wait: the application owns a yasl_loop, and yasl_init can run the display on it. - Public yasl_loop_*: descriptors, timers and signals. Descriptor callbacks return void. Timer IDs are 64 bits and never reused; a zero delay runs in the next step. A nested step or run fails with EBUSY, a step off the loop's thread with EPERM, and a quit made before a run ends it at once. An interrupted wait keeps its deadline. Creating a loop fails when it cannot make its wake pipe. - The display drives the loop through prepare, wait and check hooks instead of wrapping its step. Wayland finishes its read before any callback runs, so loop callbacks may create surfaces and do roundtrips. Readiness (queued events, an owed REFRESH) is derived in the step, so the wait never blocks over pending work. A draw that cannot proceed for want of a buffer is no longer counted as work. - yasl_init takes struct yasl_options. With loop and on_event, each step delivers events to on_event and yasl_wait_event fails with EBUSY. EALREADY only for the same options, EBUSY for others. - yasl_surface_request_frame: a REFRESH once the window can show a new frame, for pacing animation. - DISPLAY_LOST reports whether the display reconnects. Pull waits still fail with ENOTCONN after a final loss. - Events pushed from another thread wake the loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/benchmark.c8
-rw-r--r--tests/cocoa/test_native.c2
-rw-r--r--tests/common/test_contracts.c10
-rw-r--r--tests/common/test_gl.c4
-rw-r--r--tests/common/test_loop.c204
-rw-r--r--tests/common/test_surface_integration.c110
-rw-r--r--tests/common/test_timers.c128
-rw-r--r--tests/common/test_vulkan.c2
-rw-r--r--tests/test_lifecycle.c14
-rw-r--r--tests/wayland/test_clipboard.c8
-rw-r--r--tests/wayland/test_reconnect.c5
-rw-r--r--tests/x11/test_input.c8
-rw-r--r--tests/x11/test_tablet_native.c2
13 files changed, 395 insertions, 110 deletions
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 8fa8066..53c24f4 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -188,15 +188,15 @@ static uint64_t timer_dummy_cb(void *ud, yasl_private_timer_id id, uint64_t inte
static void bench_timers(void) {
const int iters = 2000000;
- struct yasl_private_loop *loop = yasl_private_loop_create();
+ struct yasl_loop *loop = yasl_loop_create();
uint64_t t0 = get_time_ns();
for (int i = 0; i < iters; i++) {
- yasl_private_timer_id id = yasl_private_loop_add_timer(loop, 1000000, timer_dummy_cb, NULL);
- yasl_private_loop_del_timer(loop, id);
+ yasl_private_timer_id id = yasl_loop_add_timer(loop, 1000000, timer_dummy_cb, NULL);
+ yasl_loop_del_timer(loop, id);
}
uint64_t t1 = get_time_ns();
- yasl_private_loop_destroy(loop);
+ yasl_loop_destroy(loop);
double ms = (double)(t1 - t0) / 1e6;
double per_cycle = (double)(t1 - t0) / iters;
char details[128];
diff --git a/tests/cocoa/test_native.c b/tests/cocoa/test_native.c
index d26a89d..7ff4426 100644
--- a/tests/cocoa/test_native.c
+++ b/tests/cocoa/test_native.c
@@ -61,7 +61,7 @@ static void test_window(enum yasl_private_backend request, bool null_spec)
yasl_private_surface_schedule_redraw(state.surface);
uint64_t deadline = yasl_private_loop_now_ns() + 3000000000ull;
while (!state.draws && yasl_private_loop_now_ns() < deadline) {
- yasl_private_display_dispatch(state.display, 0);
+ yasl_loop_step(yasl_private_display_loop(state.display), 0);
yasl_private_display_flush(state.display);
nanosleep(&(struct timespec){.tv_nsec = 1000000}, NULL);
}
diff --git a/tests/common/test_contracts.c b/tests/common/test_contracts.c
index f9f427f..004cd64 100644
--- a/tests/common/test_contracts.c
+++ b/tests/common/test_contracts.c
@@ -347,9 +347,6 @@ static bool popup_reposition(struct yasl_surface *popup,
static uint32_t popup_caps(const struct yasl_private_display *d)
{ (void)d; return YASL_PRIVATE_CAP_POPUPS; }
-static int dispatch_failure(struct yasl_private_display *d, int timeout)
-{ (void)d; (void)timeout; return -1; }
-
static struct yasl_surface *create_failure(struct yasl_private_display *d,
const struct yasl_private_window_spec *spec, void *device)
{ (void)d; (void)spec; (void)device; return NULL; }
@@ -372,8 +369,7 @@ static void test_errors(void)
.surface_create_toplevel = create_failure,
.surface_create_popup = popup_create,
.surface_popup_reposition = popup_reposition,
- .display_drag_start = drag_without_listener,
- .display_dispatch_timeout = dispatch_failure};
+ .display_drag_start = drag_without_listener};
struct yasl_private_display d = {.ops = &ops};
struct yasl_surface s = {.display = &d};
struct yasl_private_popup_spec spec = {.size = {120, 80}, .anchor = {0, 0, 1, 1}};
@@ -399,11 +395,7 @@ static void test_errors(void)
d.ops = &unsupported;
assert(!yasl_private_surface_create_popup(&s, &spec) && errno == ENOTSUP);
assert(!yasl_private_surface_popup_reposition(&s, &spec) && errno == ENOTSUP);
- assert(yasl_private_display_dispatch(&d, 0) == -1 && errno == ENOTSUP);
- assert(yasl_private_display_dispatch(NULL, 0) == -1 && errno == EINVAL);
d.ops = &ops;
- errno = ERANGE;
- assert(yasl_private_display_dispatch(&d, 0) == -1 && errno == EIO);
struct yasl_private_window_spec toplevel = {.size = {120, 80}};
errno = ERANGE;
assert(!yasl_private_surface_create_toplevel(&d, &toplevel) && errno == ENODEV);
diff --git a/tests/common/test_gl.c b/tests/common/test_gl.c
index 2bf3d8c..1bb5bec 100644
--- a/tests/common/test_gl.c
+++ b/tests/common/test_gl.c
@@ -77,8 +77,8 @@ static void wait_for_size(yasl_surface *surface, int width, int height)
int main(int argc, char **argv)
{
REQUIRE(argc == 2, "expected backend argument: wayland or x11");
- if (!strcmp(argv[1], "wayland")) REQUIRE(yasl_init(YASL_BACKEND_WAYLAND, NULL) == 0, "select Wayland backend");
- else if (!strcmp(argv[1], "x11")) REQUIRE(yasl_init(YASL_BACKEND_X11, NULL) == 0, "select X11 backend");
+ if (!strcmp(argv[1], "wayland")) REQUIRE(yasl_init(&(struct yasl_options){.backend = YASL_BACKEND_WAYLAND}) == 0, "select Wayland backend");
+ else if (!strcmp(argv[1], "x11")) REQUIRE(yasl_init(&(struct yasl_options){.backend = YASL_BACKEND_X11}) == 0, "select X11 backend");
else REQUIRE(false, "backend must be wayland or x11");
primary = yasl_surface_create(&(struct yasl_surface_options){.title="YASL GL test", .width=320, .height=240, .type=YASL_SURFACE_GL});
diff --git a/tests/common/test_loop.c b/tests/common/test_loop.c
index 5c49691..bdc33b7 100644
--- a/tests/common/test_loop.c
+++ b/tests/common/test_loop.c
@@ -4,7 +4,9 @@
#include <assert.h>
#include <errno.h>
+#include <poll.h>
#include <pthread.h>
+#include <stdint.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
@@ -29,7 +31,7 @@ static void on_alarm(int signo)
}
struct post_log {
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
char order[8];
int count;
};
@@ -57,7 +59,7 @@ static void post_b(void *ud)
static void test_post_order(void)
{
- struct yasl_private_loop *l = yasl_private_loop_create();
+ struct yasl_loop *l = yasl_loop_create();
assert(l);
assert(!yasl_private_loop_post(NULL, post_b, NULL));
assert(!yasl_private_loop_post(l, NULL, NULL));
@@ -65,20 +67,20 @@ static void test_post_order(void)
struct post_log log = {.loop = l};
assert(yasl_private_loop_post(l, post_a, &log));
assert(yasl_private_loop_post(l, post_b, &log));
- assert(yasl_private_loop_step(l, 0) >= 1);
+ assert(yasl_loop_step(l, 0) >= 1);
/* A post made while posts run waits for a later step. */
assert(log.count == 2 && memcmp(log.order, "ab", 2) == 0);
- assert(yasl_private_loop_step(l, 0) >= 1);
+ assert(yasl_loop_step(l, 0) >= 1);
assert(log.count == 3 && log.order[2] == 'c');
/* Destroy drops posts that never ran. */
assert(yasl_private_loop_post(l, post_b, &log));
- yasl_private_loop_destroy(l);
+ yasl_loop_destroy(l);
assert(log.count == 3);
}
struct thread_ctx {
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
bool kick;
int signo;
_Atomic bool ran;
@@ -105,27 +107,27 @@ static void *wake_thread(void *ud)
static void test_cross_thread(void)
{
- struct yasl_private_loop *l = yasl_private_loop_create();
+ struct yasl_loop *l = yasl_loop_create();
assert(l);
struct thread_ctx post = {.loop = l};
pthread_t t;
assert(pthread_create(&t, NULL, wake_thread, &post) == 0);
while (!post.ran)
- assert(yasl_private_loop_step(l, -1) >= 0);
+ assert(yasl_loop_step(l, -1) >= 0);
pthread_join(t, NULL);
/* A kick ends an indefinite wait without running anything. */
struct thread_ctx kick = {.loop = l, .kick = true};
assert(pthread_create(&t, NULL, wake_thread, &kick) == 0);
- assert(yasl_private_loop_step(l, -1) >= 1);
+ assert(yasl_loop_step(l, -1) >= 1);
pthread_join(t, NULL);
- yasl_private_loop_destroy(l);
+ yasl_loop_destroy(l);
}
struct signal_log {
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
int seen[NSIG];
int total;
bool unwatch;
@@ -138,7 +140,7 @@ static void on_signal(void *ud, int signo)
log->seen[signo]++;
log->total++;
if (log->unwatch)
- yasl_private_loop_unwatch_signals(log->loop);
+ yasl_loop_unwatch_signals(log->loop);
}
static volatile sig_atomic_t previous_handler_hits;
@@ -149,10 +151,10 @@ static void previous_handler(int signo)
previous_handler_hits++;
}
-static void step_until(struct yasl_private_loop *l, const int *counter, int want)
+static void step_until(struct yasl_loop *l, const int *counter, int want)
{
while (*counter < want)
- assert(yasl_private_loop_step(l, -1) >= 0);
+ assert(yasl_loop_step(l, -1) >= 0);
}
static void test_signals(void)
@@ -161,30 +163,26 @@ static void test_signals(void)
sigemptyset(&prev.sa_mask);
assert(sigaction(SIGUSR2, &prev, NULL) == 0);
- struct yasl_private_loop *l = yasl_private_loop_create();
- struct yasl_private_loop *other = yasl_private_loop_create();
+ struct yasl_loop *l = yasl_loop_create();
+ struct yasl_loop *other = yasl_loop_create();
assert(l && other);
struct signal_log log = {.loop = l};
const int bad[] = {SIGKILL};
- errno = 0;
- assert(!yasl_private_loop_watch_signals(l, bad, 1, on_signal, &log) && errno == EINVAL);
+ assert(yasl_loop_watch_signals(l, bad, 1, on_signal, &log) == -EINVAL);
const int sigs[] = {SIGUSR1, SIGUSR2, SIGCHLD};
- errno = 0;
- assert(!yasl_private_loop_watch_signals(l, sigs, 0, on_signal, &log) && errno == EINVAL);
- errno = 0;
- assert(!yasl_private_loop_watch_signals(l, sigs, 3, NULL, &log) && errno == EINVAL);
- assert(yasl_private_loop_watch_signals(l, sigs, 3, on_signal, &log));
+ assert(yasl_loop_watch_signals(l, sigs, 0, on_signal, &log) == -EINVAL);
+ assert(yasl_loop_watch_signals(l, sigs, 3, NULL, &log) == -EINVAL);
+ assert(yasl_loop_watch_signals(l, sigs, 3, on_signal, &log) == 0);
/* One signal belongs to one loop at a time. */
- errno = 0;
- assert(!yasl_private_loop_watch_signals(other, sigs, 1, on_signal, &log) && errno == EBUSY);
+ assert(yasl_loop_watch_signals(other, sigs, 1, on_signal, &log) == -EBUSY);
/* Deliveries before the callback runs coalesce per signal. */
raise(SIGUSR1);
raise(SIGUSR1);
raise(SIGUSR2);
- assert(yasl_private_loop_step(l, 0) >= 1);
+ assert(yasl_loop_step(l, 0) >= 1);
assert(log.seen[SIGUSR1] == 1 && log.seen[SIGUSR2] == 1);
assert(previous_handler_hits == 0);
@@ -203,13 +201,16 @@ static void test_signals(void)
int status;
assert(waitpid(child, &status, 0) == child);
- /* Replacing the watch restores the signals it drops. */
+ /* A loop has one watch, so a second cannot silently drop the first one's
+ * signals. Unwatching restores the previous actions. */
const int only_usr1[] = {SIGUSR1};
- assert(yasl_private_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
+ assert(yasl_loop_watch_signals(l, only_usr1, 1, on_signal, &log) == -EBUSY);
+ yasl_loop_unwatch_signals(l);
+ assert(yasl_loop_watch_signals(l, only_usr1, 1, on_signal, &log) == 0);
raise(SIGUSR2);
assert(previous_handler_hits == 1);
- assert(yasl_private_loop_watch_signals(other, (const int[]){SIGUSR2}, 1, on_signal, &log));
- yasl_private_loop_unwatch_signals(other);
+ assert(yasl_loop_watch_signals(other, (const int[]){SIGUSR2}, 1, on_signal, &log) == 0);
+ yasl_loop_unwatch_signals(other);
assert(previous_handler_hits == 1);
raise(SIGUSR2);
assert(previous_handler_hits == 2);
@@ -221,21 +222,153 @@ static void test_signals(void)
struct sigaction now;
assert(sigaction(SIGUSR1, NULL, &now) == 0);
assert(now.sa_handler == SIG_DFL);
- yasl_private_loop_unwatch_signals(l);
+ yasl_loop_unwatch_signals(l);
/* Destroy unwatches. */
log.unwatch = false;
- assert(yasl_private_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
- yasl_private_loop_destroy(l);
+ assert(yasl_loop_watch_signals(l, only_usr1, 1, on_signal, &log) == 0);
+ assert(yasl_loop_destroy(l) == 0);
assert(sigaction(SIGUSR1, NULL, &now) == 0);
assert(now.sa_handler == SIG_DFL);
- yasl_private_loop_destroy(other);
+ yasl_loop_destroy(other);
struct sigaction dfl = {.sa_handler = SIG_DFL};
sigemptyset(&dfl.sa_mask);
sigaction(SIGUSR2, &dfl, NULL);
}
+struct fd_log {
+ int calls;
+ short revents;
+};
+
+static void on_readable(void *ud, int fd, short revents)
+{
+ struct fd_log *log = ud;
+ char b;
+ if (revents & POLLIN)
+ assert(read(fd, &b, 1) == 1);
+ log->calls++;
+ log->revents = revents;
+}
+
+static void test_fds(void)
+{
+ yasl_loop *l = yasl_loop_create();
+ assert(l);
+ int p[2];
+ assert(pipe(p) == 0);
+ struct fd_log log = {0};
+ assert(yasl_loop_add_fd(l, -1, POLLIN, on_readable, &log) == -EINVAL);
+ assert(yasl_loop_add_fd(l, p[0], POLLIN, NULL, &log) == -EINVAL);
+ int id = yasl_loop_add_fd(l, p[0], POLLIN, on_readable, &log);
+ assert(id > 0);
+ assert(yasl_loop_step(l, 0) == 0 && log.calls == 0);
+ assert(write(p[1], "x", 1) == 1);
+ assert(yasl_loop_step(l, -1) == 1 && log.calls == 1 && (log.revents & POLLIN));
+ /* No requested events: a ready descriptor stays quiet. */
+ assert(yasl_loop_set_fd_events(l, id, 0) == 0);
+ assert(write(p[1], "x", 1) == 1);
+ assert(yasl_loop_step(l, 0) == 0 && log.calls == 1);
+ assert(yasl_loop_set_fd_events(l, id, POLLIN) == 0);
+ assert(yasl_loop_step(l, 0) == 1 && log.calls == 2);
+ assert(yasl_loop_del_fd(l, id) == 0);
+ assert(yasl_loop_del_fd(l, id) == -ENOENT);
+ assert(yasl_loop_set_fd_events(l, id, POLLIN) == -ENOENT);
+ assert(write(p[1], "x", 1) == 1);
+ assert(yasl_loop_step(l, 0) == 0 && log.calls == 2);
+ close(p[0]);
+ close(p[1]);
+ assert(yasl_loop_destroy(l) == 0);
+}
+
+struct reentry {
+ yasl_loop *loop;
+ int step, run;
+ bool quit;
+};
+
+static uint64_t reenter(void *ud, uint64_t id, uint64_t interval_ns)
+{
+ (void)id; (void)interval_ns;
+ struct reentry *r = ud;
+ r->step = yasl_loop_step(r->loop, 0);
+ r->run = yasl_loop_run(r->loop);
+ if (r->quit)
+ yasl_loop_quit(r->loop);
+ return 0;
+}
+
+static void *step_elsewhere(void *ud)
+{
+ return (void *)(intptr_t)yasl_loop_step(ud, 0);
+}
+
+static void test_reentry_and_quit(void)
+{
+ yasl_loop *l = yasl_loop_create();
+ assert(l);
+ /* A callback cannot step its own loop; the nested run keeps the outer quit. */
+ struct reentry r = {.loop = l, .quit = true};
+ assert(yasl_loop_add_timer(l, 0, reenter, &r));
+ assert(yasl_loop_run(l) == 0);
+ assert(r.step == -EBUSY && r.run == -EBUSY);
+
+ /* A quit before the run ends it at once, and the run clears it. */
+ yasl_loop_quit(l);
+ assert(yasl_loop_run(l) == 0);
+ r = (struct reentry){.loop = l, .quit = true};
+ assert(yasl_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), reenter, &r));
+ assert(yasl_loop_run(l) == 0 && r.step == -EBUSY);
+
+ /* Only the creating thread may step. */
+ pthread_t t;
+ void *result;
+ assert(pthread_create(&t, NULL, step_elsewhere, l) == 0);
+ pthread_join(t, &result);
+ assert((intptr_t)result == -EPERM);
+ assert(yasl_loop_destroy(l) == 0);
+}
+
+static void on_interrupt(int signo)
+{
+ (void)signo;
+}
+
+struct interrupter {
+ pthread_t target;
+ int delay_ms;
+};
+
+static void *interrupt_thread(void *ud)
+{
+ struct interrupter *i = ud;
+ sleep_ms(i->delay_ms);
+ pthread_kill(i->target, SIGUSR2);
+ return NULL;
+}
+
+/* An interrupted wait resumes with the time left, not the whole timeout. */
+static void test_interrupted_wait(void)
+{
+ struct sigaction sa = {.sa_handler = on_interrupt};
+ sigemptyset(&sa.sa_mask);
+ struct sigaction old;
+ assert(sigaction(SIGUSR2, &sa, &old) == 0);
+ yasl_loop *l = yasl_loop_create();
+ assert(l);
+ struct interrupter i = {.target = pthread_self(), .delay_ms = 60};
+ pthread_t t;
+ uint64_t start = yasl_time_ns();
+ assert(pthread_create(&t, NULL, interrupt_thread, &i) == 0);
+ assert(yasl_loop_step(l, 100) == 0);
+ uint64_t elapsed_ms = (yasl_time_ns() - start) / 1000000u;
+ pthread_join(t, NULL);
+ assert(elapsed_ms >= 90 && elapsed_ms < 140);
+ assert(yasl_loop_destroy(l) == 0);
+ sigaction(SIGUSR2, &old, NULL);
+}
+
int main(void)
{
signal(SIGALRM, on_alarm);
@@ -243,6 +376,9 @@ int main(void)
test_post_order();
test_cross_thread();
test_signals();
+ test_fds();
+ test_reentry_and_quit();
+ test_interrupted_wait();
printf("Loop tests passed.\n");
return 0;
}
diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c
index f33e35b..7862bfc 100644
--- a/tests/common/test_surface_integration.c
+++ b/tests/common/test_surface_integration.c
@@ -34,6 +34,102 @@ static void *wrong_thread(void *data)
assert(yasl_surface_get_native(data, &native) == -EPERM && !native.wl_display && !native.x11_display);
return NULL;
}
+struct callback_state {
+ yasl_loop *loop;
+ yasl_surface *window;
+ int refreshes;
+ int wait_result, shutdown_result;
+ yasl_surface *made;
+ int made_destroy;
+};
+static void on_event(void *userdata, const yasl_event *e)
+{
+ struct callback_state *st = userdata;
+ if (e->type == YASL_EVENT_REFRESH && e->surface == st->window) {
+ st->refreshes++;
+ int w = 0, h = 0;
+ uint32_t *pixels = yasl_cpu_pixels(e->surface, &w, &h);
+ assert(pixels && w > 0 && h > 0);
+ pixels[0] = 0xff336699u;
+ assert(yasl_cpu_present(e->surface) == 0);
+ }
+ yasl_event inner;
+ st->wait_result = yasl_wait_event(&inner, 0);
+ st->shutdown_result = yasl_shutdown();
+}
+/* A loop callback runs with the display idle, so surface creation and its
+ * roundtrips are allowed there. */
+static uint64_t create_in_timer(void *userdata, uint64_t id, uint64_t delay_ns)
+{
+ (void)id; (void)delay_ns;
+ struct callback_state *st = userdata;
+ st->made = yasl_surface_create(&(struct yasl_surface_options){
+ .title = "made by a timer", .width = 64, .height = 64});
+ assert(st->made);
+ st->made_destroy = yasl_surface_destroy(st->made);
+ return 0;
+}
+static uint64_t quit_in_timer(void *userdata, uint64_t id, uint64_t delay_ns)
+{
+ (void)id; (void)delay_ns;
+ yasl_loop_quit(userdata);
+ return 0;
+}
+static void step_until(struct callback_state *st, const int *counter, int want)
+{
+ uint64_t deadline = yasl_time_ns() + 5000000000ull;
+ while (*counter < want && yasl_time_ns() < deadline)
+ assert(yasl_loop_step(st->loop, 50) >= 0);
+ assert(*counter >= want);
+}
+static void test_callback_mode(enum yasl_backend backend)
+{
+ struct callback_state st = {.loop = yasl_loop_create()};
+ assert(st.loop);
+ const struct yasl_options options = {
+ .backend = backend, .loop = st.loop, .on_event = on_event, .userdata = &st};
+ assert(yasl_init(&options) == 0);
+ assert(yasl_init(&options) == -EALREADY);
+ assert(yasl_loop_destroy(st.loop) == -EBUSY);
+ yasl_event e;
+ assert(yasl_wait_event(&e, 0) == -EBUSY);
+ st.window = yasl_surface_create(&(struct yasl_surface_options){
+ .title = "callback mode", .width = 96, .height = 64});
+ assert(st.window);
+
+ /* Events reach on_event while the application only steps its loop. */
+ step_until(&st, &st.refreshes, 1);
+ assert(st.wait_result == -EBUSY && st.shutdown_result == -EBUSY);
+
+ /* Frame requests coalesce into one REFRESH, sent once the window can
+ * show a frame. */
+ int before = st.refreshes;
+ assert(yasl_surface_request_frame(st.window) == 0);
+ assert(yasl_surface_request_frame(st.window) == 0);
+ step_until(&st, &st.refreshes, before + 1);
+ for (int i = 0; i < 4; i++)
+ assert(yasl_loop_step(st.loop, 25) >= 0);
+ assert(st.refreshes == before + 1);
+
+ /* An idle loop waits instead of spinning. */
+ int steps = 0;
+ uint64_t end = yasl_time_ns() + 300000000ull;
+ while (yasl_time_ns() < end) {
+ assert(yasl_loop_step(st.loop, 100) >= 0);
+ steps++;
+ }
+ assert(steps < 30);
+
+ assert(yasl_loop_add_timer(st.loop, 0, create_in_timer, &st));
+ while (!st.made)
+ assert(yasl_loop_step(st.loop, 50) >= 0);
+ assert(st.made_destroy == 0);
+
+ assert(yasl_loop_add_timer(st.loop, YASL_PRIVATE_MS_TO_NS(10), quit_in_timer, st.loop));
+ assert(yasl_loop_run(st.loop) == 0);
+ assert(yasl_shutdown() == 0);
+ assert(yasl_loop_destroy(st.loop) == 0);
+}
static void push(yasl_surface *s, struct yasl_private_event event)
{
event.surface = s;
@@ -68,8 +164,11 @@ int main(int argc, char **argv)
enum yasl_backend backend = !strcmp(argv[1], "wayland") ? YASL_BACKEND_WAYLAND
: !strcmp(argv[1], "x11") ? YASL_BACKEND_X11
: YASL_BACKEND_COCOA;
- assert(yasl_init(backend, "org.yasl.surface-test") == 0);
- assert(yasl_init(backend, NULL) == -EALREADY);
+ const struct yasl_options options = {.backend = backend, .app_id = "org.yasl.surface-test"};
+ assert(yasl_init(&options) == 0);
+ assert(yasl_init(&options) == -EALREADY);
+ /* Other options would need another display. */
+ assert(yasl_init(&(struct yasl_options){.backend = backend}) == -EBUSY);
assert(yasl_get_backend() == backend);
unsigned features = yasl_get_features();
yasl_surface *s = yasl_surface_create(
@@ -329,16 +428,17 @@ int main(int argc, char **argv)
assert(yasl_surface_destroy(s) == 0);
if (popup)
assert(!listed(display, popup_id));
- assert(yasl_init(backend, NULL) == -EALREADY);
+ assert(yasl_init(&options) == -EALREADY);
s = yasl_surface_create(&(struct yasl_surface_options){.title = "shared backend remains",
.width = 64, .height = 64});
assert(s);
yasl_shutdown();
- assert(yasl_init(backend, NULL) == 0);
+ assert(yasl_init(&(struct yasl_options){.backend = backend}) == 0);
s = yasl_surface_create(
&(struct yasl_surface_options){.title = "reinitialized", .width = 64, .height = 64});
assert(s);
yasl_shutdown();
- puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed");
+ test_callback_mode(backend);
+ puts("public surface lifecycle, pixels, ownership, input, wake, refresh and callback mode passed");
return 0;
}
diff --git a/tests/common/test_timers.c b/tests/common/test_timers.c
index 2c3542f..3a35819 100644
--- a/tests/common/test_timers.c
+++ b/tests/common/test_timers.c
@@ -3,15 +3,17 @@
#include "common/types.h"
#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
struct test_ctx {
int count;
uint64_t last_time;
yasl_private_timer_id id;
yasl_private_timer_id other_id;
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
struct yasl_surface *surface;
bool done;
};
@@ -21,11 +23,32 @@ static uint64_t oneshot_cb(void *ud, yasl_private_timer_id id, uint64_t interval
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
- assert(interval_ns > 0);
+ (void)interval_ns;
ctx->count++;
return 0; /* Disarm */
}
+static uint64_t count_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
+{
+ (void)id; (void)interval_ns;
+ (*(int *)ud)++;
+ return 0;
+}
+
+/* Adds enough timers to move the timer array, then repeats itself. */
+static uint64_t grow_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
+{
+ struct test_ctx *ctx = ud;
+ assert(id == ctx->id);
+ if (ctx->count++ == 0) {
+ for (int i = 0; i < 64; i++)
+ assert(yasl_loop_add_timer(ctx->loop, YASL_PRIVATE_MS_TO_NS(60000), count_cb, NULL));
+ return YASL_PRIVATE_MS_TO_NS(2);
+ }
+ assert(interval_ns == YASL_PRIVATE_MS_TO_NS(2));
+ return 0;
+}
+
/* 2. Repeating timer: ticks N times, then returns 0. */
static uint64_t repeat_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
@@ -73,7 +96,7 @@ static uint64_t parent_timer_cb(void *ud, yasl_private_timer_id id, uint64_t int
struct test_ctx *ctx = ud;
assert(id == ctx->id);
ctx->count += 1;
- ctx->other_id = yasl_private_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
+ ctx->other_id = yasl_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
assert(ctx->other_id > 0);
return 0;
}
@@ -91,7 +114,7 @@ static uint64_t killer_timer_cb(void *ud, yasl_private_timer_id id, uint64_t int
(void)id; (void)interval_ns;
struct test_ctx *ctx = ud;
ctx->count++;
- assert(yasl_private_loop_del_timer(ctx->loop, ctx->other_id));
+ assert(yasl_loop_del_timer(ctx->loop, ctx->other_id));
return 0;
}
@@ -111,90 +134,109 @@ static uint64_t ms_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interva
static void test_loop_timers(void)
{
- struct yasl_private_loop *l = yasl_private_loop_create();
+ struct yasl_loop *l = yasl_loop_create();
assert(l);
/* Invalid arguments */
- assert(yasl_private_loop_add_timer(NULL, 1000, oneshot_cb, NULL) == 0);
- assert(yasl_private_loop_add_timer(l, 0, oneshot_cb, NULL) == 0);
- assert(yasl_private_loop_add_timer(l, 1000, NULL, NULL) == 0);
- assert(!yasl_private_loop_del_timer(NULL, 1));
- assert(!yasl_private_loop_del_timer(l, 0));
- assert(!yasl_private_loop_del_timer(l, 99999));
+ assert(yasl_loop_add_timer(NULL, 1000, oneshot_cb, NULL) == 0);
+ assert(yasl_loop_add_timer(l, 1000, NULL, NULL) == 0);
+ assert(!yasl_loop_del_timer(NULL, 1));
+ assert(!yasl_loop_del_timer(l, 0));
+ assert(!yasl_loop_del_timer(l, 99999));
assert(yasl_private_loop_next_timeout_ms(l) == -1);
/* Test 1: Single-shot */
struct test_ctx ctx1 = { .loop = l };
- ctx1.id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
+ ctx1.id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
assert(ctx1.id > 0);
assert(yasl_private_loop_next_timeout_ms(l) >= 0);
while (ctx1.count == 0) {
- int handled = yasl_private_loop_step(l, 50);
+ int handled = yasl_loop_step(l, 50);
assert(handled >= 0);
}
assert(ctx1.count == 1);
/* Should be disarmed and removed */
- assert(!yasl_private_loop_del_timer(l, ctx1.id));
+ assert(!yasl_loop_del_timer(l, ctx1.id));
assert(yasl_private_loop_next_timeout_ms(l) == -1);
/* Test 2: Repeating */
struct test_ctx ctx2 = { .loop = l };
- ctx2.id = yasl_private_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
+ ctx2.id = yasl_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
assert(ctx2.id > 0);
while (!ctx2.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx2.count == 5);
- assert(!yasl_private_loop_del_timer(l, ctx2.id));
+ assert(!yasl_loop_del_timer(l, ctx2.id));
/* Test 3: Reschedule dynamically */
struct test_ctx ctx3 = { .loop = l };
- ctx3.id = yasl_private_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
+ ctx3.id = yasl_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
assert(ctx3.id > 0);
while (!ctx3.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx3.count == 2);
/* Test 4: Timer cancellation before firing */
struct test_ctx ctx4 = { .loop = l };
- yasl_private_timer_id cancel_id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
+ yasl_private_timer_id cancel_id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
assert(cancel_id > 0);
- assert(yasl_private_loop_del_timer(l, cancel_id));
- assert(!yasl_private_loop_del_timer(l, cancel_id));
+ assert(yasl_loop_del_timer(l, cancel_id));
+ assert(!yasl_loop_del_timer(l, cancel_id));
/* Step for 10ms; timer should not fire */
- yasl_private_loop_step(l, 10);
+ yasl_loop_step(l, 10);
assert(ctx4.count == 0);
/* Test 5: Child timer added inside callback */
struct test_ctx ctx5 = { .loop = l };
- ctx5.id = yasl_private_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
+ ctx5.id = yasl_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
while (ctx5.count < 11) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx5.count == 11);
/* Test 6: Killer timer deletes victim timer before victim fires */
struct test_ctx ctx6 = { .loop = l };
- ctx6.id = yasl_private_loop_add_timer(l, 1000000ull, killer_timer_cb, &ctx6);
- ctx6.other_id = yasl_private_loop_add_timer(l, 10000000ull, victim_timer_cb, &ctx6);
+ ctx6.id = yasl_loop_add_timer(l, 1000000ull, killer_timer_cb, &ctx6);
+ ctx6.other_id = yasl_loop_add_timer(l, 10000000ull, victim_timer_cb, &ctx6);
while (ctx6.count == 0) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx6.count == 1);
- yasl_private_loop_step(l, 20);
+ yasl_loop_step(l, 20);
+
+ /* Test 8: Zero delay runs in the next step without waiting, and IDs are
+ * never handed out again. */
+ int zero_runs = 0;
+ yasl_private_timer_id zero = yasl_loop_add_timer(l, 0, count_cb, &zero_runs);
+ assert(zero > 0 && yasl_private_loop_next_timeout_ms(l) == 0);
+ assert(yasl_loop_step(l, -1) == 1 && zero_runs == 1);
+ yasl_private_timer_id next = yasl_loop_add_timer(l, 0, count_cb, &zero_runs);
+ assert(next > zero);
+ assert(!yasl_loop_del_timer(l, zero) && yasl_loop_del_timer(l, next));
+
+ /* Test 9: A callback that grows the timer array still reschedules itself. */
+ struct yasl_loop *grown = yasl_loop_create();
+ assert(grown);
+ struct test_ctx ctx9 = { .loop = grown };
+ ctx9.id = yasl_loop_add_timer(grown, 0, grow_cb, &ctx9);
+ while (ctx9.count < 2)
+ assert(yasl_loop_step(grown, 50) >= 0);
+ assert(!yasl_private_loop_timer_armed(grown, ctx9.id));
+ assert(yasl_loop_destroy(grown) == 0);
/* Test 7: Millisecond conversion */
struct test_ctx ctx7 = { .loop = l };
- ctx7.id = yasl_private_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), ms_timer_cb, &ctx7);
+ ctx7.id = yasl_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), ms_timer_cb, &ctx7);
assert(ctx7.id > 0);
while (!ctx7.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx7.count == 3);
- yasl_private_loop_destroy(l);
+ yasl_loop_destroy(l);
}
/* Surface timer tests */
@@ -220,14 +262,14 @@ static uint64_t surface_suicide_cb(void *ud, yasl_private_timer_id id, uint64_t
static void test_surface_timers(void)
{
- struct yasl_private_loop *loop = yasl_private_loop_create();
+ struct yasl_loop *loop = yasl_loop_create();
assert(loop);
struct yasl_private_display_spec spec = { .app_id = "org.yasl.timer_test" };
struct yasl_private_display *d = yasl_private_display_open(loop, &spec);
if (!d) {
/* Headless without display server */
- yasl_private_loop_destroy(loop);
+ yasl_loop_destroy(loop);
return;
}
@@ -243,10 +285,10 @@ static void test_surface_timers(void)
/* Application timers use the display's loop. */
struct test_ctx dctx = {0};
- dctx.id = yasl_private_loop_add_timer(yasl_private_display_loop(d), 2000000ull, oneshot_cb, &dctx);
+ dctx.id = yasl_loop_add_timer(yasl_private_display_loop(d), 2000000ull, oneshot_cb, &dctx);
assert(dctx.id > 0);
while (dctx.count == 0) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(dctx.count == 1);
@@ -255,12 +297,12 @@ static void test_surface_timers(void)
sctx.id = yasl_private_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx);
assert(sctx.id > 0);
while (sctx.count < 3) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(sctx.count >= 3);
assert(yasl_private_surface_del_timer(s, sctx.id));
int count_before = sctx.count;
- yasl_private_display_dispatch(d, 10);
+ yasl_loop_step(loop, 10);
assert(sctx.count == count_before);
/* A fired one-shot surface timer is retired, as a loop timer is. Many
@@ -270,7 +312,7 @@ static void test_surface_timers(void)
octx.id = yasl_private_surface_add_timer(s, 1000000ull, oneshot_cb, &octx);
assert(octx.id > 0);
while (octx.count == 0)
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
assert(!yasl_private_surface_del_timer(s, octx.id));
}
@@ -280,7 +322,7 @@ static void test_surface_timers(void)
assert(sctx2.id > 0);
yasl_private_surface_destroy(s);
/* Step display/loop; timer must not fire on dead surface */
- yasl_private_display_dispatch(d, 10);
+ yasl_loop_step(loop, 10);
assert(sctx2.count == 0);
/* Surface suicide from timer callback */
@@ -290,17 +332,19 @@ static void test_surface_timers(void)
sctx3.id = yasl_private_surface_add_timer(s, 2000000ull, surface_suicide_cb, &sctx3);
assert(sctx3.id > 0);
while (sctx3.count == 0) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(sctx3.count == 1);
assert(sctx3.surface == NULL);
yasl_private_display_close(d);
- yasl_private_loop_destroy(loop);
+ yasl_loop_destroy(loop);
}
int main(void)
{
+ /* A wait that never ends fails here, not at the suite timeout. */
+ alarm(10);
test_loop_timers();
test_surface_timers();
printf("Timer tests passed successfully.\n");
diff --git a/tests/common/test_vulkan.c b/tests/common/test_vulkan.c
index 4633d55..80f9cbe 100644
--- a/tests/common/test_vulkan.c
+++ b/tests/common/test_vulkan.c
@@ -41,7 +41,7 @@ static int run_test(enum yasl_backend backend)
VkSemaphore acquired = VK_NULL_HANDLE, rendered = VK_NULL_HANDLE;
VkCommandBuffer command = VK_NULL_HANDLE;
- if (yasl_init(backend, NULL) < 0) {
+ if (yasl_init(&(struct yasl_options){.backend = backend}) < 0) {
fprintf(stderr, "vulkan integration: cannot select requested backend %d (YASL error %d)\n",
backend, errno);
goto cleanup;
diff --git a/tests/test_lifecycle.c b/tests/test_lifecycle.c
index 41dafe6..7ba3f89 100644
--- a/tests/test_lifecycle.c
+++ b/tests/test_lifecycle.c
@@ -1,6 +1,11 @@
#include <yasl/yasl.h>
#include <assert.h>
#include <string.h>
+static void on_event(void *userdata, const yasl_event *event)
+{
+ (void)userdata;
+ (void)event;
+}
int main(void)
{
assert(yasl_shutdown() == 0);
@@ -8,7 +13,14 @@ int main(void)
yasl_event event = {.type = YASL_EVENT_QUIT};
assert(yasl_wait_event(&event, 0) == -ENODEV && event.type == YASL_EVENT_NONE);
assert(yasl_wait_event(NULL, 0) == -EINVAL);
- assert(yasl_init((enum yasl_backend)999, NULL) == -EINVAL);
+ assert(yasl_init(&(struct yasl_options){.backend = (enum yasl_backend)999}) == -EINVAL);
+ /* The loop and its event callback come together or not at all. */
+ yasl_loop *loop = yasl_loop_create();
+ assert(loop);
+ assert(yasl_init(&(struct yasl_options){.loop = loop}) == -EINVAL);
+ assert(yasl_init(&(struct yasl_options){.on_event = on_event}) == -EINVAL);
+ assert(yasl_loop_destroy(loop) == 0);
+ assert(yasl_surface_request_frame(NULL) == -ENODEV);
assert(yasl_get_backend() == YASL_BACKEND_AUTO && yasl_get_features() == 0);
assert(!yasl_surface_create(NULL) && errno == EINVAL);
struct yasl_surface_options options = {.width = 0, .height = 64};
diff --git a/tests/wayland/test_clipboard.c b/tests/wayland/test_clipboard.c
index 0ee74b6..f1427ab 100644
--- a/tests/wayland/test_clipboard.c
+++ b/tests/wayland/test_clipboard.c
@@ -39,7 +39,7 @@ static void receive(const char *text, size_t len, bool uri_list,
int main(void)
{
struct received received = {0};
- struct clipboard c = {.loop = yasl_private_loop_create(), .receive = receive, .ud = &received};
+ struct clipboard c = {.loop = yasl_loop_create(), .receive = receive, .ud = &received};
received.clipboard = &c;
assert(c.loop);
const struct { const char *bytes; size_t len; bool valid; } cases[] = {
@@ -62,7 +62,7 @@ int main(void)
assert(write(fds[1], cases[i].bytes, cases[i].len) == (ssize_t)cases[i].len);
close(fds[1]);
for (int steps = 0; c.transfers && steps < 10; steps++)
- assert(yasl_private_loop_step(c.loop, 0) >= 0);
+ assert(yasl_loop_step(c.loop, 0) >= 0);
assert(!c.transfers);
assert(!yasl_private_loop_timer_armed(c.loop, timeout_id));
assert(received.count == 1);
@@ -100,11 +100,11 @@ int main(void)
struct wl_surface *timeout_target = (struct wl_surface *)(uintptr_t)2;
timed->drop_surface = timeout_target;
yasl_private_timer_id timeout_id = timed->timeout;
- assert(yasl_private_loop_del_timer(c.loop, timeout_id));
+ assert(yasl_loop_del_timer(c.loop, timeout_id));
(void)transfer_timeout(timed, timeout_id, CLIPBOARD_TRANSFER_TIMEOUT_NS);
close(timeout_fds[1]);
assert(!c.transfers && received.count == 1);
assert(received.request_id == 100 && received.status == YASL_PRIVATE_TRANSFER_FAILED);
- yasl_private_loop_destroy(c.loop);
+ yasl_loop_destroy(c.loop);
return 0;
}
diff --git a/tests/wayland/test_reconnect.c b/tests/wayland/test_reconnect.c
index 891d98b..6bd6967 100644
--- a/tests/wayland/test_reconnect.c
+++ b/tests/wayland/test_reconnect.c
@@ -55,7 +55,7 @@ static VkSurfaceKHR vulkan_surface(void)
int main(void)
{
- CHECK(yasl_init(YASL_BACKEND_WAYLAND, NULL) == 0, "selecting Wayland");
+ CHECK(yasl_init(&(struct yasl_options){.backend = YASL_BACKEND_WAYLAND}) == 0, "selecting Wayland");
cpu = yasl_surface_create(&(struct yasl_surface_options){.title="reconnect CPU", .width=160, .height=120});
CHECK(cpu, "creating CPU window");
gl = yasl_surface_create(&(struct yasl_surface_options){.title="reconnect GL", .width=160, .height=120, .type=YASL_SURFACE_GL});
@@ -84,7 +84,8 @@ int main(void)
puts("ready");
fflush(stdout);
- expect(YASL_EVENT_DISPLAY_LOST, NULL, 10000);
+ yasl_event lost = expect(YASL_EVENT_DISPLAY_LOST, NULL, 10000);
+ CHECK(lost.action == YASL_LOST_RECONNECTING, "reporting a loss that reconnects");
struct yasl_native native;
CHECK(yasl_surface_get_native(cpu, &native) == -ENOTCONN && !native.wl_display && !native.wl_surface,
"rejecting native handles while offline");
diff --git a/tests/x11/test_input.c b/tests/x11/test_input.c
index aa534ca..b2b79d7 100644
--- a/tests/x11/test_input.c
+++ b/tests/x11/test_input.c
@@ -62,7 +62,7 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
0, 0, 1, 1, 0, 0, 0);
pending->target = s;
pending->id = (uint64_t)i + 1;
- pending->timeout = yasl_private_loop_add_timer(d->loop, PASTE_TIMEOUT_NS,
+ pending->timeout = yasl_loop_add_timer(d->loop, PASTE_TIMEOUT_NS,
paste_timeout, pending);
assert(pending->timeout);
pending->next = d->pastes;
@@ -89,7 +89,7 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
incr->window = XCreateSimpleWindow(d->native, DefaultRootWindow(d->native), 0, 0, 1, 1, 0, 0, 0);
incr->target = s;
incr->id = 9;
- incr->timeout = yasl_private_loop_add_timer(d->loop, PASTE_TIMEOUT_NS, paste_timeout, incr);
+ incr->timeout = yasl_loop_add_timer(d->loop, PASTE_TIMEOUT_NS, paste_timeout, incr);
assert(incr->timeout);
incr->next = d->pastes;
d->pastes = incr;
@@ -193,7 +193,7 @@ static void check_request_completion(struct x11_display *d, struct x11_surface *
assert(request_paste(&d->base, YASL_PRIVATE_CLIPBOARD, &s->base, 103));
struct paste_request *timed = d->pastes;
assert(timed && timed->id == 103 && timed->timeout);
- assert(yasl_private_loop_del_timer(d->loop, timed->timeout));
+ assert(yasl_loop_del_timer(d->loop, timed->timeout));
timed->timeout = 0;
paste_timeout(timed, 0, PASTE_TIMEOUT_NS);
event = wait_paste(&d->base, 103);
@@ -207,7 +207,7 @@ static void check_request_completion(struct x11_display *d, struct x11_surface *
yasl_private_timer_id timeout = d->pastes->timeout;
yasl_private_surface_destroy(cancel_target);
assert(d->pastes && !d->pastes->target && d->pastes->id == 0);
- assert(yasl_private_loop_del_timer(d->loop, timeout));
+ assert(yasl_loop_del_timer(d->loop, timeout));
d->pastes->timeout = 0;
XSelectionEvent late_reply = {
.requestor = d->pastes->window,
diff --git a/tests/x11/test_tablet_native.c b/tests/x11/test_tablet_native.c
index bbe39f2..8d44232 100644
--- a/tests/x11/test_tablet_native.c
+++ b/tests/x11/test_tablet_native.c
@@ -140,7 +140,7 @@ int main(int argc, char **argv)
{
assert(argc == 3); /* pen socket, eraser socket */
struct canvas_state app = {0};
- assert(yasl_init(YASL_BACKEND_X11, NULL) == 0);
+ assert(yasl_init(&(struct yasl_options){.backend = YASL_BACKEND_X11}) == 0);
yasl_surface *surface = yasl_surface_create(&(struct yasl_surface_options){.title="YASL native pressure test", .width=500, .height=400});
assert(surface && (yasl_get_features() & YASL_FEATURE_TABLET));
struct yasl_native native;