summaryrefslogtreecommitdiff
path: root/tests/common
diff options
context:
space:
mode:
Diffstat (limited to 'tests/common')
-rw-r--r--tests/common/test_app.c204
-rw-r--r--tests/common/test_backends.c302
-rw-r--r--tests/common/test_contracts.c300
-rw-r--r--tests/common/test_desktop.c72
-rw-r--r--tests/common/test_events.c169
-rw-r--r--tests/common/test_gl.c158
-rw-r--r--tests/common/test_gl_options.c16
-rw-r--r--tests/common/test_hello_example.c20
-rw-r--r--tests/common/test_input_alloc.c14
-rw-r--r--tests/common/test_keyboard.c44
-rw-r--r--tests/common/test_loop.c76
-rw-r--r--tests/common/test_selection.c20
-rw-r--r--tests/common/test_surface_integration.c90
-rw-r--r--tests/common/test_tablet_example.c65
-rw-r--r--tests/common/test_timers.c148
-rw-r--r--tests/common/test_utf8.c22
-rw-r--r--tests/common/test_vulkan.c389
17 files changed, 1236 insertions, 873 deletions
diff --git a/tests/common/test_app.c b/tests/common/test_app.c
deleted file mode 100644
index 214d8f2..0000000
--- a/tests/common/test_app.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#define _DEFAULT_SOURCE
-#include "yasl/app.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
-
-struct test_state {
- struct yasl_display *display;
- struct yasl_surface *surface;
- bool init_called;
- bool frame_called;
- bool user_event_called;
- bool timer_called;
- bool quit_called;
- int frame_count;
- yasl_timer_id timer_id;
- pthread_t worker;
- uint64_t target_id;
-};
-
-static void *worker_thread(void *arg)
-{
- struct test_state *state = arg;
- usleep(50000); /* 50ms */
- bool ok = yasl_display_post(state->display, &(struct yasl_message){
- .target_id = state->target_id, .code = 42, .payload = (void *)0x1234});
- assert(ok);
- return NULL;
-}
-
-static uint64_t on_timer(void *ud, yasl_timer_id id, uint64_t interval_ns)
-{
- (void)id;
- (void)interval_ns;
- struct test_state *state = ud;
- state->timer_called = true;
- yasl_surface_request_frame(state->surface);
- return 0; /* one-shot */
-}
-
-static enum yasl_app_result on_init(void *ud, struct yasl_display *d)
-{
- struct test_state *state = ud;
- state->display = d;
- state->init_called = true;
-
- struct yasl_window_spec spec = {
- .title = "App Runner Test",
- .size = {320, 240},
- };
- state->surface = yasl_surface_create_toplevel(d, &spec);
- assert(state->surface != NULL);
-
- yasl_surface_set_pacing(state->surface, YASL_PACING_ON_DEMAND);
- yasl_surface_set_pointer_mode(state->surface, YASL_POINTER_RELATIVE);
- yasl_surface_set_pointer_mode(state->surface, YASL_POINTER_NORMAL);
-
- state->timer_id = yasl_loop_add_timer(yasl_display_loop(d), YASL_MS_TO_NS(20), on_timer, state);
- assert(state->timer_id > 0);
-
- state->target_id = yasl_surface_id(state->surface);
- int err = pthread_create(&state->worker, NULL, worker_thread, state);
- assert(err == 0);
-
-
- yasl_surface_request_frame(state->surface);
- return YASL_APP_CONTINUE;
-}
-
-static enum yasl_app_result on_event(void *ud, const struct yasl_event *ev)
-{
- struct test_state *state = ud;
- if (ev->type == YASL_EVENT_USER) {
- assert(ev->user.code == 42);
- assert(ev->user.payload == (void *)0x1234);
- state->user_event_called = true;
- yasl_surface_request_frame(state->surface);
- } else if (ev->type == YASL_EVENT_WINDOW_CLOSE) {
- return YASL_APP_QUIT;
- }
- return YASL_APP_CONTINUE;
-}
-
-static void on_frame(void *ud, struct yasl_surface *s, struct yasl_frame *ctx)
-{
- struct test_state *state = ud;
- assert(s == state->surface);
- assert(ctx->surface == s);
- state->frame_called = true;
- state->frame_count++;
-
- if (ctx->target.pixels) {
- size_t count = (size_t)ctx->target.size.x * ctx->target.size.y;
- for (size_t i = 0; i < count; i++) {
- ctx->target.pixels[i] = 0xff204060;
- }
- bool ok = yasl_frame_present(ctx, NULL, 0);
- assert(ok);
- }
-
- if (state->user_event_called) {
- yasl_surface_destroy(state->surface);
- }
-}
-
-static void on_quit(void *ud, struct yasl_display *d)
-{
- (void)d;
- struct test_state *state = ud;
- assert(!pthread_join(state->worker, NULL));
- state->quit_called = true;
-}
-
-static void present_once(void *ud, struct yasl_surface *s, struct yasl_frame *ctx)
-{
- (*(int *)ud)++;
- if (ctx->target.pixels)
- assert(yasl_frame_present(ctx, NULL, 0));
- yasl_surface_destroy(s);
-}
-
-/* desc.window replaces init: the runner creates the toplevel and draws it. */
-static void test_window_without_init(void)
-{
- int frames = 0;
- struct yasl_window_spec window = {.title = "App Runner Window", .size = {160, 120}};
- int res = yasl_run(&(struct yasl_app_desc){
- .app_id = "org.yasl.test.app.window",
- .userdata = &frames,
- .window = &window,
- .frame = present_once,
- });
- assert(res == 0);
- assert(frames == 1);
-}
-
-
-static enum yasl_app_result fail_init(void *ud, struct yasl_display *d)
-{
- (void)ud; (void)d;
- return YASL_APP_ERROR;
-}
-static void count_quit(void *ud, struct yasl_display *d)
-{
- (void)d;
- (*(int *)ud)++;
-}
-static enum yasl_app_result inspect_initial_window(void *ud, struct yasl_display *d)
-{
- struct yasl_surface *s = yasl_app_window(d);
- assert(s && yasl_surface_userdata(s) == ud);
- errno = 0;
- assert(!yasl_surface_set_callbacks(s, NULL, NULL) && errno == EBUSY);
- return YASL_APP_CONTINUE;
-}
-static void fail_frame(void *ud, struct yasl_surface *s, struct yasl_frame *frame)
-{
- (void)ud;
- assert(frame->surface == s && frame->target.stride_bytes == frame->target.size.x * 4);
- yasl_app_exit(yasl_surface_display(s), YASL_APP_ERROR);
-}
-static void test_error_lifecycle(void)
-{
- int quits = 0;
- assert(yasl_run(&(struct yasl_app_desc){.userdata = &quits,
- .init = fail_init, .quit = count_quit}) < 0);
- assert(quits == 1 && errno == EIO);
- struct yasl_window_spec window = {.size_logical = {160, 120}, .userdata = &quits};
- assert(yasl_run(&(struct yasl_app_desc){.userdata = &quits, .window = &window,
- .init = inspect_initial_window, .frame = fail_frame, .quit = count_quit}) < 0);
- assert(quits == 2 && errno == EIO);
-}
-
-int main(void)
-{
- struct test_state state = {0};
- struct yasl_app_desc desc = {
- .app_id = "org.yasl.test.app",
- .backend = YASL_BACKEND_AUTO,
- .userdata = &state,
- .init = on_init,
- .event = on_event,
- .frame = on_frame,
- .quit = on_quit,
- };
-
- int res = yasl_run(&desc);
- if (res < 0 && !state.init_called &&
- (errno == EPERM || errno == EACCES || errno == ENOENT ||
- errno == ECONNREFUSED || errno == ENODEV)) return 77;
- assert(res == 0);
- assert(state.init_called);
- assert(state.frame_called);
- assert(state.user_event_called);
- assert(state.timer_called);
- assert(state.quit_called);
- test_window_without_init();
- test_error_lifecycle();
- printf("App runner tests passed!\n");
- return 0;
-}
diff --git a/tests/common/test_backends.c b/tests/common/test_backends.c
index 30f9b67..7eba57f 100644
--- a/tests/common/test_backends.c
+++ b/tests/common/test_backends.c
@@ -1,13 +1,13 @@
#define _POSIX_C_SOURCE 200809L
-#include "yasl/native.h"
+#include "common/private_native.h"
#if YASL_HAS_WAYLAND
-#include "yasl/native/wayland.h"
+#include "common/private_native_wayland.h"
#endif
#if YASL_HAS_X11
-#include "yasl/native/x11.h"
+#include "common/private_native_x11.h"
#endif
-#include "yasl/loop.h"
-#include "yasl/yasl.h"
+#include "common/private_loop.h"
+#include "common/types.h"
#include <X11/Xatom.h>
#include <X11/Xlib.h>
@@ -24,14 +24,14 @@
struct window {
struct yasl_surface *surface;
- struct yasl_display *display;
+ struct yasl_private_display *display;
int draws, configures, closes;
bool destroy_on_draw, destroy_on_configure;
};
struct pump {
- struct yasl_loop *loop;
- struct yasl_display *displays[2];
+ struct yasl_private_loop *loop;
+ struct yasl_private_display *displays[2];
int ticks;
};
@@ -43,76 +43,76 @@ static int tick(int fd, short events, void *ud)
struct pump *p = ud;
for (int i = 0; i < 2; i++) {
if (p->displays[i]) {
- yasl_display_dispatch(p->displays[i], 0);
- yasl_display_flush(p->displays[i]);
+ yasl_private_display_dispatch(p->displays[i], 0);
+ yasl_private_display_flush(p->displays[i]);
}
}
- if (--p->ticks == 0) yasl_loop_quit(p->loop);
+ if (--p->ticks == 0) yasl_private_loop_quit(p->loop);
return 0;
}
-static void pump(struct yasl_loop *loop, struct yasl_display *a, struct yasl_display *b)
+static void pump(struct yasl_private_loop *loop, struct yasl_private_display *a, struct yasl_private_display *b)
{
int timer = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
assert(timer >= 0);
struct pump p = {.loop = loop, .displays = {a, b}, .ticks = 20};
struct itimerspec spec = {.it_value.tv_nsec = 10000000, .it_interval.tv_nsec = 10000000};
assert(timerfd_settime(timer, 0, &spec, NULL) == 0);
- int watch = yasl_loop_add_fd(loop, timer, POLLIN, tick, &p);
+ int watch = yasl_private_loop_add_fd(loop, timer, POLLIN, tick, &p);
assert(watch > 0);
- assert(yasl_loop_run(loop) == 0);
- assert(yasl_loop_del_fd(loop, watch) == 0);
+ assert(yasl_private_loop_run(loop) == 0);
+ assert(yasl_private_loop_del_fd(loop, watch) == 0);
close(timer);
}
-static void draw(struct yasl_surface *s, struct yasl_frame *frame, void *ud)
+static void draw(struct yasl_surface *s, struct yasl_private_frame *frame, void *ud)
{
struct window *w = ud;
assert(s == w->surface);
assert(frame->surface == s);
- assert(yasl_surface_display(s) == w->display);
- struct yasl_vector2i size = yasl_surface_geometry(s).size;
+ assert(yasl_private_surface_display(s) == w->display);
+ struct yasl_private_vector2i size = yasl_private_surface_geometry(s).size;
assert(size.x == frame->target.size.x && size.y == frame->target.size.y);
assert(frame->target.pixels);
- struct yasl_native_frame native = {0};
- assert(!yasl_surface_get_native_frame(s, &frame->target, &native));
+ struct yasl_private_native_frame native = {0};
+ assert(!yasl_private_surface_get_native_frame(s, &frame->target, &native));
for (int i = 0; i < size.x * size.y; i++) frame->target.pixels[i] = 0xff4080c0;
- struct yasl_damage_list damage = {.n = YASL_DAMAGE_MAX + 1};
- assert(!yasl_surface_present(s, &frame->target, &damage));
+ struct yasl_private_damage_list damage = {.n = YASL_PRIVATE_DAMAGE_MAX + 1};
+ assert(!yasl_private_surface_present(s, &frame->target, &damage));
damage.n = -2;
- assert(!yasl_surface_present(s, &frame->target, &damage));
+ assert(!yasl_private_surface_present(s, &frame->target, &damage));
damage.n = 1;
damage.rects[0].width = -1;
- assert(!yasl_surface_present(s, &frame->target, &damage));
+ assert(!yasl_private_surface_present(s, &frame->target, &damage));
damage.n = -1;
- struct yasl_framebuffer invalid = frame->target;
+ struct yasl_private_framebuffer invalid = frame->target;
invalid.size.x++;
- assert(!yasl_surface_present(s, &invalid, &damage));
+ assert(!yasl_private_surface_present(s, &invalid, &damage));
invalid = frame->target;
invalid.generation--;
- assert(!yasl_surface_present(s, &invalid, &damage));
+ assert(!yasl_private_surface_present(s, &invalid, &damage));
invalid = frame->target;
invalid.pixels = (uint32_t *)(uintptr_t)1;
- assert(!yasl_surface_present(s, &invalid, &damage));
- assert(!yasl_surface_present(s, &frame->target, NULL));
- assert(yasl_surface_present(s, &frame->target, &damage));
- assert(!yasl_surface_present(s, &frame->target, &damage));
+ assert(!yasl_private_surface_present(s, &invalid, &damage));
+ assert(!yasl_private_surface_present(s, &frame->target, NULL));
+ assert(yasl_private_surface_present(s, &frame->target, &damage));
+ assert(!yasl_private_surface_present(s, &frame->target, &damage));
w->draws++;
- if (w->destroy_on_draw) { yasl_surface_destroy(s); w->surface = NULL; }
+ if (w->destroy_on_draw) { yasl_private_surface_destroy(s); w->surface = NULL; }
}
-static void configure(struct yasl_surface *s, struct yasl_geometry geometry, void *ud)
+static void configure(struct yasl_surface *s, struct yasl_private_geometry geometry, void *ud)
{
struct window *w = ud;
assert(w->surface == s);
- struct yasl_vector2i size = yasl_surface_geometry(s).size;
+ struct yasl_private_vector2i size = yasl_private_surface_geometry(s).size;
assert(geometry.size.x == size.x && geometry.size.y == size.y);
- assert(geometry.scale_120 == yasl_surface_geometry(s).scale_120);
+ assert(geometry.scale_120 == yasl_private_surface_geometry(s).scale_120);
w->configures++;
- if (w->destroy_on_configure) { yasl_surface_destroy(s); w->surface = NULL; }
+ if (w->destroy_on_configure) { yasl_private_surface_destroy(s); w->surface = NULL; }
}
-static void draw_without_present(struct yasl_surface *s, struct yasl_frame *frame, void *ud)
+static void draw_without_present(struct yasl_surface *s, struct yasl_private_frame *frame, void *ud)
{
(void)s;
struct window *w = ud;
@@ -126,62 +126,62 @@ static void close_window(struct yasl_surface *s, void *ud)
struct window *w = ud;
assert(s == w->surface);
w->closes++;
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
w->surface = NULL;
}
-static const struct yasl_window_cbs callbacks = {
+static const struct yasl_private_window_cbs callbacks = {
.draw = draw, .configure = configure, .close = close_window,
};
static void attach(struct window *w)
{
- struct yasl_window_cbs temporary = callbacks;
- yasl_surface_set_callbacks(w->surface, &temporary, w);
+ struct yasl_private_window_cbs temporary = callbacks;
+ yasl_private_surface_set_callbacks(w->surface, &temporary, w);
temporary.draw = NULL;
temporary.configure = NULL;
temporary.close = NULL;
}
-static struct window create(struct yasl_display *d)
+static struct window create(struct yasl_private_display *d)
{
- struct yasl_window_spec spec = {.title = "Backend test", .size = {160, 100}};
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &spec);
+ struct yasl_private_window_spec spec = {.title = "Backend test", .size = {160, 100}};
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &spec);
assert(s);
- assert(yasl_display_get_native_handle(d));
- assert(yasl_surface_get_native_handle(s));
- assert(yasl_surface_display(s) == d);
- assert(yasl_surface_timing(s).source == YASL_TIMING_UNKNOWN);
+ assert(yasl_private_display_get_native_handle(d));
+ assert(yasl_private_surface_get_native_handle(s));
+ assert(yasl_private_surface_display(s) == d);
+ assert(yasl_private_surface_timing(s).source == YASL_PRIVATE_TIMING_UNKNOWN);
return (struct window){.surface = s, .display = d};
}
/* The last presented frame reads back until a later draw replaces it. */
-static void test_read_pixels(struct yasl_loop *loop, struct yasl_display *d, struct window *w)
+static void test_read_pixels(struct yasl_private_loop *loop, struct yasl_private_display *d, struct window *w)
{
- struct yasl_vector2i size = {-1, -1};
- assert(!yasl_surface_read_pixels(w->surface, NULL, 0, NULL));
- assert(!yasl_surface_read_pixels(NULL, NULL, 0, &size) && !size.x && !size.y);
- assert(!yasl_surface_read_pixels(w->surface, NULL, 0, &size));
- struct yasl_vector2i extent = yasl_surface_geometry(w->surface).size;
+ struct yasl_private_vector2i size = {-1, -1};
+ assert(!yasl_private_surface_read_pixels(w->surface, NULL, 0, NULL));
+ assert(!yasl_private_surface_read_pixels(NULL, NULL, 0, &size) && !size.x && !size.y);
+ assert(!yasl_private_surface_read_pixels(w->surface, NULL, 0, &size));
+ struct yasl_private_vector2i extent = yasl_private_surface_geometry(w->surface).size;
assert(size.x == extent.x && size.y == extent.y);
size_t count = (size_t)size.x * (size_t)size.y;
uint32_t *pixels = calloc(count, sizeof(*pixels));
assert(pixels);
- assert(!yasl_surface_read_pixels(w->surface, pixels, count - 1, &size));
+ assert(!yasl_private_surface_read_pixels(w->surface, pixels, count - 1, &size));
assert(!pixels[0]);
- assert(yasl_surface_read_pixels(w->surface, pixels, count, &size));
+ assert(yasl_private_surface_read_pixels(w->surface, pixels, count, &size));
for (size_t i = 0; i < count; i++) assert(pixels[i] == 0xff4080c0);
/* Draws that never present must not show through. X11 reuses its one
* target; Wayland keeps the presented buffer while the compositor holds it. */
- struct yasl_window_cbs skip = callbacks;
+ struct yasl_private_window_cbs skip = callbacks;
skip.draw = draw_without_present;
- yasl_surface_set_callbacks(w->surface, &skip, w);
+ yasl_private_surface_set_callbacks(w->surface, &skip, w);
for (int i = 0; i < 4; i++) {
- yasl_surface_schedule_redraw(w->surface);
+ yasl_private_surface_schedule_redraw(w->surface);
pump(loop, d, NULL);
- if (yasl_surface_read_pixels(w->surface, pixels, count, &size)) {
- assert(yasl_display_backend(d) != YASL_BACKEND_X11);
+ if (yasl_private_surface_read_pixels(w->surface, pixels, count, &size)) {
+ assert(yasl_private_display_backend(d) != YASL_PRIVATE_BACKEND_X11);
for (size_t j = 0; j < count; j++) assert(pixels[j] == 0xff4080c0);
} else {
assert(!size.x && !size.y);
@@ -189,47 +189,47 @@ static void test_read_pixels(struct yasl_loop *loop, struct yasl_display *d, str
}
attach(w);
- yasl_surface_schedule_redraw(w->surface);
+ yasl_private_surface_schedule_redraw(w->surface);
pump(loop, d, NULL);
memset(pixels, 0, count * sizeof(*pixels));
- assert(yasl_surface_read_pixels(w->surface, pixels, count, &size));
+ assert(yasl_private_surface_read_pixels(w->surface, pixels, count, &size));
assert(pixels[0] == 0xff4080c0 && pixels[count - 1] == 0xff4080c0);
free(pixels);
}
-static void test_window_spec(struct yasl_loop *loop, struct yasl_display *d)
+static void test_window_spec(struct yasl_private_loop *loop, struct yasl_private_display *d)
{
struct window w = {.display = d, .destroy_on_draw = true};
{
- struct yasl_window_cbs temporary = callbacks;
- struct yasl_window_spec spec = {
+ struct yasl_private_window_cbs temporary = callbacks;
+ struct yasl_private_window_spec spec = {
.title = "Callbacks at creation", .size = {160, 100},
.cbs = &temporary, .ud = &w,
};
- w.surface = yasl_surface_create_toplevel(d, &spec);
+ w.surface = yasl_private_surface_create_toplevel(d, &spec);
assert(w.surface);
assert(!w.draws && !w.configures && !w.closes);
/* Neither the spec nor its callback table needs to outlive creation. */
memset(&temporary, 0, sizeof(temporary));
memset(&spec, 0, sizeof(spec));
}
- yasl_surface_schedule_redraw(w.surface);
+ yasl_private_surface_schedule_redraw(w.surface);
pump(loop, d, NULL);
assert(w.draws == 1 && !w.surface);
}
-static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct window *w)
+static void x11_behavior(struct yasl_private_loop *loop, struct yasl_private_display *d, struct window *w)
{
- Display *native = yasl_display_get_native_handle(d);
- Window window = (Window)(uintptr_t)yasl_surface_get_native_handle(w->surface);
+ Display *native = yasl_private_display_get_native_handle(d);
+ Window window = (Window)(uintptr_t)yasl_private_surface_get_native_handle(w->surface);
assert(native && window);
- assert(yasl_x11_display_get_display(d) == native);
- assert(yasl_x11_surface_get_window(w->surface) == (uintptr_t)window);
+ assert(yasl_private_x11_display_get_display(d) == native);
+ assert(yasl_private_x11_surface_get_window(w->surface) == (uintptr_t)window);
XSync(native, False);
XImage *image = XGetImage(native, window, 0, 0, 1, 1, AllPlanes, ZPixmap);
assert(image && (XGetPixel(image, 0, 0) & 0xffffff) == 0x4080c0);
XDestroyImage(image);
- yasl_surface_set_title(w->surface, "Updated title");
+ yasl_private_surface_set_title(w->surface, "Updated title");
char *title = NULL;
assert(XFetchName(native, window, &title));
assert(strcmp(title, "Updated title") == 0);
@@ -238,19 +238,19 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
XFlush(native);
pump(loop, d, NULL);
assert(w->configures > 0);
- struct yasl_vector2i size = yasl_surface_geometry(w->surface).size;
+ struct yasl_private_vector2i size = yasl_private_surface_geometry(w->surface).size;
assert(size.x == 200 && size.y == 120);
/* A server-generated motion verifies the XI2 subscription and cookie
* dispatch path, including source-device lookup, rather than SendEvent. */
- struct yasl_event pointer_event;
- while (yasl_surface_poll_event(w->surface, &pointer_event)) {}
+ struct yasl_private_event pointer_event;
+ while (yasl_private_surface_poll_event(w->surface, &pointer_event)) {}
XWarpPointer(native, None, window, 0, 0, 0, 0, 80, 50);
XFlush(native);
pump(loop, d, NULL);
bool saw_motion = false;
- while (yasl_surface_poll_event(w->surface, &pointer_event)) {
- if (pointer_event.type == YASL_EVENT_POINTER_MOTION) {
- assert(pointer_event.pointer.device == YASL_PTR_DEV_MOUSE);
+ while (yasl_private_surface_poll_event(w->surface, &pointer_event)) {
+ if (pointer_event.type == YASL_PRIVATE_EVENT_POINTER_MOTION) {
+ assert(pointer_event.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE);
assert(!pointer_event.pointer.pen.pressure);
if (pointer_event.pointer.pos.x == 80 && pointer_event.pointer.pos.y == 50)
saw_motion = true;
@@ -263,25 +263,25 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
.keycode = XKeysymToKeycode(native, XK_a)};
XSendEvent(native, window, False, KeyPressMask, &key);
XFlush(native);
- yasl_display_copy(d, YASL_CLIPBOARD, "clipboard text");
- yasl_display_paste(d, YASL_CLIPBOARD, w->surface);
+ yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, "clipboard text");
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, w->surface);
pump(loop, d, NULL);
bool saw_key = false, saw_paste = false, saw_text = false;
- struct yasl_event event;
- while (yasl_surface_poll_event(w->surface, &event)) {
+ struct yasl_private_event event;
+ while (yasl_private_surface_poll_event(w->surface, &event)) {
assert(event.surface == w->surface);
- if (event.type == YASL_EVENT_KEY) {
+ if (event.type == YASL_PRIVATE_EVENT_KEY) {
assert(event.key.codepoint == 'a');
assert(event.key.shifted == 'A');
assert(event.key.native_code == key.xkey.keycode);
saw_key = event.key.key == YASL_KEY_A;
}
- if (event.type == YASL_EVENT_PASTE) {
+ if (event.type == YASL_PRIVATE_EVENT_PASTE) {
assert(event.text.len == strlen("clipboard text"));
assert(memcmp(event.text.data, "clipboard text", event.text.len) == 0);
saw_paste = true;
}
- if (event.type == YASL_EVENT_TEXT) {
+ if (event.type == YASL_PRIVATE_EVENT_TEXT) {
assert(event.text.len == 1 && event.text.data[0] == 'a');
saw_text = true;
}
@@ -297,12 +297,12 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
XFlush(native);
pump(loop, d, NULL);
int key_count = 0, text_count = 0;
- while (yasl_surface_poll_event(w->surface, &event)) {
- if (event.type == YASL_EVENT_KEY) {
+ while (yasl_private_surface_poll_event(w->surface, &event)) {
+ if (event.type == YASL_PRIVATE_EVENT_KEY) {
assert(event.key.key == YASL_KEY_A);
assert(event.key.action == (key_count ? YASL_KEY_RELEASE : YASL_KEY_PRESS));
key_count++;
- } else if (event.type == YASL_EVENT_TEXT) {
+ } else if (event.type == YASL_PRIVATE_EVENT_TEXT) {
assert(event.text.len == 1 && event.text.data[0] == 'A');
text_count++;
}
@@ -313,10 +313,10 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
XSendEvent(native, window, False, KeyPressMask, &key);
XFlush(native);
pump(loop, d, NULL);
- assert(yasl_surface_poll_event(w->surface, &event));
- assert(event.type == YASL_EVENT_KEY && event.key.key == YASL_KEY_A);
- assert(event.key.mods & YASL_MOD_CTRL);
- assert(!yasl_surface_poll_event(w->surface, &event));
+ assert(yasl_private_surface_poll_event(w->surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_KEY && event.key.key == YASL_KEY_A);
+ assert(event.key.mods & YASL_PRIVATE_MOD_CTRL);
+ assert(!yasl_private_surface_poll_event(w->surface, &event));
int symbols_per_key = 0;
KeySym *saved_symbols = XGetKeyboardMapping(native, key.xkey.keycode, 1, &symbols_per_key);
@@ -333,11 +333,11 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
XFlush(native);
pump(loop, d, NULL);
saw_key = saw_text = false;
- while (yasl_surface_poll_event(w->surface, &event)) {
- if (event.type == YASL_EVENT_KEY) {
+ while (yasl_private_surface_poll_event(w->surface, &event)) {
+ if (event.type == YASL_PRIVATE_EVENT_KEY) {
assert(event.key.key == YASL_KEY_A && event.key.codepoint == 'q');
saw_key = true;
- } else if (event.type == YASL_EVENT_TEXT) {
+ } else if (event.type == YASL_PRIVATE_EVENT_TEXT) {
assert(event.text.len == 1 && event.text.data[0] == 'q');
saw_text = true;
}
@@ -359,67 +359,67 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
XSendEvent(native, window, False, NoEventMask, &wheel);
XFlush(native);
pump(loop, d, NULL);
- assert(yasl_surface_poll_event(w->surface, &event));
- assert(event.type == YASL_EVENT_POINTER_SCROLL);
+ assert(yasl_private_surface_poll_event(w->surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_SCROLL);
assert(event.pointer.scroll.x == (button == 6 ? -1 : button == 7 ? 1 : 0));
assert(event.pointer.scroll.y == (button == 4 ? -1 : button == 5 ? 1 : 0));
- assert(!yasl_surface_poll_event(w->surface, &event));
+ assert(!yasl_private_surface_poll_event(w->surface, &event));
}
- assert(yasl_surface_timing(w->surface).source == YASL_TIMING_SUBMISSION);
- assert(!(yasl_display_caps(d) & YASL_CAP_FRAME_PACING));
+ assert(yasl_private_surface_timing(w->surface).source == YASL_PRIVATE_TIMING_SUBMISSION);
+ assert(!(yasl_private_display_caps(d) & YASL_PRIVATE_CAP_FRAME_PACING));
/* Reuse caller storage, replace the selection, and exceed the old queue
* cap before polling: each paste must retain its own original contents. */
for (int i = 0; i < 300; i++) {
char text[32];
snprintf(text, sizeof(text), "owned-%d", i);
- yasl_display_copy(d, YASL_CLIPBOARD, text);
- yasl_display_paste(d, YASL_CLIPBOARD, w->surface);
+ yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, text);
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, w->surface);
memset(text, 'x', sizeof(text));
}
for (int i = 0; i < 300; i++) {
char text[32];
snprintf(text, sizeof(text), "owned-%d", i);
- assert(yasl_surface_poll_event(w->surface, &event));
- assert(event.type == YASL_EVENT_PASTE && strcmp(event.text.data, text) == 0);
+ assert(yasl_private_surface_poll_event(w->surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && strcmp(event.text.data, text) == 0);
}
const char *last = event.text.data;
- assert(!yasl_surface_poll_event(w->surface, &event));
- yasl_display_copy(d, YASL_CLIPBOARD, "changed");
+ assert(!yasl_private_surface_poll_event(w->surface, &event));
+ yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, "changed");
pump(loop, d, NULL);
assert(strcmp(last, "owned-299") == 0);
- yasl_display_copy(d, YASL_CLIPBOARD, "");
- yasl_display_paste(d, YASL_CLIPBOARD, w->surface);
- assert(yasl_surface_poll_event(w->surface, &event));
- assert(event.type == YASL_EVENT_PASTE && !event.text.len && !event.text.data[0]);
+ yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, "");
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, w->surface);
+ assert(yasl_private_surface_poll_event(w->surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && !event.text.len && !event.text.data[0]);
/* Concurrent external conversions must not share a mutable target slot. */
- struct yasl_display_spec ds = {.backend = YASL_BACKEND_X11};
- struct yasl_display *owner = yasl_display_open(loop, &ds);
+ struct yasl_private_display_spec ds = {.backend = YASL_PRIVATE_BACKEND_X11};
+ struct yasl_private_display *owner = yasl_private_display_open(loop, &ds);
assert(owner);
- yasl_display_copy(owner, YASL_CLIPBOARD, "external");
+ yasl_private_display_copy(owner, YASL_PRIVATE_CLIPBOARD, "external");
struct window other = create(d), cancelled = create(d);
- yasl_display_paste(d, YASL_CLIPBOARD, w->surface);
- yasl_display_paste(d, YASL_CLIPBOARD, other.surface);
- yasl_display_paste(d, YASL_CLIPBOARD, cancelled.surface);
- yasl_surface_destroy(cancelled.surface);
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, w->surface);
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, other.surface);
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, cancelled.surface);
+ yasl_private_surface_destroy(cancelled.surface);
pump(loop, d, owner);
int first_pastes = 0, second_pastes = 0;
- while (yasl_surface_poll_event(w->surface, &event)) {
- if (event.type == YASL_EVENT_PASTE) {
+ while (yasl_private_surface_poll_event(w->surface, &event)) {
+ if (event.type == YASL_PRIVATE_EVENT_PASTE) {
assert(strcmp(event.text.data, "external") == 0);
first_pastes++;
}
}
- while (yasl_surface_poll_event(other.surface, &event)) {
- if (event.type == YASL_EVENT_PASTE) {
+ while (yasl_private_surface_poll_event(other.surface, &event)) {
+ if (event.type == YASL_PRIVATE_EVENT_PASTE) {
assert(strcmp(event.text.data, "external") == 0);
second_pastes++;
}
}
assert(first_pastes == 1 && second_pastes == 1);
- yasl_surface_destroy(other.surface);
- yasl_display_close(owner);
+ yasl_private_surface_destroy(other.surface);
+ yasl_private_display_close(owner);
key.xclient = (XClientMessageEvent){.type = ClientMessage, .display = native,
.window = window, .message_type = XInternAtom(native, "WM_PROTOCOLS", False),
.format = 32, .data.l = {(long)XInternAtom(native, "WM_DELETE_WINDOW", False)}};
@@ -432,64 +432,64 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct
int main(int argc, char **argv)
{
assert(argc >= 2);
- struct yasl_loop *loop = yasl_loop_create();
+ struct yasl_private_loop *loop = yasl_private_loop_create();
assert(loop);
if (strcmp(argv[1], "failure") == 0) {
- struct yasl_display_spec spec = {.backend = (enum yasl_backend)atoi(argv[2])};
- assert(!yasl_display_open(loop, &spec));
+ struct yasl_private_display_spec spec = {.backend = (enum yasl_private_backend)atoi(argv[2])};
+ assert(!yasl_private_display_open(loop, &spec));
} else if (strcmp(argv[1], "mixed") == 0) {
- struct yasl_display_spec spec = {.backend = YASL_BACKEND_WAYLAND};
- struct yasl_display *a = yasl_display_open(loop, &spec);
- spec.backend = YASL_BACKEND_X11;
- struct yasl_display *b = yasl_display_open(loop, &spec);
+ struct yasl_private_display_spec spec = {.backend = YASL_PRIVATE_BACKEND_WAYLAND};
+ struct yasl_private_display *a = yasl_private_display_open(loop, &spec);
+ spec.backend = YASL_PRIVATE_BACKEND_X11;
+ struct yasl_private_display *b = yasl_private_display_open(loop, &spec);
assert(a && b);
test_window_spec(loop, a);
test_window_spec(loop, b);
struct window wa = create(a), wb = create(b);
#if YASL_HAS_WAYLAND
- assert(yasl_wayland_display_get_wl_display(a) != NULL);
- assert(yasl_wayland_surface_get_wl_surface(wa.surface) != NULL);
- assert(!yasl_x11_display_get_display(a));
+ assert(yasl_private_wayland_display_get_wl_display(a) != NULL);
+ assert(yasl_private_wayland_surface_get_wl_surface(wa.surface) != NULL);
+ assert(!yasl_private_x11_display_get_display(a));
#endif
#if YASL_HAS_X11
- assert(yasl_x11_display_get_display(b) != NULL);
- assert(yasl_x11_surface_get_window(wb.surface) != 0);
- assert(!yasl_wayland_display_get_wl_display(b));
+ assert(yasl_private_x11_display_get_display(b) != NULL);
+ assert(yasl_private_x11_surface_get_window(wb.surface) != 0);
+ assert(!yasl_private_wayland_display_get_wl_display(b));
#endif
attach(&wa);
attach(&wb);
pump(loop, a, b);
assert(wa.draws && wb.draws);
- yasl_surface_destroy(wa.surface);
- yasl_surface_destroy(wb.surface);
- yasl_display_close(a);
- yasl_display_close(b);
+ yasl_private_surface_destroy(wa.surface);
+ yasl_private_surface_destroy(wb.surface);
+ yasl_private_display_close(a);
+ yasl_private_display_close(b);
} else {
assert(argc == 4);
- struct yasl_display_spec spec = {.backend = (enum yasl_backend)atoi(argv[2])};
- struct yasl_display *d = strcmp(argv[1], "null") == 0 ?
- yasl_display_open(loop, NULL) : yasl_display_open(loop, &spec);
+ struct yasl_private_display_spec spec = {.backend = (enum yasl_private_backend)atoi(argv[2])};
+ struct yasl_private_display *d = strcmp(argv[1], "null") == 0 ?
+ yasl_private_display_open(loop, NULL) : yasl_private_display_open(loop, &spec);
assert(d);
- assert(yasl_display_backend(d) == (enum yasl_backend)atoi(argv[3]));
+ assert(yasl_private_display_backend(d) == (enum yasl_private_backend)atoi(argv[3]));
struct window w = create(d);
pump(loop, d, NULL);
assert(w.draws == 0);
attach(&w);
- yasl_surface_schedule_redraw(w.surface);
+ yasl_private_surface_schedule_redraw(w.surface);
pump(loop, d, NULL);
assert(w.draws > 0);
test_read_pixels(loop, d, &w);
- if (yasl_display_backend(d) == YASL_BACKEND_X11)
+ if (yasl_private_display_backend(d) == YASL_PRIVATE_BACKEND_X11)
x11_behavior(loop, d, &w);
- if (w.surface) yasl_surface_destroy(w.surface);
+ if (w.surface) yasl_private_surface_destroy(w.surface);
w = create(d);
w.destroy_on_draw = true;
attach(&w);
pump(loop, d, NULL);
assert(w.draws && !w.surface);
- yasl_display_close(d);
+ yasl_private_display_close(d);
}
- yasl_loop_destroy(loop);
+ yasl_private_loop_destroy(loop);
puts("Backend test passed.");
return 0;
}
diff --git a/tests/common/test_contracts.c b/tests/common/test_contracts.c
index d1964ff..be84586 100644
--- a/tests/common/test_contracts.c
+++ b/tests/common/test_contracts.c
@@ -13,17 +13,17 @@
static void test_timing_clock(void)
{
- struct yasl_frame_clock clock = {.refresh_ns = YASL_REFRESH_DEFAULT_NS};
- yasl_clock_presented(&clock, 1000000000, true);
+ struct yasl_private_frame_clock clock = {.refresh_ns = YASL_PRIVATE_REFRESH_DEFAULT_NS};
+ yasl_private_clock_presented(&clock, 1000000000, true);
assert(clock.last_present_ns == 1000000000);
- uint64_t next = yasl_clock_next_present_ns(&clock);
+ uint64_t next = yasl_private_clock_next_present_ns(&clock);
assert(next > 1000000000);
- assert(yasl_clock_extend_ms(1000, 1000000000) == 1000000000);
- assert(yasl_clock_frame_timestamp_ns(&clock, next) == next);
+ assert(yasl_private_clock_extend_ms(1000, 1000000000) == 1000000000);
+ assert(yasl_private_clock_frame_timestamp_ns(&clock, next) == next);
- yasl_clock_note_resize(&clock, 500000);
- struct yasl_resize_stats stats;
- yasl_clock_resize_stats(&clock, &stats);
+ yasl_private_clock_note_resize(&clock, 500000);
+ struct yasl_private_resize_stats stats;
+ yasl_private_clock_resize_stats(&clock, &stats);
assert(stats.count == 1);
assert(stats.max_us == 500.0);
}
@@ -31,27 +31,27 @@ static void test_timing_clock(void)
static void test_surface_state(void)
{
/* Reading reported flags does not require a backend query or display. */
- struct yasl_surface surface = {.state = YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED};
- assert(!yasl_surface_state(NULL));
- assert(yasl_surface_state(&surface) == (YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ struct yasl_surface surface = {.state = YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED};
+ assert(!yasl_private_surface_state(NULL));
+ assert(yasl_private_surface_state(&surface) == (YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
}
static void test_queue(void)
{
struct input_queue q = {0};
struct yasl_surface surface = {0};
- const enum yasl_event_type kinds[] = {
- YASL_EVENT_TEXT, YASL_EVENT_PASTE, YASL_EVENT_DROP,
+ const enum yasl_private_event_type kinds[] = {
+ YASL_PRIVATE_EVENT_TEXT, YASL_PRIVATE_EVENT_PASTE, YASL_PRIVATE_EVENT_DROP,
};
for (size_t k = 0; k < sizeof(kinds) / sizeof(kinds[0]); k++) {
char *source = malloc(4);
assert(source);
memcpy(source, "a\0b", 4);
- struct yasl_event in = {.surface = &surface, .type = kinds[k], .text = {.data = source, .len = 3}};
+ struct yasl_private_event in = {.surface = &surface, .type = kinds[k], .text = {.data = source, .len = 3}};
assert(input_queue_push(&q, &in));
memset(source, 'x', 4);
free(source);
- struct yasl_event out;
+ struct yasl_private_event out;
assert(input_queue_pop(&q, &out));
const char *payload = out.text.data;
assert(out.surface == &surface && out.type == kinds[k]);
@@ -60,7 +60,7 @@ static void test_queue(void)
assert(memcmp(payload, "a\0b", 4) == 0);
/* Growth/wraparound must not invalidate a previously polled payload. */
for (unsigned i = 0; i < 4096; i++) {
- in = (struct yasl_event){.type = YASL_EVENT_KEY, .key.key = i};
+ in = (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_KEY, .key.key = i};
assert(input_queue_push(&q, &in));
}
assert(memcmp(payload, "a\0b", 4) == 0);
@@ -78,12 +78,12 @@ static void test_queue(void)
}
assert(!input_queue_pop(&q, &out));
}
- struct yasl_event empty = {.surface = &surface, .type = YASL_EVENT_PASTE};
- struct yasl_event out;
+ struct yasl_private_event empty = {.surface = &surface, .type = YASL_PRIVATE_EVENT_PASTE};
+ struct yasl_private_event out;
assert(input_queue_push(&q, &empty));
assert(input_queue_pop(&q, &out));
assert(out.text.data && !out.text.len && out.text.data[0] == '\0');
- struct yasl_event in = {.surface = &surface, .type = YASL_EVENT_TEXT,
+ struct yasl_private_event in = {.surface = &surface, .type = YASL_PRIVATE_EVENT_TEXT,
.text = {"owned", 5}};
assert(input_queue_push(&q, &in));
assert(input_queue_pop(&q, &out));
@@ -93,13 +93,13 @@ static void test_queue(void)
in.text.len = SIZE_MAX;
assert(!input_queue_push(&q, &in));
assert(strcmp(last, "owned") == 0);
- in = (struct yasl_event){.surface = &surface, .type = YASL_EVENT_KEY};
+ in = (struct yasl_private_event){.surface = &surface, .type = YASL_PRIVATE_EVENT_KEY};
assert(input_queue_push(&q, &in));
- assert(input_queue_pop(&q, &out) && out.type == YASL_EVENT_INPUT_RESET);
+ assert(input_queue_pop(&q, &out) && out.type == YASL_PRIVATE_EVENT_INPUT_RESET);
assert(out.surface == &surface);
- assert(input_queue_pop(&q, &out) && out.type == YASL_EVENT_KEY);
+ assert(input_queue_pop(&q, &out) && out.type == YASL_PRIVATE_EVENT_KEY);
assert(!input_queue_pop(&q, &out));
- in = (struct yasl_event){.type = YASL_EVENT_PASTE, .text = {"pending", 7}};
+ in = (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_PASTE, .text = {"pending", 7}};
assert(input_queue_push(&q, &in));
input_queue_clear(&q);
input_queue_clear(&q);
@@ -107,49 +107,49 @@ static void test_queue(void)
}
static int presents, copies, pastes, creates;
-static struct yasl_damage_list received;
-static bool present(struct yasl_surface *s, const struct yasl_framebuffer *fb,
- const struct yasl_damage_list *damage)
+static struct yasl_private_damage_list received;
+static bool present(struct yasl_surface *s, const struct yasl_private_framebuffer *fb,
+ const struct yasl_private_damage_list *damage)
{
(void)s; (void)fb;
presents++;
received = *damage;
return true;
}
-static uint32_t caps(const struct yasl_display *d) { (void)d; return 0; }
-static void copy(struct yasl_display *d, enum yasl_selection sel, const char *text)
+static uint32_t caps(const struct yasl_private_display *d) { (void)d; return 0; }
+static void copy(struct yasl_private_display *d, enum yasl_private_selection sel, const char *text)
{ (void)d; (void)sel; (void)text; copies++; }
-static void paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *s)
+static void paste(struct yasl_private_display *d, enum yasl_private_selection sel, struct yasl_surface *s)
{ (void)d; (void)sel; (void)s; pastes++; }
-static struct yasl_surface *create(struct yasl_display *d, const struct yasl_window_spec *spec, void *graphics_device)
+static struct yasl_surface *create(struct yasl_private_display *d, const struct yasl_private_window_spec *spec, void *graphics_device)
{ (void)d; (void)spec; (void)graphics_device; creates++; return NULL; }
static void *native_device;
static int native_queries;
static struct yasl_surface native_surface;
-static uint32_t native_caps(const struct yasl_display *d)
-{ (void)d; return YASL_CAP_NATIVE_GRAPHICS; }
-static struct yasl_surface *native_create(struct yasl_display *d,
- const struct yasl_window_spec *spec, void *device)
+static uint32_t native_caps(const struct yasl_private_display *d)
+{ (void)d; return YASL_PRIVATE_CAP_NATIVE_GRAPHICS; }
+static struct yasl_surface *native_create(struct yasl_private_display *d,
+ const struct yasl_private_window_spec *spec, void *device)
{
(void)spec;
native_device = device;
native_surface = (struct yasl_surface){.display = d, .frame_generation = 1};
return &native_surface;
}
-static bool native_frame(struct yasl_surface *s, const struct yasl_framebuffer *fb,
- struct yasl_native_frame *out)
+static bool native_frame(struct yasl_surface *s, const struct yasl_private_framebuffer *fb,
+ struct yasl_private_native_frame *out)
{
(void)s; (void)fb;
native_queries++;
- *out = (struct yasl_native_frame){.drawable = native_device};
+ *out = (struct yasl_private_native_frame){.drawable = native_device};
return true;
}
-static uint32_t push_buttons(struct input_queue *q, enum yasl_event_type type,
- enum yasl_pointer_button button)
+static uint32_t push_buttons(struct input_queue *q, enum yasl_private_event_type type,
+ enum yasl_private_pointer_button button)
{
- struct yasl_event ev = {.type = type, .pointer.button = button};
+ struct yasl_private_event ev = {.type = type, .pointer.button = button};
assert(input_queue_push(q, &ev));
assert(input_queue_pop(q, &ev));
return ev.pointer.buttons;
@@ -157,31 +157,31 @@ static uint32_t push_buttons(struct input_queue *q, enum yasl_event_type type,
static void test_held_buttons(void)
{
- const uint32_t primary = YASL_BUTTON_BIT(YASL_BUTTON_PRIMARY);
- const uint32_t secondary = YASL_BUTTON_BIT(YASL_BUTTON_SECONDARY);
+ const uint32_t primary = YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY);
+ const uint32_t secondary = YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_SECONDARY);
struct input_queue q = {0};
- assert(push_buttons(&q, YASL_EVENT_POINTER_MOTION, 0) == 0);
- assert(push_buttons(&q, YASL_EVENT_POINTER_DOWN, YASL_BUTTON_PRIMARY) == primary);
- assert(push_buttons(&q, YASL_EVENT_POINTER_MOTION, 0) == primary);
- assert(push_buttons(&q, YASL_EVENT_POINTER_DOWN, YASL_BUTTON_SECONDARY) == (primary | secondary));
- assert(push_buttons(&q, YASL_EVENT_POINTER_UP, YASL_BUTTON_PRIMARY) == secondary);
- assert(push_buttons(&q, YASL_EVENT_POINTER_SCROLL, 0) == secondary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_MOTION, 0) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_DOWN, YASL_PRIVATE_BUTTON_PRIMARY) == primary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_MOTION, 0) == primary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_DOWN, YASL_PRIVATE_BUTTON_SECONDARY) == (primary | secondary));
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_UP, YASL_PRIVATE_BUTTON_PRIMARY) == secondary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_SCROLL, 0) == secondary);
/* X11 and Cocoa keep the press across leave; the release still follows. */
- assert(push_buttons(&q, YASL_EVENT_POINTER_LEAVE, 0) == secondary);
- assert(push_buttons(&q, YASL_EVENT_POINTER_UP, YASL_BUTTON_SECONDARY) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_LEAVE, 0) == secondary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_UP, YASL_PRIVATE_BUTTON_SECONDARY) == 0);
/* A release without a press leaves nothing held. */
- assert(push_buttons(&q, YASL_EVENT_POINTER_UP, YASL_BUTTON_MIDDLE) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_UP, YASL_PRIVATE_BUTTON_MIDDLE) == 0);
- assert(push_buttons(&q, YASL_EVENT_POINTER_DOWN, YASL_BUTTON_PRIMARY) == primary);
- struct yasl_event reset = {.type = YASL_EVENT_INPUT_RESET};
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_DOWN, YASL_PRIVATE_BUTTON_PRIMARY) == primary);
+ struct yasl_private_event reset = {.type = YASL_PRIVATE_EVENT_INPUT_RESET};
assert(input_queue_push(&q, &reset));
assert(input_queue_pop(&q, &reset));
- assert(push_buttons(&q, YASL_EVENT_POINTER_MOTION, 0) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_MOTION, 0) == 0);
q.leave_ends_press = true;
- assert(push_buttons(&q, YASL_EVENT_POINTER_DOWN, YASL_BUTTON_PRIMARY) == primary);
- assert(push_buttons(&q, YASL_EVENT_POINTER_LEAVE, 0) == 0);
- assert(push_buttons(&q, YASL_EVENT_POINTER_MOTION, 0) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_DOWN, YASL_PRIVATE_BUTTON_PRIMARY) == primary);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_LEAVE, 0) == 0);
+ assert(push_buttons(&q, YASL_PRIVATE_EVENT_POINTER_MOTION, 0) == 0);
input_queue_clear(&q);
}
@@ -216,117 +216,117 @@ static void test_drop_paths(void)
/* A short buffer reports the length and leaves both outputs alone. */
const char *before = cursor;
memcpy(path, "keep", 5);
- assert(yasl_drop_next_path(&cursor, path, len) == len);
+ assert(yasl_private_drop_next_path(&cursor, path, len) == len);
assert(cursor == before && strcmp(path, "keep") == 0);
- assert(yasl_drop_next_path(&cursor, NULL, 0) == len && cursor == before);
- assert(yasl_drop_next_path(&cursor, path, sizeof(path)) == len);
+ assert(yasl_private_drop_next_path(&cursor, NULL, 0) == len && cursor == before);
+ assert(yasl_private_drop_next_path(&cursor, path, sizeof(path)) == len);
assert(strcmp(path, want[i]) == 0);
}
- assert(yasl_drop_next_path(&cursor, path, sizeof(path)) == 0 && *cursor == '\0');
- assert(yasl_drop_next_path(&cursor, path, sizeof(path)) == 0);
- assert(yasl_drop_next_path(NULL, path, sizeof(path)) == 0);
+ assert(yasl_private_drop_next_path(&cursor, path, sizeof(path)) == 0 && *cursor == '\0');
+ assert(yasl_private_drop_next_path(&cursor, path, sizeof(path)) == 0);
+ assert(yasl_private_drop_next_path(NULL, path, sizeof(path)) == 0);
const char *none = NULL;
- assert(yasl_drop_next_path(&none, path, sizeof(path)) == 0);
+ assert(yasl_private_drop_next_path(&none, path, sizeof(path)) == 0);
cursor = list;
- assert(yasl_drop_next_path(&cursor, NULL, 8) == 0 && cursor == list);
+ assert(yasl_private_drop_next_path(&cursor, NULL, 8) == 0 && cursor == list);
}
static void test_native(void)
{
- const struct yasl_backend_ops ops = {.display_caps = native_caps,
+ const struct yasl_private_backend_ops ops = {.display_caps = native_caps,
.surface_create_toplevel = native_create, .surface_get_native_frame = native_frame};
- struct yasl_display d = {.ops = &ops};
- struct yasl_window_spec spec = {.size = {100, 80}};
- assert(yasl_surface_create_toplevel(&d, &spec) == &native_surface);
+ struct yasl_private_display d = {.ops = &ops};
+ struct yasl_private_window_spec spec = {.size = {100, 80}};
+ assert(yasl_private_surface_create_toplevel(&d, &spec) == &native_surface);
assert(!native_device);
- assert(yasl_surface_create_native(&d, &spec, &d) == &native_surface);
+ assert(yasl_private_surface_create_native(&d, &spec, &d) == &native_surface);
assert(native_device == &d);
- struct yasl_framebuffer fb = {.generation = 1, .size = {100, 80}};
- struct yasl_native_frame out = {0};
- assert(!yasl_surface_get_native_frame(NULL, &fb, &out));
- assert(!yasl_surface_get_native_frame(&native_surface, NULL, &out));
- assert(!yasl_surface_get_native_frame(&native_surface, &fb, NULL));
+ struct yasl_private_framebuffer fb = {.generation = 1, .size = {100, 80}};
+ struct yasl_private_native_frame out = {0};
+ assert(!yasl_private_surface_get_native_frame(NULL, &fb, &out));
+ assert(!yasl_private_surface_get_native_frame(&native_surface, NULL, &out));
+ assert(!yasl_private_surface_get_native_frame(&native_surface, &fb, NULL));
fb.generation = 0;
- assert(!yasl_surface_get_native_frame(&native_surface, &fb, &out));
+ assert(!yasl_private_surface_get_native_frame(&native_surface, &fb, &out));
fb.generation = 2;
- assert(!yasl_surface_get_native_frame(&native_surface, &fb, &out));
+ assert(!yasl_private_surface_get_native_frame(&native_surface, &fb, &out));
assert(!native_queries && !out.drawable);
fb.generation = 1;
- assert(yasl_surface_get_native_frame(&native_surface, &fb, &out));
+ assert(yasl_private_surface_get_native_frame(&native_surface, &fb, &out));
assert(native_queries == 1 && out.drawable == &d);
}
static void test_validation(void)
{
- const struct yasl_backend_ops ops = {.surface_present = present,
+ const struct yasl_private_backend_ops ops = {.surface_present = present,
.display_caps = caps, .display_copy = copy, .display_paste = paste,
.surface_create_toplevel = create};
- struct yasl_display d = {.ops = &ops};
+ struct yasl_private_display d = {.ops = &ops};
struct yasl_surface s = {.display = &d, .frame_generation = 1};
- struct yasl_framebuffer fb = {.generation = 1, .size = {100, 80}};
- struct yasl_damage_list damage = {.n = -2};
- assert(!yasl_surface_present(&s, &fb, &damage));
- damage.n = YASL_DAMAGE_MAX + 1;
- assert(!yasl_surface_present(&s, &fb, &damage));
+ struct yasl_private_framebuffer fb = {.generation = 1, .size = {100, 80}};
+ struct yasl_private_damage_list damage = {.n = -2};
+ assert(!yasl_private_surface_present(&s, &fb, &damage));
+ damage.n = YASL_PRIVATE_DAMAGE_MAX + 1;
+ assert(!yasl_private_surface_present(&s, &fb, &damage));
damage.n = 1;
- damage.rects[0] = (struct yasl_rect2i){0, 0, -1, 1};
- assert(!yasl_surface_present(&s, &fb, &damage));
- assert(!yasl_surface_present(&s, &fb, NULL));
+ damage.rects[0] = (struct yasl_private_rect2i){0, 0, -1, 1};
+ assert(!yasl_private_surface_present(&s, &fb, &damage));
+ assert(!yasl_private_surface_present(&s, &fb, NULL));
assert(!presents);
damage.n = -1;
fb.generation = 0;
- assert(!yasl_surface_present(&s, &fb, &damage));
+ assert(!yasl_private_surface_present(&s, &fb, &damage));
fb.generation = 2;
- assert(!yasl_surface_present(&s, &fb, &damage));
+ assert(!yasl_private_surface_present(&s, &fb, &damage));
fb.generation = 1;
damage.n = 4;
- damage.rects[0] = (struct yasl_rect2i){-10, -10, 30, 30};
- damage.rects[1] = (struct yasl_rect2i){90, 70, INT_MAX, INT_MAX};
- damage.rects[2] = (struct yasl_rect2i){INT_MAX, INT_MAX, INT_MAX, INT_MAX};
- damage.rects[3] = (struct yasl_rect2i){INT_MIN, INT_MIN, INT_MAX, INT_MAX};
- assert(yasl_surface_present(&s, &fb, &damage));
+ damage.rects[0] = (struct yasl_private_rect2i){-10, -10, 30, 30};
+ damage.rects[1] = (struct yasl_private_rect2i){90, 70, INT_MAX, INT_MAX};
+ damage.rects[2] = (struct yasl_private_rect2i){INT_MAX, INT_MAX, INT_MAX, INT_MAX};
+ damage.rects[3] = (struct yasl_private_rect2i){INT_MIN, INT_MIN, INT_MAX, INT_MAX};
+ assert(yasl_private_surface_present(&s, &fb, &damage));
assert(received.n == 2 && received.rects[0].x == 0 && received.rects[0].width == 20);
assert(received.rects[1].width == 10 && received.rects[1].height == 10);
assert(damage.n == 4 && damage.rects[0].x == -10);
damage.n = -1;
- assert(yasl_surface_present(&s, &fb, &damage) && received.n == -1);
+ assert(yasl_private_surface_present(&s, &fb, &damage) && received.n == -1);
damage.n = 0;
- assert(yasl_surface_present(&s, &fb, &damage) && received.n == 0);
- yasl_display_copy(&d, YASL_PRIMARY, "no alias");
- yasl_display_copy(&d, (enum yasl_selection)255, "invalid");
- yasl_display_paste(&d, YASL_PRIMARY, &s);
- yasl_display_paste(&d, (enum yasl_selection)255, &s);
+ assert(yasl_private_surface_present(&s, &fb, &damage) && received.n == 0);
+ yasl_private_display_copy(&d, YASL_PRIVATE_PRIMARY, "no alias");
+ yasl_private_display_copy(&d, (enum yasl_private_selection)255, "invalid");
+ yasl_private_display_paste(&d, YASL_PRIVATE_PRIMARY, &s);
+ yasl_private_display_paste(&d, (enum yasl_private_selection)255, &s);
assert(!copies && !pastes);
- yasl_display_copy(&d, YASL_CLIPBOARD, "yes");
- yasl_display_paste(&d, YASL_CLIPBOARD, &s);
+ yasl_private_display_copy(&d, YASL_PRIVATE_CLIPBOARD, "yes");
+ yasl_private_display_paste(&d, YASL_PRIVATE_CLIPBOARD, &s);
assert(copies == 1 && pastes == 1);
- struct yasl_window_spec spec = {.size = {100, 80}};
- assert(!yasl_surface_create_native(&d, &spec, &d) && errno == ENOTSUP);
- assert(!yasl_surface_create_native(&d, &spec, NULL) && errno == EINVAL);
+ struct yasl_private_window_spec spec = {.size = {100, 80}};
+ assert(!yasl_private_surface_create_native(&d, &spec, &d) && errno == ENOTSUP);
+ assert(!yasl_private_surface_create_native(&d, &spec, NULL) && errno == EINVAL);
spec.size.x = 0;
- assert(!yasl_surface_create_toplevel(&d, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_create_toplevel(&d, &spec) && errno == EINVAL);
assert(!creates);
}
static void test_scale(void)
{
- assert(yasl_scale_to_device(-10, 120) == -10);
- assert(yasl_scale_to_device(-0.5, 120) == -1);
- assert(yasl_scale_to_device(0.5, 120) == 1);
- assert(yasl_scale_to_device(NAN, 120) == 0);
- assert(yasl_scale_to_device(INFINITY, 120) == 0);
- assert(yasl_scale_to_device(DBL_MAX, 240) == INT_MAX);
- assert(yasl_scale_to_logical(-1, 240) == -1);
- assert(yasl_scale_to_logical(1, 240) == 1);
- assert(yasl_scale_to_logical(INT_MAX, 1) == INT_MAX);
- assert(yasl_scale_to_logical(INT_MIN, 1) == INT_MIN);
- assert(yasl_scale_to_logical(1, 0) == 0);
+ assert(yasl_private_scale_to_device(-10, 120) == -10);
+ assert(yasl_private_scale_to_device(-0.5, 120) == -1);
+ assert(yasl_private_scale_to_device(0.5, 120) == 1);
+ assert(yasl_private_scale_to_device(NAN, 120) == 0);
+ assert(yasl_private_scale_to_device(INFINITY, 120) == 0);
+ assert(yasl_private_scale_to_device(DBL_MAX, 240) == INT_MAX);
+ assert(yasl_private_scale_to_logical(-1, 240) == -1);
+ assert(yasl_private_scale_to_logical(1, 240) == 1);
+ assert(yasl_private_scale_to_logical(INT_MAX, 1) == INT_MAX);
+ assert(yasl_private_scale_to_logical(INT_MIN, 1) == INT_MIN);
+ assert(yasl_private_scale_to_logical(1, 0) == 0);
}
static int popup_calls;
static struct yasl_surface *popup_create(struct yasl_surface *parent,
- const struct yasl_popup_spec *spec)
+ const struct yasl_private_popup_spec *spec)
{
(void)parent; (void)spec;
popup_calls++;
@@ -334,7 +334,7 @@ static struct yasl_surface *popup_create(struct yasl_surface *parent,
}
static bool popup_reposition(struct yasl_surface *popup,
- const struct yasl_popup_spec *spec)
+ const struct yasl_private_popup_spec *spec)
{
(void)popup; (void)spec;
popup_calls++;
@@ -342,19 +342,19 @@ static bool popup_reposition(struct yasl_surface *popup,
return false;
}
-static uint32_t popup_caps(const struct yasl_display *d)
-{ (void)d; return YASL_CAP_POPUPS; }
+static uint32_t popup_caps(const struct yasl_private_display *d)
+{ (void)d; return YASL_PRIVATE_CAP_POPUPS; }
-static int dispatch_failure(struct yasl_display *d, int timeout)
+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_display *d,
- const struct yasl_window_spec *spec, void *device)
+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; }
static int drag_starts;
-static bool drag_without_listener(struct yasl_display *d, struct yasl_surface *s,
- const struct yasl_drag_image *image, const struct yasl_drag_listener *listener,
+static bool drag_without_listener(struct yasl_private_display *d, struct yasl_surface *s,
+ const struct yasl_private_drag_image *image, const struct yasl_private_drag_listener *listener,
void *ud)
{
(void)d; (void)s; (void)image; (void)ud;
@@ -366,52 +366,52 @@ static bool drag_without_listener(struct yasl_display *d, struct yasl_surface *s
static void test_errors(void)
{
- const struct yasl_backend_ops ops = {.display_caps = popup_caps,
+ const struct yasl_private_backend_ops ops = {.display_caps = popup_caps,
.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};
- struct yasl_display d = {.ops = &ops};
+ struct yasl_private_display d = {.ops = &ops};
struct yasl_surface s = {.display = &d};
- struct yasl_popup_spec spec = {.size = {120, 80}, .anchor = {0, 0, 1, 1}};
- assert(!yasl_surface_create_popup(NULL, &spec) && errno == EINVAL);
- assert(!yasl_surface_create_popup(&s, NULL) && errno == EINVAL);
+ struct yasl_private_popup_spec spec = {.size = {120, 80}, .anchor = {0, 0, 1, 1}};
+ assert(!yasl_private_surface_create_popup(NULL, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_create_popup(&s, NULL) && errno == EINVAL);
spec.anchor.width = -1; /* Must not reach Wayland's protocol marshaler. */
- assert(!yasl_surface_create_popup(&s, &spec) && errno == EINVAL);
- assert(!yasl_surface_popup_reposition(&s, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_create_popup(&s, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_popup_reposition(&s, &spec) && errno == EINVAL);
spec.anchor.width = 1;
spec.content_offset.x = INT_MAX;
spec.content_size.x = INT_MAX;
- assert(!yasl_surface_create_popup(&s, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_create_popup(&s, &spec) && errno == EINVAL);
spec.content_offset.x = spec.content_size.x = 0;
spec.size.x = 32768;
- assert(!yasl_surface_create_popup(&s, &spec) && errno == EINVAL);
+ assert(!yasl_private_surface_create_popup(&s, &spec) && errno == EINVAL);
assert(!popup_calls);
spec.size.x = 120;
errno = ERANGE;
- assert(!yasl_surface_create_popup(&s, &spec) && errno == ENODEV);
- assert(!yasl_surface_popup_reposition(&s, &spec) && errno == EBUSY);
+ assert(!yasl_private_surface_create_popup(&s, &spec) && errno == ENODEV);
+ assert(!yasl_private_surface_popup_reposition(&s, &spec) && errno == EBUSY);
assert(popup_calls == 2);
- const struct yasl_backend_ops unsupported = {0};
+ const struct yasl_private_backend_ops unsupported = {0};
d.ops = &unsupported;
- assert(!yasl_surface_create_popup(&s, &spec) && errno == ENOTSUP);
- assert(!yasl_surface_popup_reposition(&s, &spec) && errno == ENOTSUP);
- assert(yasl_display_dispatch(&d, 0) == -1 && errno == ENOTSUP);
- assert(yasl_display_dispatch(NULL, 0) == -1 && errno == EINVAL);
+ 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_display_dispatch(&d, 0) == -1 && errno == EIO);
- struct yasl_window_spec toplevel = {.size = {120, 80}};
+ assert(yasl_private_display_dispatch(&d, 0) == -1 && errno == EIO);
+ struct yasl_private_window_spec toplevel = {.size = {120, 80}};
errno = ERANGE;
- assert(!yasl_surface_create_toplevel(&d, &toplevel) && errno == ENODEV);
- assert(yasl_display_drag_start(&d, &s, NULL, NULL, NULL));
- struct yasl_drag_image image = {.size = {1, 1}};
- assert(!yasl_display_drag_start(&d, &s, &image, NULL, NULL));
+ assert(!yasl_private_surface_create_toplevel(&d, &toplevel) && errno == ENODEV);
+ assert(yasl_private_display_drag_start(&d, &s, NULL, NULL, NULL));
+ struct yasl_private_drag_image image = {.size = {1, 1}};
+ assert(!yasl_private_display_drag_start(&d, &s, &image, NULL, NULL));
uint32_t pixel = 0;
image.pixels = &pixel;
image.size.x = INT_MAX;
- assert(!yasl_display_drag_start(&d, &s, &image, NULL, NULL));
+ assert(!yasl_private_display_drag_start(&d, &s, &image, NULL, NULL));
assert(drag_starts == 1);
}
diff --git a/tests/common/test_desktop.c b/tests/common/test_desktop.c
index 89760fe..a665da5 100644
--- a/tests/common/test_desktop.c
+++ b/tests/common/test_desktop.c
@@ -1,7 +1,7 @@
#define _GNU_SOURCE
#include "common/backend.h"
#include "platform/freedesktop/dbus.h"
-#include "yasl/desktop.h"
+#include "common/private_desktop.h"
#include <assert.h>
#include <fcntl.h>
@@ -39,31 +39,31 @@ static char *read_file(const char *path)
static void test_buffers(void)
{
char exe[PATH_MAX], real[PATH_MAX];
- size_t len = yasl_executable_path(NULL, 0);
+ size_t len = yasl_private_executable_path(NULL, 0);
assert(len > 0);
- assert(yasl_executable_path(exe, len) == len);
- assert(yasl_executable_path(exe, sizeof(exe)) == len && exe[len] == '\0');
+ assert(yasl_private_executable_path(exe, len) == len);
+ assert(yasl_private_executable_path(exe, sizeof(exe)) == len && exe[len] == '\0');
assert(realpath("/proc/self/exe", real) && strcmp(exe, real) == 0);
/* A short buffer stays untouched. */
char small[4] = "abc";
- assert(yasl_executable_path(small, sizeof(small)) == len);
+ assert(yasl_private_executable_path(small, sizeof(small)) == len);
assert(strcmp(small, "abc") == 0);
- assert(yasl_executable_path(NULL, 8) == 0);
+ assert(yasl_private_executable_path(NULL, 8) == 0);
- assert(yasl_resource_dir(exe, sizeof(exe)) == 0);
+ assert(yasl_private_resource_dir(exe, sizeof(exe)) == 0);
char locale[64];
setenv("LC_ALL", "", 1);
setenv("LC_CTYPE", "de_DE.UTF-8", 1);
setenv("LANG", "fr_FR.UTF-8", 1);
- assert(yasl_default_locale(locale, sizeof(locale)) == 11);
+ assert(yasl_private_default_locale(locale, sizeof(locale)) == 11);
assert(strcmp(locale, "de_DE.UTF-8") == 0);
unsetenv("LC_CTYPE");
- assert(yasl_default_locale(locale, sizeof(locale)) == 11);
+ assert(yasl_private_default_locale(locale, sizeof(locale)) == 11);
assert(strcmp(locale, "fr_FR.UTF-8") == 0);
unsetenv("LANG");
unsetenv("LC_ALL");
- assert(yasl_default_locale(locale, sizeof(locale)) == 7);
+ assert(yasl_private_default_locale(locale, sizeof(locale)) == 7);
assert(strcmp(locale, "C.UTF-8") == 0);
}
@@ -86,14 +86,14 @@ static void test_open_uri(const char *dir)
snprintf(path, sizeof(path), "%s:%s", dir, old_path ? old_path : "/usr/bin:/bin");
setenv("PATH", path, 1);
- struct yasl_display display = {0};
- assert(!yasl_display_open_uri(NULL, "https://example.com"));
- assert(!yasl_display_open_uri(&display, NULL));
- assert(!yasl_display_open_uri(&display, ""));
- assert(!yasl_display_open_uri(&display, "example.com"));
- assert(!yasl_display_open_uri(&display, "-x:option"));
- assert(!yasl_display_open_uri(&display, "1http://example.com"));
- assert(!yasl_display_open_uri(&display, "http://example.com/\n"));
+ struct yasl_private_display display = {0};
+ assert(!yasl_private_display_open_uri(NULL, "https://example.com"));
+ assert(!yasl_private_display_open_uri(&display, NULL));
+ assert(!yasl_private_display_open_uri(&display, ""));
+ assert(!yasl_private_display_open_uri(&display, "example.com"));
+ assert(!yasl_private_display_open_uri(&display, "-x:option"));
+ assert(!yasl_private_display_open_uri(&display, "1http://example.com"));
+ assert(!yasl_private_display_open_uri(&display, "http://example.com/\n"));
assert(access(out, F_OK) != 0);
/* The opener must not inherit blocked or ignored signals or descriptors. */
@@ -110,7 +110,7 @@ static void test_open_uri(const char *dir)
close(null);
const char *uri = "https://example.com/a b?c='d'&e=\"f\"";
- assert(yasl_display_open_uri(&display, uri));
+ assert(yasl_private_display_open_uri(&display, uri));
char *text = NULL;
for (int i = 0; i < 500 && !(text = read_file(out)); i++) sleep_ms(10);
assert(text);
@@ -137,29 +137,29 @@ static void test_open_uri(const char *dir)
/* Without xdg-open in PATH, nothing launches. */
setenv("PATH", dir, 1);
- assert(!yasl_display_open_uri(&display, "https://example.com"));
+ assert(!yasl_private_display_open_uri(&display, "https://example.com"));
if (old_path) setenv("PATH", old_path, 1);
}
static void test_appearance_fallback(void)
{
- assert(yasl_display_double_click_ms(NULL) == YASL_DOUBLE_CLICK_MS_DEFAULT);
+ assert(yasl_private_display_double_click_ms(NULL) == YASL_PRIVATE_DOUBLE_CLICK_MS_DEFAULT);
assert(portal_double_click_ms() == 0);
- struct yasl_display display = {0};
- assert(yasl_display_appearance(NULL) == 0);
+ struct yasl_private_display display = {0};
+ assert(yasl_private_display_appearance(NULL) == 0);
unsetenv("GTK_THEME");
- assert(yasl_display_appearance(&display) == 0);
+ assert(yasl_private_display_appearance(&display) == 0);
setenv("GTK_THEME", "Adwaita:dark", 1);
- assert(yasl_display_appearance(&display) == YASL_APPEARANCE_DARK);
+ assert(yasl_private_display_appearance(&display) == YASL_PRIVATE_APPEARANCE_DARK);
setenv("GTK_THEME", "HighContrast", 1);
- assert(yasl_display_appearance(&display) == YASL_APPEARANCE_HIGH_CONTRAST);
+ assert(yasl_private_display_appearance(&display) == YASL_PRIVATE_APPEARANCE_HIGH_CONTRAST);
setenv("GTK_THEME", "HighContrastInverse", 1);
- assert(yasl_display_appearance(&display) ==
- (YASL_APPEARANCE_HIGH_CONTRAST | YASL_APPEARANCE_DARK));
+ assert(yasl_private_display_appearance(&display) ==
+ (YASL_PRIVATE_APPEARANCE_HIGH_CONTRAST | YASL_PRIVATE_APPEARANCE_DARK));
unsetenv("GTK_THEME");
- assert(!yasl_display_notify(NULL, "title", "body"));
- assert(!yasl_display_notify(&display, NULL, "body"));
- assert(!yasl_display_notify(&display, "title", "body"));
+ assert(!yasl_private_display_notify(NULL, "title", "body"));
+ assert(!yasl_private_display_notify(&display, NULL, "body"));
+ assert(!yasl_private_display_notify(&display, "title", "body"));
}
#if YASL_HAS_DBUS
@@ -310,8 +310,8 @@ static void test_bus(const char *address)
pthread_t thread;
assert(pthread_create(&thread, NULL, serve, &fb) == 0);
- struct yasl_display display = {.app_id = "org.example.Test"};
- assert(yasl_display_notify(&display, "Build done", NULL));
+ struct yasl_private_display display = {.app_id = "org.example.Test"};
+ assert(yasl_private_display_notify(&display, "Build done", NULL));
for (int i = 0; i < 500; i++) {
pthread_mutex_lock(&fb.lock);
int n = fb.notifications;
@@ -328,10 +328,10 @@ static void test_bus(const char *address)
/* Portal settings win over GTK_THEME, through ReadOne or the older Read. */
setenv("GTK_THEME", "Adwaita", 1);
- uint32_t want = YASL_APPEARANCE_DARK | YASL_APPEARANCE_HIGH_CONTRAST;
- assert(yasl_display_appearance(&display) == want);
+ uint32_t want = YASL_PRIVATE_APPEARANCE_DARK | YASL_PRIVATE_APPEARANCE_HIGH_CONTRAST;
+ assert(yasl_private_display_appearance(&display) == want);
fb.read_one = false;
- assert(yasl_display_appearance(&display) == want);
+ assert(yasl_private_display_appearance(&display) == want);
unsetenv("GTK_THEME");
/* A KDE value, sent as a string, wins over the GNOME key. */
diff --git a/tests/common/test_events.c b/tests/common/test_events.c
index c8660cb..fcfc118 100644
--- a/tests/common/test_events.c
+++ b/tests/common/test_events.c
@@ -1,5 +1,4 @@
#include "common/backend.h"
-#include "yasl/app.h"
#include <assert.h>
#include <errno.h>
@@ -8,7 +7,7 @@
#include <string.h>
static struct input_queue *queue(struct yasl_surface *s) { return &s->input; }
-static const struct yasl_backend_ops ops = {.surface_input_queue = queue};
+static const struct yasl_private_backend_ops ops = {.surface_input_queue = queue};
static int released;
static pthread_t owner;
static void release(void *payload)
@@ -18,90 +17,90 @@ static void release(void *payload)
released++;
}
-static void setup(struct yasl_display *d, struct yasl_surface *a, struct yasl_surface *b)
+static void setup(struct yasl_private_display *d, struct yasl_surface *a, struct yasl_surface *b)
{
- *d = (struct yasl_display){.ops = &ops};
+ *d = (struct yasl_private_display){.ops = &ops};
*a = (struct yasl_surface){.display = d, .scale_120 = 120};
*b = (struct yasl_surface){.display = d, .scale_120 = 120};
- assert(yasl_events_open(d));
- assert(yasl_events_register(a));
- assert(yasl_events_register(b));
+ assert(yasl_private_events_open(d));
+ assert(yasl_private_events_register(a));
+ assert(yasl_private_events_register(b));
}
-static void teardown(struct yasl_display *d, struct yasl_surface *a, struct yasl_surface *b)
+static void teardown(struct yasl_private_display *d, struct yasl_surface *a, struct yasl_surface *b)
{
- yasl_events_unregister(a);
- yasl_events_unregister(b);
+ yasl_private_events_unregister(a);
+ yasl_private_events_unregister(b);
input_queue_clear(&a->input);
input_queue_clear(&b->input);
- yasl_events_close(d);
+ yasl_private_events_close(d);
}
static void test_order_and_lifetimes(void)
{
- struct yasl_display d;
+ struct yasl_private_display d;
struct yasl_surface a, b;
setup(&d, &a, &b);
- uint64_t aid = yasl_surface_id(&a), bid = yasl_surface_id(&b);
+ uint64_t aid = yasl_private_surface_id(&a), bid = yasl_private_surface_id(&b);
assert(aid && bid && aid != bid);
- yasl_surface_set_userdata(&a, &b);
- assert(yasl_surface_userdata(&a) == &b);
+ yasl_private_surface_set_userdata(&a, &b);
+ assert(yasl_private_surface_userdata(&a) == &b);
char text[] = "text";
- assert(input_queue_push(&a.input, &(struct yasl_event){
- .type = YASL_EVENT_TEXT, .surface = &a, .text = {text, 4}}));
+ assert(input_queue_push(&a.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT, .surface = &a, .text = {text, 4}}));
memset(text, 'x', 4);
- yasl_surface_notify_state(&b, YASL_STATE_MAXIMIZED);
- yasl_surface_notify_configure(&a, (struct yasl_geometry){{640, 480}, 180});
- yasl_surface_notify_drag(&b, YASL_DRAG_OVER, (struct yasl_vector2i){3, 4});
- yasl_surface_notify_composition(&a, "hello", 1, 3);
- yasl_surface_notify_composition(&a, NULL, -1, -1);
- yasl_surface_complete_paste(&b, 42, YASL_TRANSFER_UNAVAILABLE, NULL, 0);
- const enum yasl_event_type expected[] = {YASL_EVENT_TEXT, YASL_EVENT_WINDOW_STATE,
- YASL_EVENT_WINDOW_RESIZE, YASL_EVENT_DRAG, YASL_EVENT_COMPOSITION,
- YASL_EVENT_COMPOSITION, YASL_EVENT_PASTE};
- struct yasl_event ev;
+ yasl_private_surface_notify_state(&b, YASL_PRIVATE_STATE_MAXIMIZED);
+ yasl_private_surface_notify_configure(&a, (struct yasl_private_geometry){{640, 480}, 180});
+ yasl_private_surface_notify_drag(&b, YASL_PRIVATE_DRAG_OVER, (struct yasl_private_vector2i){3, 4});
+ yasl_private_surface_notify_composition(&a, "hello", 1, 3);
+ yasl_private_surface_notify_composition(&a, NULL, -1, -1);
+ yasl_private_surface_complete_paste(&b, 42, YASL_PRIVATE_TRANSFER_UNAVAILABLE, NULL, 0);
+ const enum yasl_private_event_type expected[] = {YASL_PRIVATE_EVENT_TEXT, YASL_PRIVATE_EVENT_WINDOW_STATE,
+ YASL_PRIVATE_EVENT_WINDOW_RESIZE, YASL_PRIVATE_EVENT_DRAG, YASL_PRIVATE_EVENT_COMPOSITION,
+ YASL_PRIVATE_EVENT_COMPOSITION, YASL_PRIVATE_EVENT_PASTE};
+ struct yasl_private_event ev;
uint64_t sequence = 0;
for (size_t i = 0; i < sizeof(expected) / sizeof(*expected); i++) {
- assert(yasl_display_poll_event(&d, &ev));
+ assert(yasl_private_display_poll_event(&d, &ev));
assert(ev.type == expected[i] && ev.sequence > sequence && ev.time_ns);
sequence = ev.sequence;
if (i == 0) assert(!strcmp(ev.text.data, "text") && ev.surface_id == aid);
if (i == 2) assert(ev.resize.scale_changed && ev.resize.geometry.size.x == 640);
if (i == 4) assert(ev.composition.active && ev.composition.begin == 1 && !strcmp(ev.composition.data, "hello"));
if (i == 5) assert(!ev.composition.active && !ev.composition.len);
- if (i == 6) assert(ev.paste.request_id == 42 && ev.paste.status == YASL_TRANSFER_UNAVAILABLE);
+ if (i == 6) assert(ev.paste.request_id == 42 && ev.paste.status == YASL_PRIVATE_TRANSFER_UNAVAILABLE);
}
- assert(!yasl_display_poll_event(&d, &ev));
- assert(input_queue_push(&a.input, &(struct yasl_event){
- .type = YASL_EVENT_TEXT, .surface = &a, .text = {"kept", 4}}));
- assert(yasl_display_poll_event(&d, &ev));
+ assert(!yasl_private_display_poll_event(&d, &ev));
+ assert(input_queue_push(&a.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT, .surface = &a, .text = {"kept", 4}}));
+ assert(yasl_private_display_poll_event(&d, &ev));
const char *borrowed = ev.text.data;
- assert(input_queue_push(&a.input, &(struct yasl_event){.type = YASL_EVENT_KEY, .surface = &a}));
- yasl_events_unregister(&a);
+ assert(input_queue_push(&a.input, &(struct yasl_private_event){.type = YASL_PRIVATE_EVENT_KEY, .surface = &a}));
+ yasl_private_events_unregister(&a);
assert(!strcmp(borrowed, "kept"));
- assert(!yasl_display_poll_event(&d, &ev));
+ assert(!yasl_private_display_poll_event(&d, &ev));
/* Reusing object memory must never reuse the identity. */
- assert(yasl_events_register(&a));
+ assert(yasl_private_events_register(&a));
assert(a.id != aid);
errno = 0;
- assert(!yasl_display_post(&d, &(struct yasl_message){.target_id = aid}));
+ assert(!yasl_private_display_post(&d, &(struct yasl_private_message){.target_id = aid}));
assert(errno == ENOENT);
teardown(&d, &a, &b);
}
-struct producer { struct yasl_display *display; uint64_t target; };
+struct producer { struct yasl_private_display *display; uint64_t target; };
static void *post_worker(void *ud)
{
struct producer *producer = ud;
for (uint32_t i = 0; i < 32; i++)
- assert(yasl_display_post(producer->display, &(struct yasl_message){
+ assert(yasl_private_display_post(producer->display, &(struct yasl_private_message){
.target_id = producer->target, .code = i, .payload = &released, .release = release}));
return NULL;
}
static void test_post_cleanup(void)
{
- struct yasl_display d;
+ struct yasl_private_display d;
struct yasl_surface a, b;
setup(&d, &a, &b);
owner = pthread_self();
@@ -110,26 +109,26 @@ static void test_post_cleanup(void)
struct producer producer = {&d, a.id};
assert(!pthread_create(&worker, NULL, post_worker, &producer));
assert(!pthread_join(worker, NULL));
- struct yasl_event ev;
+ struct yasl_private_event ev;
for (uint32_t i = 0; i < 8; i++) {
- assert(yasl_display_poll_event(&d, &ev));
+ assert(yasl_private_display_poll_event(&d, &ev));
assert(ev.user.code == i && ev.surface == &a);
}
assert(released == 7); /* Last event remains borrowed. */
- yasl_events_unregister(&a);
+ yasl_private_events_unregister(&a);
assert(released == 31); /* Undelivered target messages canceled. */
- assert(!yasl_display_poll_event(&d, &ev));
- assert(yasl_display_post(&d, &(struct yasl_message){.payload = &released, .release = release}));
- yasl_events_close(&d);
+ assert(!yasl_private_display_poll_event(&d, &ev));
+ assert(yasl_private_display_post(&d, &(struct yasl_private_message){.payload = &released, .release = release}));
+ yasl_private_events_close(&d);
assert(released == 33); /* Pending message and last consumed message. */
errno = 0;
- assert(!yasl_display_post(&d, &(struct yasl_message){.payload = &released, .release = release}));
+ assert(!yasl_private_display_post(&d, &(struct yasl_private_message){.payload = &released, .release = release}));
assert(errno == EINVAL && released == 33);
}
static int damage_count;
-static bool present(struct yasl_surface *s, const struct yasl_framebuffer *target,
- const struct yasl_damage_list *damage)
+static bool present(struct yasl_surface *s, const struct yasl_private_framebuffer *target,
+ const struct yasl_private_damage_list *damage)
{
(void)s; (void)target;
damage_count = damage->n;
@@ -137,64 +136,64 @@ static bool present(struct yasl_surface *s, const struct yasl_framebuffer *targe
}
static void test_damage(void)
{
- struct yasl_backend_ops present_ops = {.surface_present = present};
- struct yasl_display d = {.ops = &present_ops};
+ struct yasl_private_backend_ops present_ops = {.surface_present = present};
+ struct yasl_private_display d = {.ops = &present_ops};
struct yasl_surface s = {.display = &d, .frame_generation = 1, .drawing = true};
- struct yasl_frame frame = {.surface = &s, .target = {.generation = 1, .size = {8, 8}}};
+ struct yasl_private_frame frame = {.surface = &s, .target = {.generation = 1, .size = {8, 8}}};
s.active_frame = &frame;
- struct yasl_rect2i rects[YASL_DAMAGE_MAX + 1] = {{0}};
- assert(yasl_frame_present(&frame, NULL, 0) && damage_count == -1);
- assert(!yasl_frame_present(&frame, NULL, 0) && errno == EALREADY);
+ struct yasl_private_rect2i rects[YASL_PRIVATE_DAMAGE_MAX + 1] = {{0}};
+ assert(yasl_private_frame_present(&frame, NULL, 0) && damage_count == -1);
+ assert(!yasl_private_frame_present(&frame, NULL, 0) && errno == EALREADY);
s.frame_presented = false;
- assert(yasl_frame_present(&frame, rects, 0) && damage_count == 0);
+ assert(yasl_private_frame_present(&frame, rects, 0) && damage_count == 0);
s.frame_presented = false;
- assert(yasl_frame_present(&frame, rects, YASL_DAMAGE_MAX + 1) && damage_count == -1);
+ assert(yasl_private_frame_present(&frame, rects, YASL_PRIVATE_DAMAGE_MAX + 1) && damage_count == -1);
s.frame_presented = false;
- rects[YASL_DAMAGE_MAX].width = -1;
+ rects[YASL_PRIVATE_DAMAGE_MAX].width = -1;
errno = 0;
- assert(!yasl_frame_present(&frame, rects, YASL_DAMAGE_MAX + 1) && errno == EINVAL);
- assert(!yasl_frame_present(&frame, NULL, 1));
+ assert(!yasl_private_frame_present(&frame, rects, YASL_PRIVATE_DAMAGE_MAX + 1) && errno == EINVAL);
+ assert(!yasl_private_frame_present(&frame, NULL, 1));
s.drawing = false;
- assert(!yasl_frame_present(&frame, NULL, 0));
+ assert(!yasl_private_frame_present(&frame, NULL, 0));
}
static void test_failures(void)
{
- struct yasl_display d;
+ struct yasl_private_display d;
struct yasl_surface a, b;
setup(&d, &a, &b);
- assert(!yasl_surface_set_size(&a, (struct yasl_vector2i){0, 10}) && errno == EINVAL);
- assert(!yasl_surface_set_size(&a, (struct yasl_vector2i){10, 10}) && errno == ENOTSUP);
- assert(!yasl_surface_set_fullscreen(&a, true) && errno == ENOTSUP);
- assert(!yasl_surface_set_maximized(&a, true) && errno == ENOTSUP);
- assert(!yasl_surface_minimize(&a) && errno == ENOTSUP);
+ assert(!yasl_private_surface_set_size(&a, (struct yasl_private_vector2i){0, 10}) && errno == EINVAL);
+ assert(!yasl_private_surface_set_size(&a, (struct yasl_private_vector2i){10, 10}) && errno == ENOTSUP);
+ assert(!yasl_private_surface_set_fullscreen(&a, true) && errno == ENOTSUP);
+ assert(!yasl_private_surface_set_maximized(&a, true) && errno == ENOTSUP);
+ assert(!yasl_private_surface_minimize(&a) && errno == ENOTSUP);
a.popup = true;
- assert(!yasl_surface_minimize(&a) && errno == EINVAL);
- assert(!yasl_clipboard_set(&d, YASL_CLIPBOARD, "text") && errno == ENOTSUP);
- assert(!yasl_clipboard_request(&a, YASL_CLIPBOARD) && errno == ENOTSUP);
+ assert(!yasl_private_surface_minimize(&a) && errno == EINVAL);
+ assert(!yasl_private_clipboard_set(&d, YASL_PRIVATE_CLIPBOARD, "text") && errno == ENOTSUP);
+ assert(!yasl_private_clipboard_request(&a, YASL_PRIVATE_CLIPBOARD) && errno == ENOTSUP);
/* Queued native event allocation/validation failure must be observable. */
- assert(!yasl_events_push(&d, &a, &(struct yasl_event){
- .type = YASL_EVENT_TEXT, .surface = &a, .text = {"x", SIZE_MAX}}));
- assert(yasl_events_error(&d) == ENOMEM);
+ assert(!yasl_private_events_push(&d, &a, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT, .surface = &a, .text = {"x", SIZE_MAX}}));
+ assert(yasl_private_events_error(&d) == ENOMEM);
teardown(&d, &a, &b);
}
static void test_legacy_poll_does_not_spin(void)
{
- struct yasl_display d;
+ struct yasl_private_display d;
struct yasl_surface a, b;
setup(&d, &a, &b);
- yasl_surface_notify_state(&a, YASL_STATE_ACTIVATED);
- yasl_surface_notify_close(&b);
- assert(yasl_events_pending(&d));
- struct yasl_event ev;
- assert(!yasl_surface_poll_event(&a, &ev));
- assert(!yasl_events_pending(&d));
- assert(input_queue_push(&b.input, &(struct yasl_event){.type = YASL_EVENT_KEY, .surface = &b}));
- assert(!yasl_surface_poll_event(&a, &ev));
- assert(yasl_surface_poll_event(&b, &ev) && ev.surface == &b);
- assert(!yasl_events_pending(&d));
+ yasl_private_surface_notify_state(&a, YASL_PRIVATE_STATE_ACTIVATED);
+ yasl_private_surface_notify_close(&b);
+ assert(yasl_private_events_pending(&d));
+ struct yasl_private_event ev;
+ assert(!yasl_private_surface_poll_event(&a, &ev));
+ assert(!yasl_private_events_pending(&d));
+ assert(input_queue_push(&b.input, &(struct yasl_private_event){.type = YASL_PRIVATE_EVENT_KEY, .surface = &b}));
+ assert(!yasl_private_surface_poll_event(&a, &ev));
+ assert(yasl_private_surface_poll_event(&b, &ev) && ev.surface == &b);
+ assert(!yasl_private_events_pending(&d));
teardown(&d, &a, &b);
}
diff --git a/tests/common/test_gl.c b/tests/common/test_gl.c
new file mode 100644
index 0000000..cd51575
--- /dev/null
+++ b/tests/common/test_gl.c
@@ -0,0 +1,158 @@
+#define _POSIX_C_SOURCE 200809L
+#include <yasl/gl.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+typedef const unsigned char *(*get_string_fn)(unsigned);
+typedef void (*clear_color_fn)(float, float, float, float);
+typedef void (*clear_fn)(unsigned);
+typedef void (*finish_fn)(void);
+typedef void (*read_pixels_fn)(int, int, int, int, unsigned, unsigned, void *);
+typedef void (*gen_textures_fn)(int, unsigned *);
+typedef void (*bind_texture_fn)(unsigned, unsigned);
+typedef unsigned char (*is_texture_fn)(unsigned);
+typedef void (*delete_textures_fn)(int, const unsigned *);
+
+enum { GL_VERSION_ = 0x1f02, GL_COLOR_BUFFER_BIT_ = 0x00004000,
+ GL_RGBA_ = 0x1908, GL_UNSIGNED_BYTE_ = 0x1401, GL_TEXTURE_2D_ = 0x0de1 };
+
+static yasl_surface *primary;
+static yasl_surface *shared;
+static yasl_surface *cpu;
+
+static void fail(const char *message, int line)
+{
+ const char *description = NULL;
+ enum yasl_error error = yasl_get_error(&description);
+ fprintf(stderr, "GL integration failure at line %d: %s (YASL error %d: %s, native error %d)\n",
+ line, message, error, description ? description : "none", yasl_get_native_error());
+ (void)yasl_gl_make_current(NULL);
+ if (cpu) yasl_surface_destroy(cpu);
+ if (shared) yasl_surface_destroy(shared);
+ if (primary) yasl_surface_destroy(primary);
+ yasl_shutdown();
+ exit(1);
+}
+
+#define REQUIRE(condition, message) do { if (!(condition)) fail((message), __LINE__); } while (0)
+
+#define LOAD_GL(function, type, symbol) do { \
+ union { yasl_gl_proc generic; type typed; } conversion; \
+ conversion.generic = yasl_gl_get_proc_address(symbol); \
+ REQUIRE(conversion.generic != NULL, "missing OpenGL function " symbol); \
+ function = conversion.typed; \
+} while (0)
+
+static double seconds_now(void)
+{
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return 0;
+ return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
+}
+
+static void wait_for_size(yasl_surface *surface, int width, int height)
+{
+ double deadline = seconds_now() + 8.0;
+ int actual_width = 0, actual_height = 0;
+ while (seconds_now() < deadline) {
+ yasl_surface_get_size(surface, &actual_width, &actual_height);
+ if (actual_width == width && actual_height == height) return;
+ yasl_event event = {0};
+ int result = yasl_wait_event(&event, 50);
+ REQUIRE(result >= 0, "waiting for configure event");
+ }
+ char message[128];
+ snprintf(message, sizeof(message), "resize did not settle at %dx%d (got %dx%d)",
+ width, height, actual_width, actual_height);
+ fail(message, __LINE__);
+}
+
+int main(int argc, char **argv)
+{
+ REQUIRE(argc == 2, "expected backend argument: wayland or x11");
+ if (!strcmp(argv[1], "wayland")) REQUIRE(yasl_set_backend(YASL_BACKEND_WAYLAND), "select Wayland backend");
+ else if (!strcmp(argv[1], "x11")) REQUIRE(yasl_set_backend(YASL_BACKEND_X11), "select X11 backend");
+ else REQUIRE(false, "backend must be wayland or x11");
+
+ primary = yasl_gl_surface_create("YASL GL test", 320, 240, 0, NULL, NULL);
+ REQUIRE(primary != NULL, "create default OpenGL 3.2 surface");
+ REQUIRE(yasl_gl_make_current(primary), "make first GL context current");
+
+ get_string_fn get_string = NULL;
+ clear_color_fn clear_color = NULL;
+ clear_fn clear = NULL;
+ finish_fn finish = NULL;
+ read_pixels_fn read_pixels = NULL;
+ gen_textures_fn gen_textures = NULL;
+ bind_texture_fn bind_texture = NULL;
+ is_texture_fn is_texture = NULL;
+ delete_textures_fn delete_textures = NULL;
+ LOAD_GL(get_string, get_string_fn, "glGetString");
+ LOAD_GL(clear_color, clear_color_fn, "glClearColor");
+ LOAD_GL(clear, clear_fn, "glClear");
+ LOAD_GL(finish, finish_fn, "glFinish");
+ LOAD_GL(read_pixels, read_pixels_fn, "glReadPixels");
+ LOAD_GL(gen_textures, gen_textures_fn, "glGenTextures");
+ LOAD_GL(bind_texture, bind_texture_fn, "glBindTexture");
+ LOAD_GL(is_texture, is_texture_fn, "glIsTexture");
+ LOAD_GL(delete_textures, delete_textures_fn, "glDeleteTextures");
+ const unsigned char *version = get_string(GL_VERSION_);
+ REQUIRE(version && version[0], "query GL version string");
+
+ clear_color(0.2f, 0.4f, 0.8f, 1.0f);
+ clear(GL_COLOR_BUFFER_BIT_);
+ finish();
+ unsigned char pixel[4] = {0};
+ int pixel_width = 0, pixel_height = 0;
+ yasl_surface_get_framebuffer_size(primary, &pixel_width, &pixel_height);
+ REQUIRE(pixel_width > 0 && pixel_height > 0, "query initial framebuffer size");
+ read_pixels(pixel_width / 2, pixel_height / 2, 1, 1, GL_RGBA_, GL_UNSIGNED_BYTE_, pixel);
+ REQUIRE(abs((int)pixel[0] - 51) <= 3 && abs((int)pixel[1] - 102) <= 3 &&
+ abs((int)pixel[2] - 204) <= 3 && pixel[3] >= 250,
+ "read rendered pixel from the native GL framebuffer");
+ REQUIRE(yasl_gl_swap_interval(primary, 0), "disable swap interval");
+ REQUIRE(yasl_gl_swap_buffers(primary), "swap first GL surface");
+
+ unsigned texture = 0;
+ gen_textures(1, &texture);
+ bind_texture(GL_TEXTURE_2D_, texture);
+ REQUIRE(is_texture(texture), "create a shareable GL texture");
+
+ shared = yasl_gl_surface_create("YASL GL shared context", 160, 120, 0, NULL, primary);
+ REQUIRE(shared != NULL, "create shared GL context");
+ REQUIRE(yasl_gl_make_current(shared), "make shared context current");
+ REQUIRE(is_texture(texture), "verify context shares GL objects");
+ delete_textures(1, &texture);
+ REQUIRE(yasl_gl_make_current(primary), "restore primary GL context");
+
+ REQUIRE(yasl_surface_request_size(primary, 400, 300), "request surface resize");
+ wait_for_size(primary, 400, 300);
+ yasl_surface_get_framebuffer_size(primary, &pixel_width, &pixel_height);
+ double scale = yasl_surface_get_scale(primary);
+ REQUIRE(abs(pixel_width - (int)lround(400 * scale)) <= 1 &&
+ abs(pixel_height - (int)lround(300 * scale)) <= 1,
+ "query resized framebuffer dimensions");
+ clear_color(0.7f, 0.1f, 0.3f, 1.0f);
+ clear(GL_COLOR_BUFFER_BIT_);
+ REQUIRE(yasl_gl_swap_buffers(primary), "swap resized GL surface");
+
+ const int invalid_attributes[] = {0x7fff, 1, YASL_GL_END};
+ REQUIRE(yasl_gl_surface_create("invalid attrs", 100, 100, 0, invalid_attributes, NULL) == NULL,
+ "reject unknown GL context attributes");
+ REQUIRE(yasl_gl_surface_create("invalid CPU GL", 100, 100, YASL_SURFACE_CPU, NULL, NULL) == NULL,
+ "reject CPU flag on GL surface creation");
+ cpu = yasl_surface_create("CPU surface", 100, 100, YASL_SURFACE_CPU);
+ REQUIRE(cpu != NULL, "create CPU surface for incompatibility check");
+ REQUIRE(!yasl_gl_make_current(cpu), "reject CPU surface as a GL context");
+
+ REQUIRE(yasl_gl_make_current(NULL), "detach GL context before destruction");
+ yasl_surface_destroy(cpu); cpu = NULL;
+ yasl_surface_destroy(shared); shared = NULL;
+ yasl_surface_destroy(primary); primary = NULL;
+ yasl_shutdown();
+ return 0;
+}
diff --git a/tests/common/test_gl_options.c b/tests/common/test_gl_options.c
new file mode 100644
index 0000000..4bcd521
--- /dev/null
+++ b/tests/common/test_gl_options.c
@@ -0,0 +1,16 @@
+#include "common/gl_options.h"
+#include <assert.h>
+#include <stddef.h>
+#include <errno.h>
+int main(void)
+{
+ struct yasl_private_gl_options o;
+ assert(yasl_private_gl_parse_options(NULL,&o));assert(o.major==3&&o.minor==2&&o.red_bits==8);
+ const int es[]={YASL_PRIVATE_GL_API,YASL_PRIVATE_GL_OPENGL_ES,YASL_PRIVATE_GL_MAJOR,3,YASL_PRIVATE_GL_MINOR,0,YASL_PRIVATE_GL_END};
+ assert(yasl_private_gl_parse_options(es,&o)&&o.api==YASL_PRIVATE_GL_OPENGL_ES&&o.minor==0);
+ const int invalid[]={99,0,YASL_PRIVATE_GL_END};
+ assert(!yasl_private_gl_parse_options(invalid,&o)&&errno==EINVAL);
+ const int negative[]={YASL_PRIVATE_GL_DEPTH_BITS,-1,YASL_PRIVATE_GL_END};
+ assert(!yasl_private_gl_parse_options(negative,&o));
+ return 0;
+}
diff --git a/tests/common/test_hello_example.c b/tests/common/test_hello_example.c
deleted file mode 100644
index 350b3bb..0000000
--- a/tests/common/test_hello_example.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Exercise hello's real frame callback; automated exit belongs in the test. */
-#define main hello_example_main
-#include "../../examples/hello.c"
-#undef main
-
-static void draw_once(void *ud, struct yasl_surface *surface, struct yasl_frame *frame)
-{
- draw(ud, surface, frame);
- if (!failed) yasl_surface_destroy(surface);
-}
-
-int main(void)
-{
- struct yasl_window_spec window = {.title = "Hello YASL", .size = {640, 480}};
- struct yasl_app_desc desc = {
- .app_id = "org.yasl.test.hello", .window = &window,
- .frame = draw_once,
- };
- return yasl_run(&desc) || failed ? 1 : 0;
-}
diff --git a/tests/common/test_input_alloc.c b/tests/common/test_input_alloc.c
index 7aba4b2..12e7656 100644
--- a/tests/common/test_input_alloc.c
+++ b/tests/common/test_input_alloc.c
@@ -5,7 +5,7 @@
/* This executable compiles input.c with malloc redirected here. */
static int allocations = -1;
-void *yasl_test_malloc(size_t bytes)
+void *yasl_private_test_malloc(size_t bytes)
{
if (allocations == 0) return NULL;
if (allocations > 0) allocations--;
@@ -13,19 +13,19 @@ void *yasl_test_malloc(size_t bytes)
}
/* input.c timestamps events, but this executable links no event loop. */
-uint64_t yasl_loop_now_ns(void) { return 1; }
+uint64_t yasl_private_loop_now_ns(void) { return 1; }
int main(void)
{
struct yasl_surface *surface = (struct yasl_surface *)(uintptr_t)1;
for (int failure = 0; failure < 2; failure++) {
struct input_queue q = {0};
- struct yasl_event in = {.surface = surface, .type = YASL_EVENT_PASTE,
+ struct yasl_private_event in = {.surface = surface, .type = YASL_PRIVATE_EVENT_PASTE,
.text = {"payload", 7}}, out;
/* Fail either payload allocation or the initial event-array allocation. */
allocations = failure;
assert(!input_queue_push(&q, &in));
- assert(input_queue_pop(&q, &out) && out.type == YASL_EVENT_INPUT_RESET);
+ assert(input_queue_pop(&q, &out) && out.type == YASL_PRIVATE_EVENT_INPUT_RESET);
assert(out.surface == surface);
assert(!input_queue_pop(&q, &out));
input_queue_clear(&q);
@@ -40,15 +40,15 @@ int main(void)
assert(strcmp(last, "payload") == 0);
assert(!q.count && q.reset_pending);
allocations = -1;
- in = (struct yasl_event){.surface = surface, .type = YASL_EVENT_KEY,
+ in = (struct yasl_private_event){.surface = surface, .type = YASL_PRIVATE_EVENT_KEY,
.key.action = YASL_KEY_RELEASE};
assert(input_queue_push(&q, &in));
- assert(input_queue_pop(&q, &out) && out.type == YASL_EVENT_INPUT_RESET);
+ assert(input_queue_pop(&q, &out) && out.type == YASL_PRIVATE_EVENT_INPUT_RESET);
assert(input_queue_pop(&q, &out) && out.key.action == YASL_KEY_RELEASE);
input_queue_clear(&q);
/* A lost event clears held buttons along with the stream. */
- in = (struct yasl_event){.surface = surface, .type = YASL_EVENT_POINTER_DOWN};
+ in = (struct yasl_private_event){.surface = surface, .type = YASL_PRIVATE_EVENT_POINTER_DOWN};
assert(input_queue_push(&q, &in) && q.buttons);
for (size_t i = 1; i < q.capacity; i++) assert(input_queue_push(&q, &in));
allocations = 0;
diff --git a/tests/common/test_keyboard.c b/tests/common/test_keyboard.c
index f2fc8f2..7406c1d 100644
--- a/tests/common/test_keyboard.c
+++ b/tests/common/test_keyboard.c
@@ -9,27 +9,27 @@ int main(void)
{
/* Same physical positions across native encodings, including keypad and
* left/right modifiers. macOS A is code zero, which is not UNKNOWN. */
- assert(yasl_key_from_evdev(30) == YASL_KEY_A);
- assert(yasl_key_from_cocoa(kVK_ANSI_A) == YASL_KEY_A);
- assert(yasl_key_from_xkb_name("AC01") == YASL_KEY_A);
- assert(yasl_key_from_evdev(1) == YASL_KEY_ESCAPE);
- assert(yasl_key_from_cocoa(kVK_Escape) == YASL_KEY_ESCAPE);
- assert(yasl_key_from_xkb_name("ESC\0") == YASL_KEY_ESCAPE);
- assert(yasl_key_from_evdev(96) == YASL_KEY_KP_ENTER);
- assert(yasl_key_from_cocoa(kVK_ANSI_KeypadEnter) == YASL_KEY_KP_ENTER);
- assert(yasl_key_from_cocoa(kVK_Return) == YASL_KEY_ENTER);
- assert(yasl_key_from_evdev(100) == YASL_KEY_RIGHT_ALT);
- assert(yasl_key_from_cocoa(kVK_RightOption) == YASL_KEY_RIGHT_ALT);
- assert(yasl_key_from_evdev(42) == YASL_KEY_LEFT_SHIFT);
- assert(yasl_key_from_cocoa(kVK_Shift) == YASL_KEY_LEFT_SHIFT);
- assert(yasl_key_from_evdev(86) == YASL_KEY_ISO_BACKSLASH);
- assert(yasl_key_from_cocoa(kVK_ISO_Section) == YASL_KEY_ISO_BACKSLASH);
- assert(yasl_key_from_evdev(0) == YASL_KEY_UNKNOWN);
- assert(yasl_key_from_evdev(UINT32_MAX) == YASL_KEY_UNKNOWN);
- assert(yasl_key_from_cocoa(UINT32_MAX) == YASL_KEY_UNKNOWN);
- assert(yasl_key_from_xkb_name("ZZZZ") == YASL_KEY_UNKNOWN);
- assert(yasl_key_label(0x1f600) == 0x1f600);
- assert(yasl_key_label(0xd800) == 0 && yasl_key_label(0x110000) == 0);
- assert(yasl_key_label(0xf700) == 0 && yasl_key_label('\t') == 0);
+ assert(yasl_private_key_from_evdev(30) == YASL_KEY_A);
+ assert(yasl_private_key_from_cocoa(kVK_ANSI_A) == YASL_KEY_A);
+ assert(yasl_private_key_from_xkb_name("AC01") == YASL_KEY_A);
+ assert(yasl_private_key_from_evdev(1) == YASL_KEY_ESCAPE);
+ assert(yasl_private_key_from_cocoa(kVK_Escape) == YASL_KEY_ESCAPE);
+ assert(yasl_private_key_from_xkb_name("ESC\0") == YASL_KEY_ESCAPE);
+ assert(yasl_private_key_from_evdev(96) == YASL_KEY_KP_ENTER);
+ assert(yasl_private_key_from_cocoa(kVK_ANSI_KeypadEnter) == YASL_KEY_KP_ENTER);
+ assert(yasl_private_key_from_cocoa(kVK_Return) == YASL_KEY_ENTER);
+ assert(yasl_private_key_from_evdev(100) == YASL_KEY_RIGHT_ALT);
+ assert(yasl_private_key_from_cocoa(kVK_RightOption) == YASL_KEY_RIGHT_ALT);
+ assert(yasl_private_key_from_evdev(42) == YASL_KEY_LEFT_SHIFT);
+ assert(yasl_private_key_from_cocoa(kVK_Shift) == YASL_KEY_LEFT_SHIFT);
+ assert(yasl_private_key_from_evdev(86) == YASL_KEY_ISO_BACKSLASH);
+ assert(yasl_private_key_from_cocoa(kVK_ISO_Section) == YASL_KEY_ISO_BACKSLASH);
+ assert(yasl_private_key_from_evdev(0) == YASL_KEY_UNKNOWN);
+ assert(yasl_private_key_from_evdev(UINT32_MAX) == YASL_KEY_UNKNOWN);
+ assert(yasl_private_key_from_cocoa(UINT32_MAX) == YASL_KEY_UNKNOWN);
+ assert(yasl_private_key_from_xkb_name("ZZZZ") == YASL_KEY_UNKNOWN);
+ assert(yasl_private_key_label(0x1f600) == 0x1f600);
+ assert(yasl_private_key_label(0xd800) == 0 && yasl_private_key_label(0x110000) == 0);
+ assert(yasl_private_key_label(0xf700) == 0 && yasl_private_key_label('\t') == 0);
return 0;
}
diff --git a/tests/common/test_loop.c b/tests/common/test_loop.c
index f982e5e..5c49691 100644
--- a/tests/common/test_loop.c
+++ b/tests/common/test_loop.c
@@ -1,6 +1,6 @@
#define _GNU_SOURCE
#define _DARWIN_C_SOURCE
-#include "yasl/loop.h"
+#include "common/private_loop.h"
#include <assert.h>
#include <errno.h>
@@ -29,7 +29,7 @@ static void on_alarm(int signo)
}
struct post_log {
- struct yasl_loop *loop;
+ struct yasl_private_loop *loop;
char order[8];
int count;
};
@@ -46,7 +46,7 @@ static void post_a(void *ud)
{
struct post_log *log = ud;
log->order[log->count++] = 'a';
- assert(yasl_loop_post(log->loop, post_c, log));
+ assert(yasl_private_loop_post(log->loop, post_c, log));
}
static void post_b(void *ud)
@@ -57,28 +57,28 @@ static void post_b(void *ud)
static void test_post_order(void)
{
- struct yasl_loop *l = yasl_loop_create();
+ struct yasl_private_loop *l = yasl_private_loop_create();
assert(l);
- assert(!yasl_loop_post(NULL, post_b, NULL));
- assert(!yasl_loop_post(l, NULL, NULL));
+ assert(!yasl_private_loop_post(NULL, post_b, NULL));
+ assert(!yasl_private_loop_post(l, NULL, NULL));
struct post_log log = {.loop = l};
- assert(yasl_loop_post(l, post_a, &log));
- assert(yasl_loop_post(l, post_b, &log));
- assert(yasl_loop_step(l, 0) >= 1);
+ 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);
/* A post made while posts run waits for a later step. */
assert(log.count == 2 && memcmp(log.order, "ab", 2) == 0);
- assert(yasl_loop_step(l, 0) >= 1);
+ assert(yasl_private_loop_step(l, 0) >= 1);
assert(log.count == 3 && log.order[2] == 'c');
/* Destroy drops posts that never ran. */
- assert(yasl_loop_post(l, post_b, &log));
- yasl_loop_destroy(l);
+ assert(yasl_private_loop_post(l, post_b, &log));
+ yasl_private_loop_destroy(l);
assert(log.count == 3);
}
struct thread_ctx {
- struct yasl_loop *loop;
+ struct yasl_private_loop *loop;
bool kick;
int signo;
_Atomic bool ran;
@@ -97,35 +97,35 @@ static void *wake_thread(void *ud)
if (ctx->signo)
kill(getpid(), ctx->signo);
else if (ctx->kick)
- yasl_loop_kick(ctx->loop);
+ yasl_private_loop_kick(ctx->loop);
else
- assert(yasl_loop_post(ctx->loop, mark_ran, ctx));
+ assert(yasl_private_loop_post(ctx->loop, mark_ran, ctx));
return NULL;
}
static void test_cross_thread(void)
{
- struct yasl_loop *l = yasl_loop_create();
+ struct yasl_private_loop *l = yasl_private_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_loop_step(l, -1) >= 0);
+ assert(yasl_private_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_loop_step(l, -1) >= 1);
+ assert(yasl_private_loop_step(l, -1) >= 1);
pthread_join(t, NULL);
- yasl_loop_destroy(l);
+ yasl_private_loop_destroy(l);
}
struct signal_log {
- struct yasl_loop *loop;
+ struct yasl_private_loop *loop;
int seen[NSIG];
int total;
bool unwatch;
@@ -138,7 +138,7 @@ static void on_signal(void *ud, int signo)
log->seen[signo]++;
log->total++;
if (log->unwatch)
- yasl_loop_unwatch_signals(log->loop);
+ yasl_private_loop_unwatch_signals(log->loop);
}
static volatile sig_atomic_t previous_handler_hits;
@@ -149,10 +149,10 @@ static void previous_handler(int signo)
previous_handler_hits++;
}
-static void step_until(struct yasl_loop *l, const int *counter, int want)
+static void step_until(struct yasl_private_loop *l, const int *counter, int want)
{
while (*counter < want)
- assert(yasl_loop_step(l, -1) >= 0);
+ assert(yasl_private_loop_step(l, -1) >= 0);
}
static void test_signals(void)
@@ -161,30 +161,30 @@ static void test_signals(void)
sigemptyset(&prev.sa_mask);
assert(sigaction(SIGUSR2, &prev, NULL) == 0);
- struct yasl_loop *l = yasl_loop_create();
- struct yasl_loop *other = yasl_loop_create();
+ struct yasl_private_loop *l = yasl_private_loop_create();
+ struct yasl_private_loop *other = yasl_private_loop_create();
assert(l && other);
struct signal_log log = {.loop = l};
const int bad[] = {SIGKILL};
errno = 0;
- assert(!yasl_loop_watch_signals(l, bad, 1, on_signal, &log) && errno == EINVAL);
+ assert(!yasl_private_loop_watch_signals(l, bad, 1, on_signal, &log) && errno == EINVAL);
const int sigs[] = {SIGUSR1, SIGUSR2, SIGCHLD};
errno = 0;
- assert(!yasl_loop_watch_signals(l, sigs, 0, on_signal, &log) && errno == EINVAL);
+ assert(!yasl_private_loop_watch_signals(l, sigs, 0, on_signal, &log) && errno == EINVAL);
errno = 0;
- assert(!yasl_loop_watch_signals(l, sigs, 3, NULL, &log) && errno == EINVAL);
- assert(yasl_loop_watch_signals(l, sigs, 3, on_signal, &log));
+ 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));
/* One signal belongs to one loop at a time. */
errno = 0;
- assert(!yasl_loop_watch_signals(other, sigs, 1, on_signal, &log) && errno == EBUSY);
+ assert(!yasl_private_loop_watch_signals(other, sigs, 1, on_signal, &log) && errno == EBUSY);
/* Deliveries before the callback runs coalesce per signal. */
raise(SIGUSR1);
raise(SIGUSR1);
raise(SIGUSR2);
- assert(yasl_loop_step(l, 0) >= 1);
+ assert(yasl_private_loop_step(l, 0) >= 1);
assert(log.seen[SIGUSR1] == 1 && log.seen[SIGUSR2] == 1);
assert(previous_handler_hits == 0);
@@ -205,11 +205,11 @@ static void test_signals(void)
/* Replacing the watch restores the signals it drops. */
const int only_usr1[] = {SIGUSR1};
- assert(yasl_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
+ assert(yasl_private_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
raise(SIGUSR2);
assert(previous_handler_hits == 1);
- assert(yasl_loop_watch_signals(other, (const int[]){SIGUSR2}, 1, on_signal, &log));
- yasl_loop_unwatch_signals(other);
+ assert(yasl_private_loop_watch_signals(other, (const int[]){SIGUSR2}, 1, on_signal, &log));
+ yasl_private_loop_unwatch_signals(other);
assert(previous_handler_hits == 1);
raise(SIGUSR2);
assert(previous_handler_hits == 2);
@@ -221,15 +221,15 @@ static void test_signals(void)
struct sigaction now;
assert(sigaction(SIGUSR1, NULL, &now) == 0);
assert(now.sa_handler == SIG_DFL);
- yasl_loop_unwatch_signals(l);
+ yasl_private_loop_unwatch_signals(l);
/* Destroy unwatches. */
log.unwatch = false;
- assert(yasl_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
- yasl_loop_destroy(l);
+ assert(yasl_private_loop_watch_signals(l, only_usr1, 1, on_signal, &log));
+ yasl_private_loop_destroy(l);
assert(sigaction(SIGUSR1, NULL, &now) == 0);
assert(now.sa_handler == SIG_DFL);
- yasl_loop_destroy(other);
+ yasl_private_loop_destroy(other);
struct sigaction dfl = {.sa_handler = SIG_DFL};
sigemptyset(&dfl.sa_mask);
diff --git a/tests/common/test_selection.c b/tests/common/test_selection.c
index d1b3eb8..9772923 100644
--- a/tests/common/test_selection.c
+++ b/tests/common/test_selection.c
@@ -1,5 +1,5 @@
#define _POSIX_C_SOURCE 200809L
-#include "yasl/yasl.h"
+#include "common/types.h"
#include <assert.h>
#include <errno.h>
@@ -7,27 +7,27 @@
int main(void)
{
- struct yasl_display_spec spec = {.backend = (enum yasl_backend)999};
+ struct yasl_private_display_spec spec = {.backend = (enum yasl_private_backend)999};
errno = 0;
- assert(!yasl_display_open(NULL, &spec));
+ assert(!yasl_private_display_open(NULL, &spec));
assert(errno == EINVAL);
- assert(yasl_display_backend(NULL) == YASL_BACKEND_AUTO);
+ assert(yasl_private_display_backend(NULL) == YASL_PRIVATE_BACKEND_AUTO);
#if !YASL_HAS_COCOA
- spec.backend = YASL_BACKEND_COCOA;
+ spec.backend = YASL_PRIVATE_BACKEND_COCOA;
errno = 0;
- assert(!yasl_display_open(NULL, &spec));
+ assert(!yasl_private_display_open(NULL, &spec));
assert(errno == ENOSYS);
#endif
#if !YASL_HAS_WAYLAND
- spec.backend = YASL_BACKEND_WAYLAND;
+ spec.backend = YASL_PRIVATE_BACKEND_WAYLAND;
errno = 0;
- assert(!yasl_display_open(NULL, &spec));
+ assert(!yasl_private_display_open(NULL, &spec));
assert(errno == ENOSYS);
#endif
#if !YASL_HAS_X11
- spec.backend = YASL_BACKEND_X11;
+ spec.backend = YASL_PRIVATE_BACKEND_X11;
errno = 0;
- assert(!yasl_display_open(NULL, &spec));
+ assert(!yasl_private_display_open(NULL, &spec));
assert(errno == ENOSYS);
#endif
return 0;
diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c
new file mode 100644
index 0000000..2752208
--- /dev/null
+++ b/tests/common/test_surface_integration.c
@@ -0,0 +1,90 @@
+#define _POSIX_C_SOURCE 200809L
+#include <yasl/yasl.h>
+#include <yasl/cpu.h>
+#include "common/backend.h"
+#include <assert.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+static void drain(void)
+{
+ yasl_event e;int n=0;
+ while(yasl_wait_event(&e,0)>0)assert(++n<1000);
+}
+static void *wake_thread(void *unused)
+{ (void)unused;struct timespec delay={0,20000000};nanosleep(&delay,NULL);yasl_wake();return NULL; }
+static void *wrong_thread(void *data)
+{ assert(!yasl_surface_set_title(data,"wrong"));assert(yasl_get_error(NULL)==YASL_ERROR_WRONG_THREAD);return NULL; }
+static int refreshes;
+static void refresh(yasl_surface *s,void *ud)
+{
+ (void)ud;refreshes++;
+ yasl_event e;assert(yasl_wait_event(&e,0)==-1);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY);
+ yasl_surface_destroy(s);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY);
+}
+int main(int argc,char **argv)
+{
+ assert(argc==2);
+ enum yasl_backend backend=!strcmp(argv[1],"wayland")?YASL_BACKEND_WAYLAND:!strcmp(argv[1],"x11")?YASL_BACKEND_X11:YASL_BACKEND_COCOA;
+ assert(yasl_set_backend(backend));assert(yasl_set_app_id("org.yasl.surface-test"));
+ yasl_surface *s=yasl_surface_create("CPU contract",96,80,YASL_SURFACE_CPU);
+ if(!s){const char *why;yasl_get_error(&why);fprintf(stderr,"surface: %s native=%d\n",why,yasl_get_native_error());return 1;}
+ assert(yasl_surface_backend(s)==backend);
+ /* The first events report the window size, then ask for a frame. */
+ yasl_event e;int fw=0,fh=0;bool window=false;
+ for(int i=0;i<1000;i++) {
+ assert(yasl_wait_event(&e,i?20:0)>=0);
+ if(e.type==YASL_EVENT_WINDOW){window=true;fw=e.window.pixel_width;fh=e.window.pixel_height;}
+ if(e.type==YASL_EVENT_REFRESH){assert(window&&fw>0&&fh>0&&e.surface==s);break;}
+ }
+ assert(e.type==YASL_EVENT_REFRESH);
+ int w,h;yasl_surface_get_framebuffer_size(s,&w,&h);assert(w==fw&&h==fh);
+ assert(!yasl_set_backend(backend));assert(yasl_get_error(NULL)==YASL_ERROR_BUSY);
+ int pw,ph;uint32_t *pixels=yasl_cpu_pixels(s,&pw,&ph);assert(pixels&&pw==w&&ph==h);
+ assert(pixels[0]==0&&pixels[(size_t)w*h-1]==0);
+ for(size_t i=0;i<(size_t)w*h;i++)pixels[i]=0xff102030u;
+ pixels[(size_t)3*w+2]=0xffaabbccu;
+ assert(yasl_cpu_present(s));
+ assert(yasl_cpu_pixels(s,&pw,&ph)==pixels&&pixels[0]==0xff102030u&&pixels[(size_t)3*w+2]==0xffaabbccu);
+ drain();
+ pthread_t thread;assert(!pthread_create(&thread,NULL,wrong_thread,s));pthread_join(thread,NULL);
+ assert(!pthread_create(&thread,NULL,wake_thread,NULL));
+ int n=yasl_wait_event(&e,500);assert(n>=0);pthread_join(thread,NULL);
+ bool ime=yasl_surface_set_text_input(s,true,YASL_TEXT_NORMAL);
+ if(!ime)assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED);
+ bool snapshot=yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,1,3,7);
+ if(ime)assert(snapshot);
+ else assert(!snapshot&&yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED);
+ assert(!yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,2,3,8));
+ assert(!yasl_surface_set_surrounding_text(s,"\xc0\xaf",2,0,2,8));
+ drain();
+ struct yasl_private_event pen={.type=YASL_PRIVATE_EVENT_PEN,.surface=s,
+ .pen={.device_id=10,.tool_id=20,.x=12.5,.y=9.25,.pressure=0.3,
+ .axes_valid=YASL_PRIVATE_PEN_PRESSURE,.action=YASL_PRIVATE_PEN_DOWN,.in_contact=true}};
+ assert(yasl_private_events_push(s->display,s,&pen));
+ assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_PEN&&e.pen.device_id==10&&e.pen.pressure==0.3&&e.pen.in_contact);
+ struct yasl_private_event text={.type=YASL_PRIVATE_EVENT_TEXT,.surface=s,.text={.data="owned",.len=5}};
+ assert(yasl_private_events_push(s->display,s,&text));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_TEXT);
+ assert(e.text.length==5&&!strcmp(e.text.data,"owned"));
+ /* Unchanged focus folds into no event; a change reports the activated state. */
+ unsigned active=yasl_surface_state(s)&YASL_STATE_ACTIVATED;
+ struct yasl_private_event focus={.type=YASL_PRIVATE_EVENT_FOCUS,.surface=s,.focus={.focused=!active}};
+ assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_WINDOW);
+ assert((e.window.state&YASL_STATE_ACTIVATED)==(active?0u:YASL_STATE_ACTIVATED)&&e.window.pixel_width==w);
+ assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==0&&e.type==YASL_EVENT_NONE);
+ struct yasl_private_event hover={.type=YASL_PRIVATE_EVENT_DROP_HOVER,.surface=s,.drop={YASL_PRIVATE_DROP_LEAVE,{0,0}}};
+ assert(yasl_private_events_push(s->display,s,&hover));
+ assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_DROP&&e.drop.action==YASL_DROP_LEAVE);
+ yasl_surface_set_refresh_callback(s,refresh,NULL);
+ assert(yasl_cpu_present(s));
+ drain();assert(refreshes>0);
+ yasl_surface_set_refresh_callback(s,NULL,NULL);
+ yasl_surface_destroy(s);
+ assert(!yasl_set_backend(backend));
+ s=yasl_surface_create("shared backend remains",64,64,YASL_SURFACE_CPU);assert(s);
+ yasl_shutdown();assert(yasl_set_backend(backend));
+ s=yasl_surface_create("reinitialized",64,64,YASL_SURFACE_CPU);assert(s);yasl_shutdown();
+ puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed");return 0;
+}
diff --git a/tests/common/test_tablet_example.c b/tests/common/test_tablet_example.c
deleted file mode 100644
index e291b2a..0000000
--- a/tests/common/test_tablet_example.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#define main tablet_example_main
-#include "../../examples/tablet.c"
-#undef main
-#include <assert.h>
-
-static void pointer(struct app *app, enum yasl_event_type type,
- enum yasl_pointer_device device, enum yasl_pointer_button button, int x, int y, uint16_t pressure)
-{
- struct yasl_event event = {
- .type = type,
- .pointer = {
- .pos = (struct yasl_vector2i){x, y},
- .device = device,
- .button = button,
- .pen = { .pressure = pressure },
- },
- };
- input(app, &event);
-}
-
-int main(void)
-{
- struct app app = {0};
- assert(resize_canvas(&app, (struct yasl_geometry){{400, 300}, 120}));
- pointer(&app, YASL_EVENT_POINTER_MOTION, YASL_PTR_DEV_PEN, YASL_BUTTON_BACK, 80, 160, 65535);
- /* Hover never paints. */
- assert(app.canvas[(size_t)160 * app.geometry.size.x + 80] == PAPER);
- pointer(&app, YASL_EVENT_POINTER_DOWN, YASL_PTR_DEV_PEN, YASL_BUTTON_SECONDARY, 80, 160, 65535);
- /* Side button isn't the tip. */
- assert(!app.down &&
- app.canvas[(size_t)160 * app.geometry.size.x + 80] == PAPER);
- pointer(&app, YASL_EVENT_POINTER_DOWN, YASL_PTR_DEV_PEN, YASL_BUTTON_PRIMARY, 80, 160, 0);
- assert(app.down &&
- app.canvas[(size_t)160 * app.geometry.size.x + 80] == INK &&
- app.canvas[(size_t)160 * app.geometry.size.x + 90] == PAPER);
- pointer(&app, YASL_EVENT_POINTER_MOTION, YASL_PTR_DEV_PEN, YASL_BUTTON_PRIMARY, 80, 160, 65535);
- /* Stationary pressure widens brush. */
- assert(app.canvas[(size_t)160 * app.geometry.size.x + 100] == INK);
- pointer(&app, YASL_EVENT_POINTER_MOTION, YASL_PTR_DEV_PEN, YASL_BUTTON_PRIMARY, 180, 160, 20000);
- /* Segments are continuous. */
- assert(app.canvas[(size_t)160 * app.geometry.size.x + 130] == INK);
- pointer(&app, YASL_EVENT_POINTER_UP, YASL_PTR_DEV_PEN, YASL_BUTTON_PRIMARY, 180, 160, 0);
- pointer(&app, YASL_EVENT_POINTER_MOTION, YASL_PTR_DEV_PEN, YASL_BUTTON_BACK, 250, 160, 65535);
- assert(!app.down && app.canvas[(size_t)160 * app.geometry.size.x + 250] == PAPER);
- pointer(&app, YASL_EVENT_POINTER_DOWN, YASL_PTR_DEV_ERASER, YASL_BUTTON_PRIMARY, 80, 160, 65535);
- assert(app.canvas[(size_t)160 * app.geometry.size.x + 80] == PAPER &&
- app.canvas[(size_t)160 * app.geometry.size.x + 130] == INK);
- struct yasl_event reset = {.type = YASL_EVENT_INPUT_RESET};
- input(&app, &reset);
- pointer(&app, YASL_EVENT_POINTER_MOTION, YASL_PTR_DEV_ERASER, YASL_BUTTON_PRIMARY, 130, 160, 65535);
- assert(!app.down && app.canvas[(size_t)160 * app.geometry.size.x + 130] == INK);
- pointer(&app, YASL_EVENT_POINTER_DOWN, YASL_PTR_DEV_MOUSE, YASL_BUTTON_PRIMARY, 300, 200, 0);
- assert(app.canvas[(size_t)200 * app.geometry.size.x + 300] == INK);
- struct yasl_event blur = {.type = YASL_EVENT_FOCUS, .focus.focused = false};
- input(&app, &blur);
- assert(!app.down);
- assert(resize_canvas(&app, (struct yasl_geometry){{800, 600}, 240}));
- /* DPI preserves logical drawing. */
- assert(app.canvas[(size_t)400 * app.geometry.size.x + 600] == INK &&
- !app.previous);
- clear_canvas(&app);
- assert(app.canvas[(size_t)400 * app.geometry.size.x + 600] == PAPER);
- free(app.canvas);
- return 0;
-}
diff --git a/tests/common/test_timers.c b/tests/common/test_timers.c
index 8c92158..2c3542f 100644
--- a/tests/common/test_timers.c
+++ b/tests/common/test_timers.c
@@ -1,6 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include "common/loop.h"
-#include "yasl/yasl.h"
+#include "common/types.h"
#include <assert.h>
#include <stdio.h>
@@ -9,15 +9,15 @@
struct test_ctx {
int count;
uint64_t last_time;
- yasl_timer_id id;
- yasl_timer_id other_id;
- struct yasl_loop *loop;
+ yasl_private_timer_id id;
+ yasl_private_timer_id other_id;
+ struct yasl_private_loop *loop;
struct yasl_surface *surface;
bool done;
};
/* 1. Single-shot timer: returns 0, fires exactly once. */
-static uint64_t oneshot_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t oneshot_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
@@ -27,7 +27,7 @@ static uint64_t oneshot_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
}
/* 2. Repeating timer: ticks N times, then returns 0. */
-static uint64_t repeat_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t repeat_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
@@ -41,7 +41,7 @@ static uint64_t repeat_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
}
/* 3. Rescheduling timer: changes interval dynamically. */
-static uint64_t reschedule_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t reschedule_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
@@ -58,7 +58,7 @@ static uint64_t reschedule_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
}
/* 4. Timer adding another timer from inside callback. */
-static uint64_t child_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t child_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)interval_ns;
struct test_ctx *ctx = ud;
@@ -67,40 +67,40 @@ static uint64_t child_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
return 0;
}
-static uint64_t parent_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t parent_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)interval_ns;
struct test_ctx *ctx = ud;
assert(id == ctx->id);
ctx->count += 1;
- ctx->other_id = yasl_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
+ ctx->other_id = yasl_private_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
assert(ctx->other_id > 0);
return 0;
}
/* 5. Timer deleting another timer from inside callback. */
-static uint64_t victim_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t victim_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)ud; (void)id; (void)interval_ns;
assert(false && "Victim timer should have been cancelled before firing!");
return 0;
}
-static uint64_t killer_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t killer_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)id; (void)interval_ns;
struct test_ctx *ctx = ud;
ctx->count++;
- assert(yasl_loop_del_timer(ctx->loop, ctx->other_id));
+ assert(yasl_private_loop_del_timer(ctx->loop, ctx->other_id));
return 0;
}
/* 6. Millisecond convenience conversion uses the same timer callback. */
-static uint64_t ms_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t ms_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
- assert(interval_ns == YASL_MS_TO_NS(5));
+ assert(interval_ns == YASL_PRIVATE_MS_TO_NS(5));
ctx->count++;
if (ctx->count >= 3) {
ctx->done = true;
@@ -111,94 +111,94 @@ static uint64_t ms_timer_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
static void test_loop_timers(void)
{
- struct yasl_loop *l = yasl_loop_create();
+ struct yasl_private_loop *l = yasl_private_loop_create();
assert(l);
/* Invalid arguments */
- assert(yasl_loop_add_timer(NULL, 1000, oneshot_cb, NULL) == 0);
- assert(yasl_loop_add_timer(l, 0, 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_loop_next_timeout_ms(l) == -1);
+ 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_private_loop_next_timeout_ms(l) == -1);
/* Test 1: Single-shot */
struct test_ctx ctx1 = { .loop = l };
- ctx1.id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
+ ctx1.id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
assert(ctx1.id > 0);
- assert(yasl_loop_next_timeout_ms(l) >= 0);
+ assert(yasl_private_loop_next_timeout_ms(l) >= 0);
while (ctx1.count == 0) {
- int handled = yasl_loop_step(l, 50);
+ int handled = yasl_private_loop_step(l, 50);
assert(handled >= 0);
}
assert(ctx1.count == 1);
/* Should be disarmed and removed */
- assert(!yasl_loop_del_timer(l, ctx1.id));
- assert(yasl_loop_next_timeout_ms(l) == -1);
+ assert(!yasl_private_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_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
+ ctx2.id = yasl_private_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
assert(ctx2.id > 0);
while (!ctx2.done) {
- yasl_loop_step(l, 50);
+ yasl_private_loop_step(l, 50);
}
assert(ctx2.count == 5);
- assert(!yasl_loop_del_timer(l, ctx2.id));
+ assert(!yasl_private_loop_del_timer(l, ctx2.id));
/* Test 3: Reschedule dynamically */
struct test_ctx ctx3 = { .loop = l };
- ctx3.id = yasl_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
+ ctx3.id = yasl_private_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
assert(ctx3.id > 0);
while (!ctx3.done) {
- yasl_loop_step(l, 50);
+ yasl_private_loop_step(l, 50);
}
assert(ctx3.count == 2);
/* Test 4: Timer cancellation before firing */
struct test_ctx ctx4 = { .loop = l };
- yasl_timer_id cancel_id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
+ yasl_private_timer_id cancel_id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
assert(cancel_id > 0);
- assert(yasl_loop_del_timer(l, cancel_id));
- assert(!yasl_loop_del_timer(l, cancel_id));
+ assert(yasl_private_loop_del_timer(l, cancel_id));
+ assert(!yasl_private_loop_del_timer(l, cancel_id));
/* Step for 10ms; timer should not fire */
- yasl_loop_step(l, 10);
+ yasl_private_loop_step(l, 10);
assert(ctx4.count == 0);
/* Test 5: Child timer added inside callback */
struct test_ctx ctx5 = { .loop = l };
- ctx5.id = yasl_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
+ ctx5.id = yasl_private_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
while (ctx5.count < 11) {
- yasl_loop_step(l, 50);
+ yasl_private_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_loop_add_timer(l, 1000000ull, killer_timer_cb, &ctx6);
- ctx6.other_id = yasl_loop_add_timer(l, 10000000ull, victim_timer_cb, &ctx6);
+ 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);
while (ctx6.count == 0) {
- yasl_loop_step(l, 50);
+ yasl_private_loop_step(l, 50);
}
assert(ctx6.count == 1);
- yasl_loop_step(l, 20);
+ yasl_private_loop_step(l, 20);
/* Test 7: Millisecond conversion */
struct test_ctx ctx7 = { .loop = l };
- ctx7.id = yasl_loop_add_timer(l, YASL_MS_TO_NS(5), ms_timer_cb, &ctx7);
+ ctx7.id = yasl_private_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), ms_timer_cb, &ctx7);
assert(ctx7.id > 0);
while (!ctx7.done) {
- yasl_loop_step(l, 50);
+ yasl_private_loop_step(l, 50);
}
assert(ctx7.count == 3);
- yasl_loop_destroy(l);
+ yasl_private_loop_destroy(l);
}
/* Surface timer tests */
-static uint64_t surface_timer_repeat_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t surface_timer_repeat_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)interval_ns;
struct test_ctx *ctx = ud;
@@ -207,96 +207,96 @@ static uint64_t surface_timer_repeat_cb(void *ud, yasl_timer_id id, uint64_t int
return interval_ns;
}
-static uint64_t surface_suicide_cb(void *ud, yasl_timer_id id, uint64_t interval_ns)
+static uint64_t surface_suicide_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
(void)id; (void)interval_ns;
struct test_ctx *ctx = ud;
ctx->count++;
/* Destroy surface from within the timer callback */
- yasl_surface_destroy(ctx->surface);
+ yasl_private_surface_destroy(ctx->surface);
ctx->surface = NULL;
return 1000000ull; /* Even if it returns > 0, surface is destroyed */
}
static void test_surface_timers(void)
{
- struct yasl_loop *loop = yasl_loop_create();
+ struct yasl_private_loop *loop = yasl_private_loop_create();
assert(loop);
- struct yasl_display_spec spec = { .app_id = "org.yasl.timer_test" };
- struct yasl_display *d = yasl_display_open(loop, &spec);
+ 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_loop_destroy(loop);
+ yasl_private_loop_destroy(loop);
return;
}
- assert(yasl_display_loop(d) == loop);
+ assert(yasl_private_display_loop(d) == loop);
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Timer Surface",
.size = { .x = 160, .y = 100 },
};
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
assert(s);
- assert(yasl_display_loop(yasl_surface_display(s)) == loop);
+ assert(yasl_private_display_loop(yasl_private_surface_display(s)) == loop);
/* Application timers use the display's loop. */
struct test_ctx dctx = {0};
- dctx.id = yasl_loop_add_timer(yasl_display_loop(d), 2000000ull, oneshot_cb, &dctx);
+ dctx.id = yasl_private_loop_add_timer(yasl_private_display_loop(d), 2000000ull, oneshot_cb, &dctx);
assert(dctx.id > 0);
while (dctx.count == 0) {
- yasl_display_dispatch(d, 50);
+ yasl_private_display_dispatch(d, 50);
}
assert(dctx.count == 1);
/* Surface timer basic repeat & manual delete */
struct test_ctx sctx = {0};
- sctx.id = yasl_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx);
+ sctx.id = yasl_private_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx);
assert(sctx.id > 0);
while (sctx.count < 3) {
- yasl_display_dispatch(d, 50);
+ yasl_private_display_dispatch(d, 50);
}
assert(sctx.count >= 3);
- assert(yasl_surface_del_timer(s, sctx.id));
+ assert(yasl_private_surface_del_timer(s, sctx.id));
int count_before = sctx.count;
- yasl_display_dispatch(d, 10);
+ yasl_private_display_dispatch(d, 10);
assert(sctx.count == count_before);
/* A fired one-shot surface timer is retired, as a loop timer is. Many
* of them stay retired after the surface's id list compacts. */
for (int i = 0; i < 64; i++) {
struct test_ctx octx = {0};
- octx.id = yasl_surface_add_timer(s, 1000000ull, oneshot_cb, &octx);
+ octx.id = yasl_private_surface_add_timer(s, 1000000ull, oneshot_cb, &octx);
assert(octx.id > 0);
while (octx.count == 0)
- yasl_display_dispatch(d, 50);
- assert(!yasl_surface_del_timer(s, octx.id));
+ yasl_private_display_dispatch(d, 50);
+ assert(!yasl_private_surface_del_timer(s, octx.id));
}
/* Surface timer auto-cleanup on surface destruction */
struct test_ctx sctx2 = {0};
- sctx2.id = yasl_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx2);
+ sctx2.id = yasl_private_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx2);
assert(sctx2.id > 0);
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
/* Step display/loop; timer must not fire on dead surface */
- yasl_display_dispatch(d, 10);
+ yasl_private_display_dispatch(d, 10);
assert(sctx2.count == 0);
/* Surface suicide from timer callback */
- s = yasl_surface_create_toplevel(d, &sspec);
+ s = yasl_private_surface_create_toplevel(d, &sspec);
assert(s);
struct test_ctx sctx3 = { .surface = s };
- sctx3.id = yasl_surface_add_timer(s, 2000000ull, surface_suicide_cb, &sctx3);
+ sctx3.id = yasl_private_surface_add_timer(s, 2000000ull, surface_suicide_cb, &sctx3);
assert(sctx3.id > 0);
while (sctx3.count == 0) {
- yasl_display_dispatch(d, 50);
+ yasl_private_display_dispatch(d, 50);
}
assert(sctx3.count == 1);
assert(sctx3.surface == NULL);
- yasl_display_close(d);
- yasl_loop_destroy(loop);
+ yasl_private_display_close(d);
+ yasl_private_loop_destroy(loop);
}
int main(void)
diff --git a/tests/common/test_utf8.c b/tests/common/test_utf8.c
index 72f8904..58bfe9d 100644
--- a/tests/common/test_utf8.c
+++ b/tests/common/test_utf8.c
@@ -9,19 +9,19 @@ int main(void)
for (int i = 1; i <= 255; i++) latin1[i - 1] = (char)i;
latin1[255] = '\0';
size_t len = 0, back_len = 0;
- char *utf8 = yasl_utf8_from_latin1(latin1, 255, &len);
- assert(utf8 && yasl_utf8_validate(utf8, len));
- char *back = yasl_utf8_to_latin1(utf8, &back_len);
+ char *utf8 = yasl_private_utf8_from_latin1(latin1, 255, &len);
+ assert(utf8 && yasl_private_utf8_validate(utf8, len));
+ char *back = yasl_private_utf8_to_latin1(utf8, &back_len);
assert(back && back_len == 255 && memcmp(back, latin1, 256) == 0);
free(back);
free(utf8);
- assert(!yasl_utf8_to_latin1("😀", &len));
- assert(!yasl_utf8_to_latin1("\xc3", &len));
- assert(!yasl_utf8_validate("\xc3", 1));
- assert(!yasl_utf8_validate("\xe2\x82", 2));
- assert(!yasl_utf8_validate("\xf0\x9f\x98", 3));
- assert(!yasl_utf8_validate("\xed\xa0\x80", 3)); /* Surrogate. */
- assert(yasl_utf8_validate("😀", sizeof("😀") - 1));
- assert(yasl_utf8_validate(NULL, 0));
+ assert(!yasl_private_utf8_to_latin1("😀", &len));
+ assert(!yasl_private_utf8_to_latin1("\xc3", &len));
+ assert(!yasl_private_utf8_validate("\xc3", 1));
+ assert(!yasl_private_utf8_validate("\xe2\x82", 2));
+ assert(!yasl_private_utf8_validate("\xf0\x9f\x98", 3));
+ assert(!yasl_private_utf8_validate("\xed\xa0\x80", 3)); /* Surrogate. */
+ assert(yasl_private_utf8_validate("😀", sizeof("😀") - 1));
+ assert(yasl_private_utf8_validate(NULL, 0));
return 0;
}
diff --git a/tests/common/test_vulkan.c b/tests/common/test_vulkan.c
new file mode 100644
index 0000000..12daa22
--- /dev/null
+++ b/tests/common/test_vulkan.c
@@ -0,0 +1,389 @@
+/* Public Vulkan WSI integration test. The launcher supplies a real Wayland
+ * or X11 session (normally Weston/Xwayland); no internal YASL headers are
+ * used here. */
+#include "yasl/yasl.h"
+#include "yasl/vulkan.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int fail_vk(const char *what, VkResult result)
+{
+ fprintf(stderr, "vulkan integration: %s failed (VkResult %d)\n", what, result);
+ return 1;
+}
+
+static bool has_device_extension(VkPhysicalDevice device, const char *name)
+{
+ uint32_t count = 0;
+ if (vkEnumerateDeviceExtensionProperties(device, NULL, &count, NULL) != VK_SUCCESS)
+ return false;
+ VkExtensionProperties *extensions = count ? calloc(count, sizeof(*extensions)) : NULL;
+ if (count && !extensions) return false;
+ bool found = false;
+ if (vkEnumerateDeviceExtensionProperties(device, NULL, &count, extensions) == VK_SUCCESS)
+ for (uint32_t i = 0; i < count; i++)
+ if (strcmp(extensions[i].extensionName, name) == 0) found = true;
+ free(extensions);
+ return found;
+}
+
+static int run_test(enum yasl_backend backend)
+{
+ int status = 1;
+ yasl_surface *surface = NULL;
+ VkInstance instance = VK_NULL_HANDLE;
+ VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
+ VkDevice device = VK_NULL_HANDLE;
+ VkSwapchainKHR swapchain = VK_NULL_HANDLE;
+ VkCommandPool command_pool = VK_NULL_HANDLE;
+ VkSemaphore acquired = VK_NULL_HANDLE, rendered = VK_NULL_HANDLE;
+ VkCommandBuffer command = VK_NULL_HANDLE;
+
+ if (!yasl_set_backend(backend)) {
+ fprintf(stderr, "vulkan integration: cannot select requested backend %d (YASL error %d)\n",
+ backend, yasl_get_error(NULL));
+ goto cleanup;
+ }
+ if (!yasl_vulkan_init(vkGetInstanceProcAddr)) {
+ fprintf(stderr, "vulkan integration: loader initialization failed (YASL error %d)\n",
+ yasl_get_error(NULL));
+ goto cleanup;
+ }
+ surface = yasl_surface_create("yasl Vulkan WSI integration", 256, 192, 0);
+ if (!surface) {
+ fprintf(stderr, "vulkan integration: surface creation failed (YASL error %d)\n",
+ yasl_get_error(NULL));
+ goto cleanup;
+ }
+ if (!(yasl_surface_features(surface) & YASL_CAP_VULKAN)) {
+ fprintf(stderr, "vulkan integration: requested backend does not advertise Vulkan WSI\n");
+ goto cleanup;
+ }
+
+ uint32_t extension_count = 0;
+ const char *const *required = yasl_vulkan_instance_extensions(surface, &extension_count);
+ if (!required || !extension_count) {
+ fprintf(stderr, "vulkan integration: surface returned no required instance extensions\n");
+ goto cleanup;
+ }
+ uint32_t available_count = 0;
+ VkResult vr = vkEnumerateInstanceExtensionProperties(NULL, &available_count, NULL);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkEnumerateInstanceExtensionProperties", vr); goto cleanup; }
+ VkExtensionProperties *available = available_count ? calloc(available_count, sizeof(*available)) : NULL;
+ if (available_count && !available) { fprintf(stderr, "vulkan integration: out of memory\n"); goto cleanup; }
+ vr = vkEnumerateInstanceExtensionProperties(NULL, &available_count, available);
+ if (vr != VK_SUCCESS) {
+ free(available); status = fail_vk("vkEnumerateInstanceExtensionProperties", vr); goto cleanup;
+ }
+ for (uint32_t i = 0; i < extension_count; i++) {
+ bool found = false;
+ for (uint32_t j = 0; j < available_count; j++)
+ if (strcmp(required[i], available[j].extensionName) == 0) found = true;
+ if (!found) {
+ fprintf(stderr, "vulkan integration: required instance extension unavailable: %s\n", required[i]);
+ free(available); goto cleanup;
+ }
+ }
+ free(available);
+
+ VkApplicationInfo app = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pApplicationName = "yasl Vulkan WSI integration",
+ .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
+ .pEngineName = "yasl",
+ .engineVersion = VK_MAKE_VERSION(1, 0, 0),
+ .apiVersion = VK_API_VERSION_1_0,
+ };
+ VkInstanceCreateInfo instance_info = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pApplicationInfo = &app,
+ .flags = yasl_vulkan_instance_flags(surface),
+ .enabledExtensionCount = extension_count,
+ .ppEnabledExtensionNames = required,
+ };
+ vr = vkCreateInstance(&instance_info, NULL, &instance);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkCreateInstance", vr); goto cleanup; }
+ vr = yasl_vulkan_create_surface(surface, instance, NULL, &vk_surface);
+ if (vr != VK_SUCCESS) { status = fail_vk("yasl_vulkan_create_surface", vr); goto cleanup; }
+
+ uint32_t physical_count = 0;
+ vr = vkEnumeratePhysicalDevices(instance, &physical_count, NULL);
+ if (vr != VK_SUCCESS || !physical_count) {
+ status = vr == VK_SUCCESS ? 1 : fail_vk("vkEnumeratePhysicalDevices", vr);
+ if (vr == VK_SUCCESS) fprintf(stderr, "vulkan integration: no physical devices found\n");
+ goto cleanup;
+ }
+ VkPhysicalDevice *physical = calloc(physical_count, sizeof(*physical));
+ if (!physical) { fprintf(stderr, "vulkan integration: out of memory\n"); goto cleanup; }
+ vr = vkEnumeratePhysicalDevices(instance, &physical_count, physical);
+ if (vr != VK_SUCCESS) { free(physical); status = fail_vk("vkEnumeratePhysicalDevices", vr); goto cleanup; }
+
+ VkPhysicalDevice selected = VK_NULL_HANDLE;
+ uint32_t queue_family = UINT32_MAX;
+ for (uint32_t p = 0; p < physical_count && !selected; p++) {
+ if (!has_device_extension(physical[p], VK_KHR_SWAPCHAIN_EXTENSION_NAME)) continue;
+ uint32_t family_count = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &family_count, NULL);
+ VkQueueFamilyProperties *families = family_count ? calloc(family_count, sizeof(*families)) : NULL;
+ if (family_count && !families) continue;
+ vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &family_count, families);
+ for (uint32_t q = 0; q < family_count; q++) {
+ VkBool32 present = VK_FALSE;
+ if ((families[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) &&
+ vkGetPhysicalDeviceSurfaceSupportKHR(physical[p], q, vk_surface, &present) == VK_SUCCESS && present) {
+ selected = physical[p];
+ queue_family = q;
+ break;
+ }
+ }
+ free(families);
+ }
+ free(physical);
+ if (!selected) {
+ fprintf(stderr, "vulkan integration: no graphics queue with VK_KHR_swapchain presentation support\n");
+ goto cleanup;
+ }
+
+ VkPhysicalDeviceProperties properties;
+ vkGetPhysicalDeviceProperties(selected, &properties);
+ fprintf(stderr, "vulkan integration: using %s\n", properties.deviceName);
+ VkSurfaceCapabilitiesKHR capabilities;
+ vr = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(selected, vk_surface, &capabilities);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", vr); goto cleanup; }
+ if (!(capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
+ fprintf(stderr, "vulkan integration: surface images cannot be transfer destinations\n");
+ goto cleanup;
+ }
+ uint32_t format_count = 0;
+ vr = vkGetPhysicalDeviceSurfaceFormatsKHR(selected, vk_surface, &format_count, NULL);
+ if (vr != VK_SUCCESS || !format_count) {
+ status = vr == VK_SUCCESS ? 1 : fail_vk("vkGetPhysicalDeviceSurfaceFormatsKHR", vr);
+ if (vr == VK_SUCCESS) fprintf(stderr, "vulkan integration: surface has no formats\n");
+ goto cleanup;
+ }
+ VkSurfaceFormatKHR *formats = calloc(format_count, sizeof(*formats));
+ if (!formats) { fprintf(stderr, "vulkan integration: out of memory\n"); goto cleanup; }
+ vr = vkGetPhysicalDeviceSurfaceFormatsKHR(selected, vk_surface, &format_count, formats);
+ if (vr != VK_SUCCESS) { free(formats); status = fail_vk("vkGetPhysicalDeviceSurfaceFormatsKHR", vr); goto cleanup; }
+ VkSurfaceFormatKHR format = formats[0];
+ for (uint32_t i = 0; i < format_count; i++)
+ if (formats[i].format == VK_FORMAT_B8G8R8A8_SRGB &&
+ formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { format = formats[i]; break; }
+ if (format.format == VK_FORMAT_UNDEFINED) format.format = VK_FORMAT_B8G8R8A8_UNORM;
+ free(formats);
+
+ VkExtent2D extent = capabilities.currentExtent;
+ if (extent.width == UINT32_MAX) {
+ int width = 0, height = 0;
+ yasl_surface_get_framebuffer_size(surface, &width, &height);
+ if (width <= 0 || height <= 0) {
+ fprintf(stderr, "vulkan integration: surface has no drawable framebuffer extent\n");
+ goto cleanup;
+ }
+ extent.width = (uint32_t)width;
+ extent.height = (uint32_t)height;
+ if (extent.width < capabilities.minImageExtent.width) extent.width = capabilities.minImageExtent.width;
+ if (extent.width > capabilities.maxImageExtent.width) extent.width = capabilities.maxImageExtent.width;
+ if (extent.height < capabilities.minImageExtent.height) extent.height = capabilities.minImageExtent.height;
+ if (extent.height > capabilities.maxImageExtent.height) extent.height = capabilities.maxImageExtent.height;
+ }
+ uint32_t image_count = capabilities.minImageCount + 1;
+ if (capabilities.maxImageCount && image_count > capabilities.maxImageCount)
+ image_count = capabilities.maxImageCount;
+ VkCompositeAlphaFlagBitsKHR alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ if (!(capabilities.supportedCompositeAlpha & alpha)) {
+ const VkCompositeAlphaFlagBitsKHR alphas[] = {
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ };
+ bool found = false;
+ for (size_t i = 0; i < sizeof(alphas) / sizeof(alphas[0]); i++)
+ if (capabilities.supportedCompositeAlpha & alphas[i]) { alpha = alphas[i]; found = true; break; }
+ if (!found) { fprintf(stderr, "vulkan integration: no supported composite alpha mode\n"); goto cleanup; }
+ }
+ uint32_t present_mode_count = 0;
+ vr = vkGetPhysicalDeviceSurfacePresentModesKHR(selected, vk_surface, &present_mode_count, NULL);
+ if (vr != VK_SUCCESS || !present_mode_count) {
+ status = vr == VK_SUCCESS ? 1 : fail_vk("vkGetPhysicalDeviceSurfacePresentModesKHR", vr);
+ if (vr == VK_SUCCESS) fprintf(stderr, "vulkan integration: surface has no present modes\n");
+ goto cleanup;
+ }
+ VkPresentModeKHR *present_modes = calloc(present_mode_count, sizeof(*present_modes));
+ if (!present_modes) { fprintf(stderr, "vulkan integration: out of memory\n"); goto cleanup; }
+ vr = vkGetPhysicalDeviceSurfacePresentModesKHR(selected, vk_surface, &present_mode_count, present_modes);
+ free(present_modes);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkGetPhysicalDeviceSurfacePresentModesKHR", vr); goto cleanup; }
+
+ float priority = 1.0f;
+ VkDeviceQueueCreateInfo queue_info = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ .queueFamilyIndex = queue_family,
+ .queueCount = 1,
+ .pQueuePriorities = &priority,
+ };
+ const char *device_extensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
+ VkDeviceCreateInfo device_info = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .queueCreateInfoCount = 1,
+ .pQueueCreateInfos = &queue_info,
+ .enabledExtensionCount = 1,
+ .ppEnabledExtensionNames = device_extensions,
+ };
+ vr = vkCreateDevice(selected, &device_info, NULL, &device);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkCreateDevice", vr); goto cleanup; }
+ VkQueue queue;
+ vkGetDeviceQueue(device, queue_family, 0, &queue);
+
+ VkSwapchainCreateInfoKHR swap_info = {
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ .surface = vk_surface,
+ .minImageCount = image_count,
+ .imageFormat = format.format,
+ .imageColorSpace = format.colorSpace,
+ .imageExtent = extent,
+ .imageArrayLayers = 1,
+ .imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .preTransform = capabilities.currentTransform,
+ .compositeAlpha = alpha,
+ .presentMode = VK_PRESENT_MODE_FIFO_KHR,
+ .clipped = VK_TRUE,
+ };
+ vr = vkCreateSwapchainKHR(device, &swap_info, NULL, &swapchain);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkCreateSwapchainKHR", vr); goto cleanup; }
+ uint32_t swap_image_count = 0;
+ vr = vkGetSwapchainImagesKHR(device, swapchain, &swap_image_count, NULL);
+ if (vr != VK_SUCCESS || !swap_image_count) {
+ status = vr == VK_SUCCESS ? 1 : fail_vk("vkGetSwapchainImagesKHR", vr);
+ if (vr == VK_SUCCESS) fprintf(stderr, "vulkan integration: swapchain returned no images\n");
+ goto cleanup;
+ }
+ VkImage *images = calloc(swap_image_count, sizeof(*images));
+ if (!images) { fprintf(stderr, "vulkan integration: out of memory\n"); goto cleanup; }
+ vr = vkGetSwapchainImagesKHR(device, swapchain, &swap_image_count, images);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkGetSwapchainImagesKHR", vr); goto cleanup; }
+
+ VkCommandPoolCreateInfo pool_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
+ .queueFamilyIndex = queue_family,
+ };
+ vr = vkCreateCommandPool(device, &pool_info, NULL, &command_pool);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkCreateCommandPool", vr); goto cleanup; }
+ VkCommandBufferAllocateInfo command_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandPool = command_pool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = 1,
+ };
+ vr = vkAllocateCommandBuffers(device, &command_info, &command);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkAllocateCommandBuffers", vr); goto cleanup; }
+ VkSemaphoreCreateInfo semaphore_info = {.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ vr = vkCreateSemaphore(device, &semaphore_info, NULL, &acquired);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkCreateSemaphore(acquired)", vr); goto cleanup; }
+ vr = vkCreateSemaphore(device, &semaphore_info, NULL, &rendered);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkCreateSemaphore(rendered)", vr); goto cleanup; }
+
+ uint32_t image_index = 0;
+ vr = vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, acquired, VK_NULL_HANDLE, &image_index);
+ if (vr != VK_SUCCESS && vr != VK_SUBOPTIMAL_KHR) {
+ free(images); status = fail_vk("vkAcquireNextImageKHR", vr); goto cleanup;
+ }
+ VkCommandBufferBeginInfo begin = {.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
+ vr = vkBeginCommandBuffer(command, &begin);
+ if (vr != VK_SUCCESS) { free(images); status = fail_vk("vkBeginCommandBuffer", vr); goto cleanup; }
+ VkImageMemoryBarrier to_clear = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .srcAccessMask = 0,
+ .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .image = images[image_index],
+ .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
+ };
+ vkCmdPipelineBarrier(command, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &to_clear);
+ VkClearColorValue color = {.float32 = {0.08f, 0.18f, 0.32f, 1.0f}};
+ VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
+ vkCmdClearColorImage(command, images[image_index], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range);
+ VkImageMemoryBarrier to_present = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = 0,
+ .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .image = images[image_index],
+ .subresourceRange = range,
+ };
+ vkCmdPipelineBarrier(command, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &to_present);
+ vr = vkEndCommandBuffer(command);
+ free(images);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkEndCommandBuffer", vr); goto cleanup; }
+ VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ VkSubmitInfo submit = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &acquired,
+ .pWaitDstStageMask = &wait_stage,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &command,
+ .signalSemaphoreCount = 1,
+ .pSignalSemaphores = &rendered,
+ };
+ vr = vkQueueSubmit(queue, 1, &submit, VK_NULL_HANDLE);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkQueueSubmit", vr); goto cleanup; }
+ VkPresentInfoKHR present = {
+ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &rendered,
+ .swapchainCount = 1,
+ .pSwapchains = &swapchain,
+ .pImageIndices = &image_index,
+ };
+ vr = vkQueuePresentKHR(queue, &present);
+ if (vr != VK_SUCCESS && vr != VK_SUBOPTIMAL_KHR) {
+ status = fail_vk("vkQueuePresentKHR", vr); goto cleanup;
+ }
+ vr = vkDeviceWaitIdle(device);
+ if (vr != VK_SUCCESS) { status = fail_vk("vkDeviceWaitIdle", vr); goto cleanup; }
+ fprintf(stderr, "vulkan integration: created surface, cleared and presented %ux%u swapchain image\n",
+ extent.width, extent.height);
+ status = 0;
+
+cleanup:
+ if (device) vkDeviceWaitIdle(device);
+ if (rendered) vkDestroySemaphore(device, rendered, NULL);
+ if (acquired) vkDestroySemaphore(device, acquired, NULL);
+ if (command_pool) vkDestroyCommandPool(device, command_pool, NULL);
+ if (swapchain) vkDestroySwapchainKHR(device, swapchain, NULL);
+ if (device) vkDestroyDevice(device, NULL);
+ if (vk_surface) vkDestroySurfaceKHR(instance, vk_surface, NULL);
+ if (instance) vkDestroyInstance(instance, NULL);
+ if (surface) yasl_surface_destroy(surface);
+ yasl_shutdown();
+ return status;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s wayland|x11\n", argv[0]);
+ return 2;
+ }
+ enum yasl_backend backend;
+ if (strcmp(argv[1], "wayland") == 0) backend = YASL_BACKEND_WAYLAND;
+ else if (strcmp(argv[1], "x11") == 0) backend = YASL_BACKEND_X11;
+ else {
+ fprintf(stderr, "vulkan integration: unsupported backend '%s'\n", argv[1]);
+ return 2;
+ }
+ return run_test(backend);
+}