summaryrefslogtreecommitdiff
path: root/tests/common
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-14 13:56:48 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-14 13:56:48 +0300
commit87279f6903343e621c0446b20d1e7d6a495f1125 (patch)
tree999b5fb5fb76702efb02f856f082147304f0859b /tests/common
parent1ab3e5a123109704789c2768e11a4f9af515821d (diff)
Simplify the public API into one dense header
yasl.h now holds everything except Vulkan: 45 functions instead of 62, and three installed headers instead of ten. - One constructor: yasl_surface_create takes CPU, GL or NATIVE, with zero-initialized GL options meaning 3.2 core, RGBA8, D24S8. - Events carry action, mods, x, y and text at the top level; pen positions are now logical like pointer positions. - yasl_cpu_pixels/yasl_cpu_present draw into one persistent canvas, cutting three full-frame copies per frame. - yasl_surface_get_info, yasl_surface_request, YASL_CURSOR_LOCKED, yasl_surface_set_text_input, yasl_surface_begin_move_resize and yasl_surface_get_native replace groups of narrower calls. - Interactive calls drop the decorative trigger event argument. - yasl_wait_event returns 0 only on timeout or yasl_wake, the refresh callback runs only in native modal loops, focus loss sends INPUT_RESET, and a lost event no longer fails every later wait. - Unsupported operations and bad arguments report ENOTSUP and EINVAL instead of EIO; the keycodes header no longer needs C23. - The shared library gets a versioned SONAME and version macros. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/common')
-rw-r--r--tests/common/test_gl.c35
-rw-r--r--tests/common/test_surface_integration.c316
-rw-r--r--tests/common/test_vulkan.c17
3 files changed, 182 insertions, 186 deletions
diff --git a/tests/common/test_gl.c b/tests/common/test_gl.c
index 0e4597b..2bf3d8c 100644
--- a/tests/common/test_gl.c
+++ b/tests/common/test_gl.c
@@ -1,6 +1,6 @@
#define _POSIX_C_SOURCE 200809L
-#include <yasl/gl.h>
+#include <yasl/yasl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -60,7 +60,9 @@ 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);
+ struct yasl_surface_info info = yasl_surface_get_info(surface);
+ actual_width = info.width;
+ actual_height = info.height;
if (actual_width == width && actual_height == height) return;
yasl_event event = {0};
int result = yasl_wait_event(&event, 50);
@@ -75,11 +77,12 @@ static void wait_for_size(yasl_surface *surface, int width, int height)
int main(int argc, char **argv)
{
REQUIRE(argc == 2, "expected backend argument: wayland or x11");
- if (!strcmp(argv[1], "wayland")) REQUIRE((yasl_init(&(struct yasl_options){.backend=YASL_BACKEND_WAYLAND}) == 0), "select Wayland backend");
- else if (!strcmp(argv[1], "x11")) REQUIRE((yasl_init(&(struct yasl_options){.backend=YASL_BACKEND_X11}) == 0), "select X11 backend");
+ if (!strcmp(argv[1], "wayland")) REQUIRE(yasl_init(YASL_BACKEND_WAYLAND, NULL) == 0, "select Wayland backend");
+ else if (!strcmp(argv[1], "x11")) REQUIRE(yasl_init(YASL_BACKEND_X11, NULL) == 0, "select X11 backend");
else REQUIRE(false, "backend must be wayland or x11");
- primary = yasl_gl_surface_create(&(struct yasl_surface_options){.title="YASL GL test", .width=320, .height=240, .type=YASL_SURFACE_NATIVE, .flags=0}, NULL);
+ primary = yasl_surface_create(&(struct yasl_surface_options){.title="YASL GL test", .width=320, .height=240, .type=YASL_SURFACE_GL});
+ REQUIRE(yasl_get_features() & YASL_FEATURE_OPENGL, "report OpenGL support");
REQUIRE(primary != NULL, "create default OpenGL 3.2 surface");
REQUIRE((yasl_gl_make_current(primary) == 0), "make first GL context current");
@@ -109,7 +112,8 @@ int main(int argc, char **argv)
finish();
unsigned char pixel[4] = {0};
int pixel_width = 0, pixel_height = 0;
- yasl_surface_get_framebuffer_size(primary, &pixel_width, &pixel_height);
+ pixel_width = yasl_surface_get_info(primary).pixel_width;
+ pixel_height = yasl_surface_get_info(primary).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 &&
@@ -123,9 +127,7 @@ int main(int argc, char **argv)
bind_texture(GL_TEXTURE_2D_, texture);
REQUIRE(is_texture(texture), "create a shareable GL texture");
- struct yasl_gl_options sharing = YASL_GL_OPTIONS_INIT;
- sharing.share = primary;
- shared = yasl_gl_surface_create(&(struct yasl_surface_options){.title="YASL GL shared context", .width=160, .height=120, .type=YASL_SURFACE_NATIVE, .flags=0}, &sharing);
+ shared = yasl_surface_create(&(struct yasl_surface_options){.title="YASL GL shared context", .width=160, .height=120, .type=YASL_SURFACE_GL, .gl = {.share = primary}});
REQUIRE(shared != NULL, "create shared GL context");
REQUIRE((yasl_gl_make_current(shared) == 0), "make shared context current");
REQUIRE(is_texture(texture), "verify context shares GL objects");
@@ -134,8 +136,9 @@ int main(int argc, char **argv)
REQUIRE((yasl_surface_request_size(primary, 400, 300) == 0), "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);
+ pixel_width = yasl_surface_get_info(primary).pixel_width;
+ pixel_height = yasl_surface_get_info(primary).pixel_height;
+ double scale = yasl_surface_get_info(primary).scale;
REQUIRE(abs(pixel_width - (int)lround(400 * scale)) <= 1 &&
abs(pixel_height - (int)lround(300 * scale)) <= 1,
"query resized framebuffer dimensions");
@@ -143,13 +146,11 @@ int main(int argc, char **argv)
clear(GL_COLOR_BUFFER_BIT_);
REQUIRE((yasl_gl_present(primary) == 0), "swap resized GL surface");
- struct yasl_gl_options invalid_options = YASL_GL_OPTIONS_INIT;
- invalid_options.major = -1;
- REQUIRE(yasl_gl_surface_create(&(struct yasl_surface_options){.title="invalid attrs", .width=100, .height=100, .type=YASL_SURFACE_NATIVE, .flags=0}, &invalid_options) == NULL,
+ REQUIRE(yasl_surface_create(&(struct yasl_surface_options){.title="invalid attrs", .width=100, .height=100, .type=YASL_SURFACE_GL, .gl = {.major = -1}}) == NULL && errno == EINVAL,
"reject invalid GL context options");
- REQUIRE(yasl_gl_surface_create(&(struct yasl_surface_options){.title="invalid CPU GL", .width=100, .height=100, .type=YASL_SURFACE_CPU, .flags=0}, NULL) == NULL,
- "reject CPU flag on GL surface creation");
- cpu = yasl_surface_create(&(struct yasl_surface_options){.title="CPU surface", .width=100, .height=100, .type=YASL_SURFACE_CPU, .flags=0});
+ cpu = yasl_surface_create(&(struct yasl_surface_options){.title="CPU surface", .width=100, .height=100});
+ REQUIRE(yasl_surface_create(&(struct yasl_surface_options){.title="no CPU sharing", .width=100, .height=100, .type=YASL_SURFACE_GL, .gl = {.share = cpu}}) == NULL && errno == EINVAL,
+ "reject a non-GL share surface");
REQUIRE(cpu != NULL, "create CPU surface for incompatibility check");
REQUIRE((yasl_gl_make_current(cpu) < 0), "reject CPU surface as a GL context");
diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c
index 1f18f23..072a307 100644
--- a/tests/common/test_surface_integration.c
+++ b/tests/common/test_surface_integration.c
@@ -1,17 +1,5 @@
#define _POSIX_C_SOURCE 200809L
#include <yasl/yasl.h>
-#include <yasl/cpu.h>
-#include <yasl/gl.h>
-#include <yasl/metal.h>
-#if YASL_HAS_WAYLAND
-#include <yasl/native/wayland.h>
-#endif
-#if YASL_HAS_X11
-#include <yasl/native/x11.h>
-#endif
-#if YASL_HAS_COCOA
-#include <yasl/native/cocoa.h>
-#endif
#include "common/backend.h"
#include <assert.h>
#include <pthread.h>
@@ -40,18 +28,20 @@ static void *wake_thread(void *unused)
static void *wrong_thread(void *data)
{
assert(yasl_surface_set_title(data, "wrong") == -EPERM);
- struct yasl_cpu_buffer buffer;
- assert(yasl_cpu_acquire(data, &buffer) == -EPERM && !buffer.pixels);
-#if YASL_HAS_WAYLAND
- struct yasl_wayland_handles native;
- assert(yasl_wayland_get_native(data, &native) == -EPERM && !native.display && !native.surface);
-#endif
+ int w = 1, h = 1;
+ assert(!yasl_cpu_pixels(data, &w, &h) && errno == EPERM && !w && !h);
+ struct yasl_native native;
+ assert(yasl_surface_get_native(data, &native) == -EPERM && !native.wl_display && !native.x11_display);
return NULL;
}
+static void push(yasl_surface *s, struct yasl_private_event event)
+{
+ event.surface = s;
+ assert(yasl_private_events_push(s->display, s, &event));
+}
static int refreshes;
-static void refresh(yasl_surface *s, void *ud)
+static void refresh(yasl_surface *s)
{
- (void)ud;
refreshes++;
yasl_event e;
assert(yasl_wait_event(&e, 0) == -EBUSY);
@@ -59,7 +49,10 @@ static void refresh(yasl_surface *s, void *ud)
assert(yasl_surface_destroy(s) == -EBUSY);
struct yasl_surface_options options = {.width = 32, .height = 32};
assert(!yasl_surface_create(&options) && errno == EBUSY);
- assert(!yasl_gl_surface_create(&options, NULL) && errno == EBUSY);
+ options.type = YASL_SURFACE_GL;
+ assert(!yasl_surface_create(&options) && errno == EBUSY);
+ int w, h;
+ assert(yasl_cpu_pixels(s, &w, &h) && yasl_cpu_present(s) == 0);
}
int main(int argc, char **argv)
{
@@ -67,53 +60,32 @@ int main(int argc, char **argv)
enum yasl_backend backend = !strcmp(argv[1], "wayland") ? YASL_BACKEND_WAYLAND
: !strcmp(argv[1], "x11") ? YASL_BACKEND_X11
: YASL_BACKEND_COCOA;
- assert(yasl_init(
- &(struct yasl_options){.backend = backend, .app_id = "org.yasl.surface-test"}) == 0);
- yasl_surface *s = yasl_surface_create(&(struct yasl_surface_options){
- .title = "CPU contract", .width = 96, .height = 80, .type = YASL_SURFACE_CPU, .flags = 0});
+ assert(yasl_init(backend, "org.yasl.surface-test") == 0);
+ assert(yasl_init(backend, NULL) == -EALREADY);
+ assert(yasl_get_backend() == backend);
+ unsigned features = yasl_get_features();
+ yasl_surface *s = yasl_surface_create(
+ &(struct yasl_surface_options){.title = "CPU contract", .width = 96, .height = 80});
if (!s) {
- const char *why;
- why = strerror(errno);
- fprintf(stderr, "surface: %s native=%d\n", why, errno);
+ fprintf(stderr, "surface: %s\n", strerror(errno));
return 1;
}
- assert(yasl_surface_get_backend(s) == backend);
assert(yasl_surface_set_userdata(s, &backend) == 0);
assert(yasl_surface_get_userdata(s) == &backend);
-#if YASL_HAS_WAYLAND
- struct yasl_wayland_handles wl;
- int wl_result = yasl_wayland_get_native(s, &wl);
- assert(wl_result == (backend == YASL_BACKEND_WAYLAND ? 0 : -ENOTSUP));
- assert(backend == YASL_BACKEND_WAYLAND ? wl.display && wl.surface : !wl.display && !wl.surface);
- assert(yasl_wayland_get_native(s, NULL) == -EINVAL);
-#endif
-#if YASL_HAS_X11
- struct yasl_x11_handles x;
- int x_result = yasl_x11_get_native(s, &x);
- assert(x_result == (backend == YASL_BACKEND_X11 ? 0 : -ENOTSUP));
- assert(backend == YASL_BACKEND_X11 ? x.display && x.window : !x.display && !x.window);
-#endif
-#if YASL_HAS_COCOA
- struct yasl_cocoa_handles cocoa;
- assert(yasl_cocoa_get_native(s, &cocoa) == 0 && cocoa.application && cocoa.window &&
- cocoa.view);
-#endif
- CAMetalLayer *layer = NULL;
- assert(yasl_metal_get_layer(s, &layer) == -EBUSY && !layer);
- assert(yasl_surface_set_ime_caret(s, 1e300, 0, 1, 1) == -EOVERFLOW);
+ struct yasl_native native;
+ assert(yasl_surface_get_native(s, &native) == 0);
+ assert(backend != YASL_BACKEND_WAYLAND || (native.wl_display && native.wl_surface));
+ assert(backend != YASL_BACKEND_X11 || (native.x11_display && native.x11_window));
+ assert(backend != YASL_BACKEND_COCOA || (native.ns_window && native.ns_view));
+ assert(yasl_surface_get_native(s, NULL) == -EINVAL);
+ assert(!yasl_metal_get_layer(s) && errno == EBUSY);
if (backend == YASL_BACKEND_COCOA) {
- assert(!(yasl_surface_get_features(s) & YASL_CAP_OPENGL));
- assert(!yasl_gl_surface_create(&(struct yasl_surface_options){.title = "unsupported GL",
- .width = 64,
- .height = 64,
- .type = YASL_SURFACE_NATIVE,
- .flags = 0},
- NULL));
- assert(errno == ENOTSUP);
- assert((yasl_gl_make_current(NULL) < 0));
- assert(errno == ENOTSUP);
- assert(!yasl_gl_get_proc_address("glClear"));
+ assert(!(features & YASL_FEATURE_OPENGL));
+ assert(!yasl_surface_create(&(struct yasl_surface_options){
+ .title = "unsupported GL", .width = 64, .height = 64, .type = YASL_SURFACE_GL}));
assert(errno == ENOTSUP);
+ assert(yasl_gl_make_current(NULL) == 0);
+ assert(!yasl_gl_get_proc_address("glClear") && errno == ENOTSUP);
}
/* The first events report the window size, then ask for a frame. */
yasl_event e;
@@ -132,131 +104,155 @@ int main(int argc, char **argv)
}
}
assert(e.type == YASL_EVENT_REFRESH);
+ struct yasl_surface_info info = yasl_surface_get_info(s);
+ assert(info.pixel_width == fw && info.pixel_height == fh && info.scale > 0);
+
+ /* CPU pixels persist between frames and are the window's own buffer. */
int w, h;
- yasl_surface_get_framebuffer_size(s, &w, &h);
- assert(w == fw && h == fh);
- assert((yasl_init(&(struct yasl_options){.backend = backend}) < 0));
- assert(errno == EALREADY);
- struct yasl_cpu_buffer buffer, other;
- assert(yasl_cpu_acquire(s, &buffer) == 0);
- uint32_t *pixels = buffer.pixels;
- assert(buffer.width == w && buffer.height == h && buffer.stride_bytes == (size_t)w * 4);
+ uint32_t *pixels = yasl_cpu_pixels(s, &w, &h);
+ assert(pixels && w == fw && h == fh);
assert(pixels[0] == 0 && pixels[(size_t)w * h - 1] == 0);
- assert(yasl_cpu_acquire(s, &other) == -EBUSY && !other.pixels);
for (size_t i = 0; i < (size_t)w * h; i++)
pixels[i] = 0xff102030u;
pixels[(size_t)3 * w + 2] = 0xffaabbccu;
- other = buffer;
- other.stride_bytes++;
- assert(yasl_cpu_present(s, &other) == -EINVAL);
- assert(yasl_cpu_present(s, &buffer) == 0);
- assert(yasl_cpu_present(s, &buffer) == -ESTALE);
- assert(yasl_cpu_acquire(s, &buffer) == 0);
- assert(buffer.pixels[0] == 0xff102030u && buffer.pixels[(size_t)3 * w + 2] == 0xffaabbccu);
- buffer.pixels[0] = 0xffffffffu;
- assert(s->committed_pixels[0] == 0xff102030u);
- assert(yasl_cpu_discard(s, &buffer) == 0);
- assert(yasl_cpu_discard(s, &buffer) == -ESTALE);
- assert(yasl_cpu_acquire(s, &buffer) == 0 && buffer.pixels[0] == 0xff102030u);
+ assert(yasl_cpu_present(s) == 0);
+ drain();
+ pixels = yasl_cpu_pixels(s, &w, &h);
+ assert(pixels[0] == 0xff102030u && pixels[(size_t)3 * w + 2] == 0xffaabbccu);
+
+ /* Waiting ends only on an event, the timeout or yasl_wake, never early. */
+ drain();
+ uint64_t start = yasl_time_ns();
+ int n = yasl_wait_event(&e, 200);
+ assert(n == 1 || yasl_time_ns() - start >= 190000000ull);
drain();
- assert(yasl_cpu_present(s, &buffer) == -ESTALE);
- yasl_surface *second = yasl_surface_create(&(struct yasl_surface_options){
- .width = 32, .height = 32, .type = YASL_SURFACE_CPU, .userdata = &backend});
- assert(second && yasl_surface_get_userdata(second) == &backend);
- assert(yasl_cpu_acquire(s, &buffer) == 0);
- assert(yasl_cpu_acquire(second, &other) == 0);
- assert(yasl_cpu_present(second, &buffer) == -ESTALE);
- assert(yasl_cpu_discard(second, &other) == 0);
- assert(yasl_surface_destroy(second) == 0);
- assert(yasl_cpu_discard(s, &buffer) == 0);
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);
+ start = yasl_time_ns();
+ n = yasl_wait_event(&e, 5000);
pthread_join(thread, NULL);
- bool ime = (yasl_surface_set_text_input(s, true, YASL_TEXT_NORMAL) == 0);
- if (!ime)
- assert(errno == ENOTSUP);
- bool snapshot = (yasl_surface_set_surrounding_text(s, "a\xc3\xa9z", 4, 1, 3, 7) == 0);
- if (ime)
- assert(snapshot);
- else
- assert(!snapshot && errno == ENOTSUP);
- assert((yasl_surface_set_surrounding_text(s, "a\xc3\xa9z", 4, 2, 3, 8) < 0));
- assert((yasl_surface_set_surrounding_text(s, "\xc0\xaf", 2, 0, 2, 8) < 0));
+ assert(n == 1 || (n == 0 && yasl_time_ns() - start < 4000000000ull));
+ assert(!pthread_create(&thread, NULL, wrong_thread, s));
+ pthread_join(thread, NULL);
+
+ yasl_surface *second = yasl_surface_create(
+ &(struct yasl_surface_options){.width = 32, .height = 32, .userdata = &backend});
+ assert(second && yasl_surface_get_userdata(second) == &backend);
+ assert(yasl_surface_destroy(second) == 0);
+
+ /* Text input */
+ int ime = yasl_surface_set_text_input(s, &(struct yasl_text_input){
+ .text = "a\xc3\xa9z", .length = 4, .selection_begin = 1, .selection_end = 3,
+ .revision = 7, .caret_x = 1, .caret_y = 2, .caret_width = 1, .caret_height = 10});
+ assert(ime == 0 || ime == -ENOTSUP);
+ assert(yasl_surface_set_text_input(s, &(struct yasl_text_input){
+ .text = "a\xc3\xa9z", .length = 4, .selection_begin = 2, .selection_end = 3}) == -EILSEQ);
+ assert(yasl_surface_set_text_input(s, &(struct yasl_text_input){
+ .text = "\xc0\xaf", .length = 2}) == -EILSEQ);
+ assert(yasl_surface_set_text_input(s, &(struct yasl_text_input){
+ .text = "ab", .length = 2, .selection_end = 3}) == -EINVAL);
+ assert(yasl_surface_set_text_input(s, &(struct yasl_text_input){.caret_x = 1e300}) == -EOVERFLOW);
+ assert(yasl_surface_set_text_input(s, NULL) == 0 || ime == -ENOTSUP);
+
+ /* Arguments are checked before the backend sees them. */
+ assert(yasl_surface_begin_move_resize(s, YASL_EDGE_TOP | YASL_EDGE_BOTTOM) == -EINVAL);
+ assert(yasl_surface_begin_move_resize(s, 16) == -EINVAL);
+ assert(yasl_surface_request(s, (enum yasl_request)9) == -EINVAL);
+ assert(yasl_surface_request_size(s, 0, 10) == -EINVAL);
+ assert(yasl_surface_set_cursor(s, (enum yasl_cursor)99) == -EINVAL);
+ int locked = yasl_surface_set_cursor(s, YASL_CURSOR_LOCKED);
+ assert(locked == ((features & YASL_FEATURE_LOCKED_CURSOR) ? 0 : -ENOTSUP));
+ assert(yasl_surface_set_cursor(s, YASL_CURSOR_ARROW) == 0);
+ assert(yasl_drag_start(s, &(struct yasl_drag_image){.pixel_width = 4, .pixel_height = 4}) == -EINVAL);
+ uint32_t icon[4] = {0};
+ assert(yasl_drag_start(s, &(struct yasl_drag_image){
+ .pixels = icon, .pixel_width = 2, .pixel_height = 2, .hotspot_x = 2}) == -EINVAL);
+ assert(!yasl_popup_create(s, &(struct yasl_popup_options){.width = 10, .height = 10,
+ .anchor = YASL_EDGE_LEFT | YASL_EDGE_RIGHT}) &&
+ errno == EINVAL);
+ assert(yasl_clipboard_set((enum yasl_selection)5, "x") == -EINVAL);
+ assert(yasl_clipboard_set(YASL_CLIPBOARD, NULL) == -EINVAL);
+ assert(yasl_clipboard_set(YASL_CLIPBOARD, "\xff") == -EILSEQ);
+ assert(yasl_clipboard_set(YASL_PRIMARY, "x") ==
+ ((features & YASL_FEATURE_PRIMARY_SELECTION) ? 0 : -ENOTSUP));
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));
+
+ /* Event conversion: positions are logical, text is owned until the next wait. */
+ uint32_t real_scale = s->scale_120;
+ s->scale_120 = 240;
+ push(s, (struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_PEN,
+ .pen = {.device_id = 10, .x = 25, .y = 18.5, .pressure = 0.3,
+ .axes_valid = YASL_PRIVATE_PEN_PRESSURE, .action = YASL_PRIVATE_PEN_DOWN,
+ .in_contact = true}});
+ assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_PEN && e.action == YASL_PEN_DOWN);
+ assert(e.x == 12.5 && e.y == 9.25 && e.pen.device_id == 10 && e.pen.pressure == 0.3 &&
+ (e.pen.axes & YASL_PEN_PRESSURE) && e.pen.in_contact);
+ push(s, (struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_POINTER_DOWN,
+ .pointer = {.pos = {20, 10}, .button = YASL_PRIVATE_BUTTON_SECONDARY,
+ .buttons = 4, .mods = YASL_PRIVATE_MOD_CTRL}});
+ assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_POINTER &&
+ e.action == YASL_POINTER_DOWN && e.x == 10 && e.y == 5 && e.mods == YASL_MOD_CTRL &&
+ e.pointer.button == YASL_BUTTON_SECONDARY && e.pointer.buttons == 4);
+ s->scale_120 = real_scale;
+ push(s, (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_TEXT, .text = {"owned", 5}});
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_get_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(e.length == 5 && !strcmp(e.text, "owned"));
+ push(s, (struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_PASTE,
+ .paste = {.data = "", .request_id = 1, .status = YASL_PRIVATE_TRANSFER_UNAVAILABLE}});
+ assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_CLIPBOARD &&
+ e.action == YASL_TRANSFER_UNAVAILABLE && e.length == 0);
+ /* Losing focus releases held input; activation itself comes from the window state. */
+ push(s, (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_FOCUS, .focus = {.focused = false}});
+ assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_INPUT_RESET);
+ push(s, (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_FOCUS, .focus = {.focused = true}});
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);
+ push(s, (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_DROP_HOVER,
+ .drop = {YASL_PRIVATE_DROP_LEAVE, {0, 0}}});
+ assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_DROP && e.action == YASL_DROP_LEAVE);
+
+ /* A resize keeps the overlap of the pixels and zeroes the rest. */
assert(yasl_surface_request_size(s, 112, 96) == 0);
uint64_t resize_deadline = yasl_time_ns() + 3000000000ull;
- int logical_w = 0, logical_h = 0;
do {
assert(yasl_wait_event(&e, 20) >= 0);
- yasl_surface_get_size(s, &logical_w, &logical_h);
- } while ((logical_w != 112 || logical_h != 96) && yasl_time_ns() < resize_deadline);
- assert(logical_w == 112 && logical_h == 96);
- assert(yasl_cpu_acquire(s, &buffer) == 0);
- assert(buffer.pixels[0] == 0xff102030u);
- assert(buffer.pixels[(size_t)3 * buffer.width + 2] == 0xffaabbccu);
- assert(buffer.pixels[(size_t)buffer.width * buffer.height - 1] == 0);
- assert(yasl_cpu_present(s, &buffer) == 0);
- yasl_surface_set_refresh_callback(s, refresh, NULL);
- assert(yasl_cpu_acquire(s, &buffer) == 0);
- assert(yasl_cpu_present(s, &buffer) == 0);
+ info = yasl_surface_get_info(s);
+ } while ((info.width != 112 || info.height != 96) && yasl_time_ns() < resize_deadline);
+ assert(info.width == 112 && info.height == 96);
+ pixels = yasl_cpu_pixels(s, &w, &h);
+ assert(pixels && w == info.pixel_width && h == info.pixel_height);
+ assert(pixels[0] == 0xff102030u && pixels[(size_t)3 * w + 2] == 0xffaabbccu);
+ assert(pixels[(size_t)w * h - 1] == 0);
+ assert(yasl_cpu_present(s) == 0);
+
+ /* The refresh callback is reserved for modal loops; ordinary waits deliver REFRESH. */
+ s->refresh = refresh;
+ for (int i = 0; i < 5; i++) {
+ assert(yasl_cpu_pixels(s, &w, &h) && yasl_cpu_present(s) == 0);
+ assert(yasl_wait_event(&e, 20) >= 0);
+ }
+ assert(refreshes == 0);
#if YASL_HAS_COCOA
+ s->display->modal = true;
yasl_test_frame_tick(s);
-#endif
uint64_t deadline = yasl_private_loop_now_ns() + 3000000000ull;
while (!refreshes && yasl_private_loop_now_ns() < deadline)
assert(yasl_wait_event(&e, 20) >= 0);
assert(refreshes > 0);
- yasl_surface_set_refresh_callback(s, NULL, NULL);
+ s->display->modal = false;
+#endif
+ s->refresh = NULL;
yasl_surface_destroy(s);
- assert((yasl_init(&(struct yasl_options){.backend = backend}) < 0));
+ assert(yasl_init(backend, NULL) == -EALREADY);
s = yasl_surface_create(&(struct yasl_surface_options){.title = "shared backend remains",
- .width = 64,
- .height = 64,
- .type = YASL_SURFACE_CPU,
- .flags = 0});
+ .width = 64, .height = 64});
assert(s);
yasl_shutdown();
- assert((yasl_init(&(struct yasl_options){.backend = backend}) == 0));
- s = yasl_surface_create(&(struct yasl_surface_options){
- .title = "reinitialized", .width = 64, .height = 64, .type = YASL_SURFACE_CPU, .flags = 0});
+ assert(yasl_init(backend, NULL) == 0);
+ s = yasl_surface_create(
+ &(struct yasl_surface_options){.title = "reinitialized", .width = 64, .height = 64});
assert(s);
yasl_shutdown();
puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed");
diff --git a/tests/common/test_vulkan.c b/tests/common/test_vulkan.c
index b12256a..4633d55 100644
--- a/tests/common/test_vulkan.c
+++ b/tests/common/test_vulkan.c
@@ -41,30 +41,29 @@ static int run_test(enum yasl_backend backend)
VkSemaphore acquired = VK_NULL_HANDLE, rendered = VK_NULL_HANDLE;
VkCommandBuffer command = VK_NULL_HANDLE;
- if ((yasl_init(&(struct yasl_options){.backend=backend}) < 0)) {
+ if (yasl_init(backend, NULL) < 0) {
fprintf(stderr, "vulkan integration: cannot select requested backend %d (YASL error %d)\n",
backend, errno);
goto cleanup;
}
- if ((yasl_vulkan_init(vkGetInstanceProcAddr) < 0)) {
+ struct yasl_vulkan_requirements requirements;
+ if (yasl_vulkan_init(vkGetInstanceProcAddr, &requirements) < 0) {
fprintf(stderr, "vulkan integration: loader initialization failed (YASL error %d)\n",
errno);
goto cleanup;
}
- surface = yasl_surface_create(&(struct yasl_surface_options){.title="yasl Vulkan WSI integration", .width=256, .height=192, .type=YASL_SURFACE_NATIVE, .flags=0});
+ surface = yasl_surface_create(&(struct yasl_surface_options){.title="yasl Vulkan WSI integration", .width=256, .height=192, .type=YASL_SURFACE_NATIVE});
if (!surface) {
fprintf(stderr, "vulkan integration: surface creation failed (YASL error %d)\n",
errno);
goto cleanup;
}
- if (!(yasl_surface_get_features(surface) & YASL_CAP_VULKAN)) {
+ if (!(yasl_get_features() & YASL_FEATURE_VULKAN)) {
fprintf(stderr, "vulkan integration: requested backend does not advertise Vulkan WSI\n");
goto cleanup;
}
uint32_t extension_count = 0;
- struct yasl_vulkan_requirements requirements;
- if (yasl_vulkan_get_requirements(surface, &requirements) < 0) goto cleanup;
extension_count = requirements.extension_count;
const char *const *required = requirements.extensions;
if (!required || !extension_count) {
@@ -114,7 +113,7 @@ static int run_test(enum yasl_backend backend)
VkSurfaceKHR duplicate = VK_NULL_HANDLE;
if (yasl_vulkan_create_surface(surface, instance, NULL, &duplicate) != VK_ERROR_NATIVE_WINDOW_IN_USE_KHR ||
duplicate != VK_NULL_HANDLE || yasl_surface_destroy(surface) != -EBUSY ||
- yasl_shutdown() != -EBUSY || yasl_vulkan_init(vkGetInstanceProcAddr) != -EBUSY) {
+ yasl_shutdown() != -EBUSY || yasl_vulkan_init(vkGetInstanceProcAddr, &requirements) != -EBUSY) {
fprintf(stderr, "vulkan integration: live WSI ownership was not enforced\n");
goto cleanup;
}
@@ -191,8 +190,8 @@ static int run_test(enum yasl_backend backend)
VkExtent2D extent = capabilities.currentExtent;
if (extent.width == UINT32_MAX) {
- int width = 0, height = 0;
- yasl_surface_get_framebuffer_size(surface, &width, &height);
+ int width = yasl_surface_get_info(surface).pixel_width;
+ int height = yasl_surface_get_info(surface).pixel_height;
if (width <= 0 || height <= 0) {
fprintf(stderr, "vulkan integration: surface has no drawable framebuffer extent\n");
goto cleanup;