summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /tests
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff)
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/benchmark.c150
-rw-r--r--tests/cocoa/test_cursor.m24
-rw-r--r--tests/cocoa/test_keyboard.m76
-rw-r--r--tests/cocoa/test_native.c70
-rw-r--r--tests/cocoa/test_ownership.m154
-rw-r--r--tests/cocoa/test_tablet.m111
-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
-rw-r--r--tests/helpers/run_surfaces.py82
-rw-r--r--tests/meson.build348
-rw-r--r--tests/test_api.cpp95
-rw-r--r--tests/test_lifecycle.c91
-rw-r--r--tests/wayland/test_app_input.c174
-rw-r--r--tests/wayland/test_clipboard.c32
-rw-r--r--tests/wayland/test_cursor.c30
-rw-r--r--tests/wayland/test_input.c59
-rw-r--r--tests/wayland/test_keyboard.c63
-rw-r--r--tests/wayland/test_popup_positioner.c93
-rw-r--r--tests/wayland/test_relative_pointer.c30
-rw-r--r--tests/wayland/test_state.c61
-rw-r--r--tests/wayland/test_tablet.c115
-rw-r--r--tests/x11/inputtest-protocol.h4
-rw-r--r--tests/x11/test_input.c148
-rw-r--r--tests/x11/test_state.c18
-rw-r--r--tests/x11/test_tablet.c210
-rw-r--r--tests/x11/test_tablet_native.c58
41 files changed, 2461 insertions, 1944 deletions
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 1cea614..8fa8066 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -7,12 +7,12 @@
#include <time.h>
#include <limits.h>
-#include "yasl/yasl.h"
-#include "yasl/loop.h"
-#include "yasl/timing.h"
+#include "common/types.h"
+#include "common/private_loop.h"
+#include "common/private_timing.h"
#include "common/input.h"
#if YASL_HAS_WAYLAND
-#include "yasl/native/wayland.h"
+#include "common/private_native_wayland.h"
#endif
static inline uint64_t get_time_ns(void) {
@@ -48,28 +48,28 @@ static void print_bench_skipped(const char *name, const char *reason) {
static void bench_surface_lookup(void) {
const int num_surfaces = 16;
const int lookups = 10000000;
- struct yasl_display_spec spec = {
+ struct yasl_private_display_spec spec = {
.app_id = "org.yasl.benchmark",
- .backend = YASL_BACKEND_WAYLAND,
+ .backend = YASL_PRIVATE_BACKEND_WAYLAND,
};
- struct yasl_display *d = yasl_display_open(NULL, &spec);
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &spec);
struct yasl_surface *surfaces[num_surfaces];
memset(surfaces, 0, sizeof(surfaces));
if (d) {
for (int i = 0; i < num_surfaces; i++) {
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark",
.size = { .x = 320, .y = 240 },
};
- surfaces[i] = yasl_surface_create_toplevel(d, &sspec);
+ surfaces[i] = yasl_private_surface_create_toplevel(d, &sspec);
}
}
uint64_t t0 = get_time_ns();
uintptr_t sum = 0;
for (int i = 0; i < lookups; i++) {
- struct wl_surface *found = yasl_wayland_surface_get_wl_surface(surfaces[i % num_surfaces]);
+ struct wl_surface *found = yasl_private_wayland_surface_get_wl_surface(surfaces[i % num_surfaces]);
sum += (uintptr_t)found;
}
uint64_t t1 = get_time_ns();
@@ -82,35 +82,35 @@ static void bench_surface_lookup(void) {
if (d) {
for (int i = 0; i < num_surfaces; i++) {
- if (surfaces[i]) yasl_surface_destroy(surfaces[i]);
+ if (surfaces[i]) yasl_private_surface_destroy(surfaces[i]);
}
- yasl_display_close(d);
+ yasl_private_display_close(d);
}
}
/* Benchmark 2: Public Surface Geometry & Refresh Timing */
static void bench_output_follow(void) {
const int iters = 10000000;
- struct yasl_display_spec spec = {
+ struct yasl_private_display_spec spec = {
.app_id = "org.yasl.benchmark",
- .backend = YASL_BACKEND_WAYLAND,
+ .backend = YASL_PRIVATE_BACKEND_WAYLAND,
};
- struct yasl_display *d = yasl_display_open(NULL, &spec);
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &spec);
struct yasl_surface *s = NULL;
if (d) {
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark",
.size = { .x = 320, .y = 240 },
};
- s = yasl_surface_create_toplevel(d, &sspec);
+ s = yasl_private_surface_create_toplevel(d, &sspec);
}
uint64_t t0 = get_time_ns();
uint64_t sum = 0;
for (int i = 0; i < iters; i++) {
- struct yasl_geometry geom = yasl_surface_geometry(s);
- struct yasl_timing timing = yasl_surface_timing(s);
- int dev = yasl_scale_to_device(320.0, geom.scale_120);
+ struct yasl_private_geometry geom = yasl_private_surface_geometry(s);
+ struct yasl_private_timing timing = yasl_private_surface_timing(s);
+ int dev = yasl_private_scale_to_device(320.0, geom.scale_120);
sum += (uint64_t)dev + timing.refresh_ns;
}
uint64_t t1 = get_time_ns();
@@ -121,8 +121,8 @@ static void bench_output_follow(void) {
iters, (unsigned long long)sum);
print_bench_row("[2] surface_geometry_timing", per_cycle, ms, details);
- if (s) yasl_surface_destroy(s);
- if (d) yasl_display_close(d);
+ if (s) yasl_private_surface_destroy(s);
+ if (d) yasl_private_display_close(d);
}
#endif
@@ -135,8 +135,8 @@ static void bench_input_queue_resize(void) {
for (int b = 0; b < batches; b++) {
struct input_queue q = {0};
for (int i = 0; i < size; i++) {
- struct yasl_event ev = {
- .type = YASL_EVENT_POINTER_MOTION,
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_POINTER_MOTION,
.pointer = { .pos = { .x = i, .y = b } },
};
input_queue_push(&q, &ev);
@@ -160,13 +160,13 @@ static void bench_input_queue_push_pop(void) {
uint64_t t0 = get_time_ns();
for (int r = 0; r < rounds; r++) {
for (int i = 0; i < events_per_round; i++) {
- struct yasl_event ev = {
- .type = YASL_EVENT_POINTER_DOWN,
- .pointer = { .pos = { .x = i, .y = r }, .button = YASL_BUTTON_MIDDLE },
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_POINTER_DOWN,
+ .pointer = { .pos = { .x = i, .y = r }, .button = YASL_PRIVATE_BUTTON_MIDDLE },
};
input_queue_push(&q, &ev);
}
- struct yasl_event out;
+ struct yasl_private_event out;
while (input_queue_pop(&q, &out)) {
/* consume */
}
@@ -181,22 +181,22 @@ static void bench_input_queue_push_pop(void) {
}
/* Benchmark 5: Event Loop Timers Add & Delete */
-static uint64_t timer_dummy_cb(void *ud, yasl_timer_id id, uint64_t interval_ns) {
+static uint64_t timer_dummy_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns) {
(void)ud; (void)id; (void)interval_ns;
return 0;
}
static void bench_timers(void) {
const int iters = 2000000;
- struct yasl_loop *loop = yasl_loop_create();
+ struct yasl_private_loop *loop = yasl_private_loop_create();
uint64_t t0 = get_time_ns();
for (int i = 0; i < iters; i++) {
- yasl_timer_id id = yasl_loop_add_timer(loop, 1000000, timer_dummy_cb, NULL);
- yasl_loop_del_timer(loop, id);
+ yasl_private_timer_id id = yasl_private_loop_add_timer(loop, 1000000, timer_dummy_cb, NULL);
+ yasl_private_loop_del_timer(loop, id);
}
uint64_t t1 = get_time_ns();
- yasl_loop_destroy(loop);
+ yasl_private_loop_destroy(loop);
double ms = (double)(t1 - t0) / 1e6;
double per_cycle = (double)(t1 - t0) / iters;
char details[128];
@@ -207,30 +207,30 @@ static void bench_timers(void) {
/* Benchmark 6: Window Cold Create & Teardown */
static void bench_window_cold_create(void) {
const int iters = 200;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.cold" };
- struct yasl_window_spec sspec = {
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.cold" };
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark Cold",
.size = { .x = 320, .y = 240 },
};
- struct yasl_display *probe = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display *probe = yasl_private_display_open(NULL, &dspec);
if (!probe) {
print_bench_skipped("[6] window_cold_create", "no display server");
return;
}
- yasl_display_close(probe);
+ yasl_private_display_close(probe);
uint64_t t0 = get_time_ns();
int count = 0;
for (int i = 0; i < iters; i++) {
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (d) {
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
if (s) {
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
count++;
}
- yasl_display_close(d);
+ yasl_private_display_close(d);
}
}
uint64_t t1 = get_time_ns();
@@ -244,14 +244,14 @@ static void bench_window_cold_create(void) {
/* Benchmark 7: Window Warm Create */
static void bench_window_warm_create(void) {
const int iters = 2000;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.warm" };
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.warm" };
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (!d) {
print_bench_skipped("[7] window_warm_create", "no display server");
return;
}
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark Warm",
.size = { .x = 320, .y = 240 },
};
@@ -259,14 +259,14 @@ static void bench_window_warm_create(void) {
uint64_t t0 = get_time_ns();
int count = 0;
for (int i = 0; i < iters; i++) {
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
if (s) {
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
count++;
}
}
uint64_t t1 = get_time_ns();
- yasl_display_close(d);
+ yasl_private_display_close(d);
double ms = (double)(t1 - t0) / 1e6;
double per_cycle = count ? (double)(t1 - t0) / count : 0.0;
char details[128];
@@ -277,14 +277,14 @@ static void bench_window_warm_create(void) {
/* Benchmark 8: Window Shutdown (Single) */
static void bench_window_shutdown_single(void) {
const int iters = 2000;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.shutdown_single" };
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.shutdown_single" };
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (!d) {
print_bench_skipped("[8] window_shutdown_single", "no display server");
return;
}
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark Shutdown Single",
.size = { .x = 320, .y = 240 },
};
@@ -292,16 +292,16 @@ static void bench_window_shutdown_single(void) {
uint64_t destroy_time_ns = 0;
int count = 0;
for (int i = 0; i < iters; i++) {
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
if (s) {
uint64_t t0 = get_time_ns();
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
uint64_t t1 = get_time_ns();
destroy_time_ns += (t1 - t0);
count++;
}
}
- yasl_display_close(d);
+ yasl_private_display_close(d);
double ms = (double)destroy_time_ns / 1e6;
double per_cycle = count ? (double)destroy_time_ns / count : 0.0;
char details[128];
@@ -313,14 +313,14 @@ static void bench_window_shutdown_single(void) {
static void bench_window_shutdown_all(void) {
const int batches = 50;
const int batch_size = 64;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.shutdown_all" };
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.shutdown_all" };
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (!d) {
print_bench_skipped("[9] window_shutdown_all", "no display server");
return;
}
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Benchmark Bulk Window",
.size = { .x = 320, .y = 240 },
};
@@ -331,12 +331,12 @@ static void bench_window_shutdown_all(void) {
for (int b = 0; b < batches; b++) {
for (int i = 0; i < batch_size; i++) {
- surfaces[i] = yasl_surface_create_toplevel(d, &sspec);
+ surfaces[i] = yasl_private_surface_create_toplevel(d, &sspec);
}
uint64_t t0 = get_time_ns();
for (int i = 0; i < batch_size; i++) {
if (surfaces[i]) {
- yasl_surface_destroy(surfaces[i]);
+ yasl_private_surface_destroy(surfaces[i]);
surfaces[i] = NULL;
total_destroyed++;
}
@@ -344,7 +344,7 @@ static void bench_window_shutdown_all(void) {
uint64_t t1 = get_time_ns();
destroy_time_ns += (t1 - t0);
}
- yasl_display_close(d);
+ yasl_private_display_close(d);
double ms = (double)destroy_time_ns / 1e6;
double per_cycle = total_destroyed ? (double)destroy_time_ns / total_destroyed : 0.0;
double per_batch_ns = batches ? (double)destroy_time_ns / batches : 0.0;
@@ -359,20 +359,20 @@ static void bench_window_shutdown_all(void) {
/* Benchmark 10: Window Titlebar Update */
static void bench_window_title_update(void) {
const int iters = 200000;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.title" };
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.title" };
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (!d) {
print_bench_skipped("[10] window_titlebar_update", "no display server");
return;
}
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Initial Title",
.size = { .x = 320, .y = 240 },
};
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
if (!s) {
- yasl_display_close(d);
+ yasl_private_display_close(d);
print_bench_skipped("[10] window_titlebar_update", "failed to create surface");
return;
}
@@ -386,11 +386,11 @@ static void bench_window_title_update(void) {
uint64_t t0 = get_time_ns();
for (int i = 0; i < iters; i++) {
- yasl_surface_set_title(s, titles[i & 3]);
+ yasl_private_surface_set_title(s, titles[i & 3]);
}
uint64_t t1 = get_time_ns();
- yasl_surface_destroy(s);
- yasl_display_close(d);
+ yasl_private_surface_destroy(s);
+ yasl_private_display_close(d);
double ms = (double)(t1 - t0) / 1e6;
double per_cycle = (double)(t1 - t0) / iters;
char details[128];
@@ -401,14 +401,14 @@ static void bench_window_title_update(void) {
/* Benchmark 11: Window Resize / Dimension Reallocation */
static void bench_window_resize(void) {
const int iters = 2000;
- struct yasl_display_spec dspec = { .app_id = "org.yasl.bench.resize" };
- struct yasl_display *d = yasl_display_open(NULL, &dspec);
+ struct yasl_private_display_spec dspec = { .app_id = "org.yasl.bench.resize" };
+ struct yasl_private_display *d = yasl_private_display_open(NULL, &dspec);
if (!d) {
print_bench_skipped("[11] window_resize_cycle", "no display server");
return;
}
- static const struct yasl_vector2i sizes[] = {
+ static const struct yasl_private_vector2i sizes[] = {
{ 320, 240 },
{ 640, 480 },
{ 800, 600 },
@@ -421,20 +421,20 @@ static void bench_window_resize(void) {
uint64_t t0 = get_time_ns();
int count = 0;
for (int i = 0; i < iters; i++) {
- struct yasl_window_spec sspec = {
+ struct yasl_private_window_spec sspec = {
.title = "Resize Bench",
.size = sizes[i % num_sizes],
};
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &sspec);
if (s) {
- struct yasl_geometry geom = yasl_surface_geometry(s);
+ struct yasl_private_geometry geom = yasl_private_surface_geometry(s);
(void)geom;
- yasl_surface_destroy(s);
+ yasl_private_surface_destroy(s);
count++;
}
}
uint64_t t1 = get_time_ns();
- yasl_display_close(d);
+ yasl_private_display_close(d);
double ms = (double)(t1 - t0) / 1e6;
double per_cycle = count ? (double)(t1 - t0) / count : 0.0;
char details[128];
diff --git a/tests/cocoa/test_cursor.m b/tests/cocoa/test_cursor.m
index 4054d59..4c961df 100644
--- a/tests/cocoa/test_cursor.m
+++ b/tests/cocoa/test_cursor.m
@@ -1,5 +1,5 @@
#import <AppKit/AppKit.h>
-#include <yasl/native.h>
+#include <common/private_native.h>
#include <assert.h>
static void assert_transparent(NSCursor *cursor)
@@ -15,18 +15,18 @@ static void assert_transparent(NSCursor *cursor)
int main(void)
{
@autoreleasepool {
- struct yasl_display *display = yasl_display_open(NULL, NULL);
+ struct yasl_private_display *display = yasl_private_display_open(NULL, NULL);
assert(display);
- struct yasl_window_spec spec = {.title = "Cursor test", .size = {320, 240}};
- struct yasl_surface *surface = yasl_surface_create_toplevel(display, &spec);
+ struct yasl_private_window_spec spec = {.title = "Cursor test", .size = {320, 240}};
+ struct yasl_surface *surface = yasl_private_surface_create_toplevel(display, &spec);
assert(surface);
- NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(surface);
+ NSWindow *window = (NSWindow *)yasl_private_surface_get_native_handle(surface);
NSView *view = window.contentView;
NSEvent *cursor = [NSEvent enterExitEventWithType:NSEventTypeCursorUpdate
location:NSMakePoint(100, 120) modifierFlags:0 timestamp:0
windowNumber:window.windowNumber context:nil eventNumber:0 trackingNumber:0 userData:NULL];
assert(cursor);
- yasl_surface_set_cursor(surface, YASL_CURSOR_HIDDEN);
+ yasl_private_surface_set_cursor(surface, YASL_PRIVATE_CURSOR_HIDDEN);
[view cursorUpdate:cursor];
NSCursor *hidden = [NSCursor currentCursor];
assert_transparent(hidden);
@@ -37,21 +37,21 @@ int main(void)
[view mouseMoved:motion];
[view cursorUpdate:cursor];
assert([NSCursor currentCursor] == hidden);
- struct yasl_event event;
+ struct yasl_private_event event;
bool moved = false;
- while (yasl_surface_poll_event(surface, &event))
- if (event.type == YASL_EVENT_POINTER_MOTION)
+ while (yasl_private_surface_poll_event(surface, &event))
+ if (event.type == YASL_PRIVATE_EVENT_POINTER_MOTION)
moved = true;
assert(moved);
[[NSCursor arrowCursor] set]; /* Simulate leaving and re-entering. */
[view cursorUpdate:cursor];
assert([NSCursor currentCursor] == hidden);
- yasl_surface_set_cursor(surface, YASL_CURSOR_ARROW);
+ yasl_private_surface_set_cursor(surface, YASL_PRIVATE_CURSOR_ARROW);
[view cursorUpdate:cursor];
assert([NSCursor currentCursor] == [NSCursor arrowCursor]);
- yasl_surface_destroy(surface);
- yasl_display_close(display);
+ yasl_private_surface_destroy(surface);
+ yasl_private_display_close(display);
}
return 0;
}
diff --git a/tests/cocoa/test_keyboard.m b/tests/cocoa/test_keyboard.m
index f93a745..a41011c 100644
--- a/tests/cocoa/test_keyboard.m
+++ b/tests/cocoa/test_keyboard.m
@@ -1,5 +1,6 @@
#import <AppKit/AppKit.h>
-#include <yasl/native.h>
+#include <common/private_native.h>
+#include <common/backend.h>
#include <assert.h>
#include <math.h>
#include <string.h>
@@ -31,32 +32,40 @@
}
@end
-static struct yasl_event next(struct yasl_surface *surface, enum yasl_event_type type)
+static struct yasl_private_event next(struct yasl_surface *surface, enum yasl_private_event_type type)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(surface, &event));
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(surface, &event));
assert(event.type == type && event.surface == surface);
return event;
}
static void empty(struct yasl_surface *surface)
{
- struct yasl_event event;
- assert(!yasl_surface_poll_event(surface, &event));
+ struct yasl_private_event event;
+ assert(!yasl_private_surface_poll_event(surface, &event));
}
int main(void)
{
@autoreleasepool {
- struct yasl_display *display = yasl_display_open(NULL, NULL);
+ struct yasl_private_display *display = yasl_private_display_open(NULL, NULL);
assert(display);
- struct yasl_window_spec spec = {.title = "Keyboard test", .size = {320, 240}};
- struct yasl_surface *surface = yasl_surface_create_toplevel(display, &spec);
+ struct yasl_private_window_spec spec = {.title = "Keyboard test", .size = {320, 240}};
+ struct yasl_surface *surface = yasl_private_surface_create_toplevel(display, &spec);
assert(surface);
- NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(surface);
+ surface->text_input_active = true;
+ surface->text_surrounding = strdup("A😀B");
+ surface->text_length = strlen(surface->text_surrounding);
+ surface->text_begin = 1;
+ surface->text_end = 5;
+ surface->text_revision = 7;
+ surface->text_generation = 3;
+ assert(display->ops->surface_update_text_input(surface));
+ NSWindow *window = (NSWindow *)yasl_private_surface_get_native_handle(surface);
NSView<NSTextInputClient> *view = (id)window.contentView;
- struct yasl_event event;
- while (yasl_surface_poll_event(surface, &event)) {}
+ struct yasl_private_event event;
+ while (yasl_private_surface_poll_event(surface, &event)) {}
InputSample *sample = [InputSample new];
NSEvent *native = (NSEvent *)sample;
@@ -65,7 +74,7 @@ int main(void)
sample.label = @"q";
sample.shiftedLabel = @"Q";
[view keyUp:native];
- event = next(surface, YASL_EVENT_KEY);
+ event = next(surface, YASL_PRIVATE_EVENT_KEY);
assert(event.key.key == YASL_KEY_A && event.key.native_code == 0);
assert(event.key.action == YASL_KEY_RELEASE);
assert(event.key.codepoint == 'q' && event.key.shifted == 'Q');
@@ -73,29 +82,31 @@ int main(void)
sample.label = @"😀"; /* One scalar, two UTF-16 units. */
sample.shiftedLabel = @"ab";
[view keyUp:native];
- event = next(surface, YASL_EVENT_KEY);
+ event = next(surface, YASL_PRIVATE_EVENT_KEY);
assert(event.key.codepoint == 0x1f600 && event.key.shifted == 0);
sample.type = NSEventTypeFlagsChanged;
sample.keyCode = 56; /* Left Shift. */
sample.modifierFlags = NSEventModifierFlagShift | 0x0002;
[view flagsChanged:native];
- event = next(surface, YASL_EVENT_KEY);
+ event = next(surface, YASL_PRIVATE_EVENT_KEY);
assert(event.key.key == YASL_KEY_LEFT_SHIFT && event.key.action == YASL_KEY_PRESS);
- assert(event.key.mods == YASL_MOD_SHIFT && !event.key.codepoint && !event.key.shifted);
+ assert(event.key.mods == YASL_PRIVATE_MOD_SHIFT && !event.key.codepoint && !event.key.shifted);
sample.modifierFlags = 0;
[view flagsChanged:native];
- assert(next(surface, YASL_EVENT_KEY).key.action == YASL_KEY_RELEASE);
+ assert(next(surface, YASL_PRIVATE_EVENT_KEY).key.action == YASL_KEY_RELEASE);
/* Native text services own preedit and commits. Marked text is not an
* insertion, and commits retain all UTF-8 bytes, including non-BMP. */
[view setMarkedText:@"é" selectedRange:NSMakeRange(1, 0)
- replacementRange:NSMakeRange(NSNotFound, 0)];
- assert(strcmp(yasl_surface_ime_preedit(surface), "é") == 0);
+ replacementRange:NSMakeRange(1, 2)];
+ assert(strcmp(yasl_private_surface_ime_preedit(surface), "é") == 0);
empty(surface);
[view insertText:@"😀é" replacementRange:NSMakeRange(NSNotFound, 0)];
- event = next(surface, YASL_EVENT_TEXT);
- assert(event.text.len == strlen("😀é") && strcmp(event.text.data, "😀é") == 0);
- assert(!yasl_surface_ime_preedit(surface));
+ event = next(surface, YASL_PRIVATE_EVENT_TEXT_EDIT);
+ assert(event.text_edit.len == strlen("😀é") && strcmp(event.text_edit.data, "😀é") == 0);
+ assert(event.text_edit.begin == 1 && event.text_edit.end == 5);
+ assert(event.text_edit.revision == 7 && event.text_edit.generation == 3);
+ assert(!yasl_private_surface_ime_preedit(surface));
empty(surface);
/* Exercise the keyDown -> interpretKeyEvents -> insertText route with
@@ -104,9 +115,16 @@ int main(void)
modifierFlags:0 timestamp:0 windowNumber:window.windowNumber context:nil
characters:@"a" charactersIgnoringModifiers:@"a" isARepeat:NO keyCode:0];
[view keyDown:press];
- assert(next(surface, YASL_EVENT_KEY).key.key == YASL_KEY_A);
- event = next(surface, YASL_EVENT_TEXT);
- assert(event.text.len == 1 && event.text.data[0] == 'a');
+ assert(next(surface, YASL_PRIVATE_EVENT_KEY).key.key == YASL_KEY_A);
+ event = next(surface, YASL_PRIVATE_EVENT_TEXT_EDIT);
+ assert(event.text_edit.len == 1 && event.text_edit.data[0] == 'a');
+ assert(event.text_edit.begin == 1 && event.text_edit.end == 5);
+ empty(surface);
+
+ surface->text_end = 1;
+ [view doCommandBySelector:@selector(deleteBackward)];
+ event = next(surface, YASL_PRIVATE_EVENT_TEXT_EDIT);
+ assert(event.text_edit.len == 0 && event.text_edit.begin == 0 && event.text_edit.end == 1);
empty(surface);
sample.type = NSEventTypeScrollWheel;
@@ -114,20 +132,20 @@ int main(void)
sample.scrollingDeltaX = -2.5;
sample.scrollingDeltaY = 1.25;
[view scrollWheel:native];
- event = next(surface, YASL_EVENT_POINTER_SCROLL);
+ event = next(surface, YASL_PRIVATE_EVENT_POINTER_SCROLL);
assert(event.pointer.scroll.x == 0.25 && event.pointer.scroll.y == -0.125);
sample.hasPreciseScrollingDeltas = NO;
sample.scrollingDeltaX = 1;
sample.scrollingDeltaY = -1;
[view scrollWheel:native];
- event = next(surface, YASL_EVENT_POINTER_SCROLL);
+ event = next(surface, YASL_PRIVATE_EVENT_POINTER_SCROLL);
assert(event.pointer.scroll.x == -1 && event.pointer.scroll.y == 1);
sample.scrollingDeltaX = NAN;
[view scrollWheel:native];
empty(surface);
[sample release];
- yasl_surface_destroy(surface);
- yasl_display_close(display);
+ yasl_private_surface_destroy(surface);
+ yasl_private_display_close(display);
}
return 0;
}
diff --git a/tests/cocoa/test_native.c b/tests/cocoa/test_native.c
index 674513d..9b8f8fa 100644
--- a/tests/cocoa/test_native.c
+++ b/tests/cocoa/test_native.c
@@ -1,77 +1,77 @@
#define _POSIX_C_SOURCE 200809L
-#include "yasl/native.h"
-#include "yasl/loop.h"
-#include "yasl/yasl.h"
+#include "common/private_native.h"
+#include "common/private_loop.h"
+#include "common/types.h"
#include <assert.h>
#include <time.h>
struct state {
- struct yasl_display *display;
+ struct yasl_private_display *display;
struct yasl_surface *surface;
unsigned draws;
};
-static void draw(struct yasl_surface *surface, struct yasl_frame *frame, void *ud)
+static void draw(struct yasl_surface *surface, struct yasl_private_frame *frame, void *ud)
{
struct state *state = ud;
assert(surface == state->surface && frame->surface == surface);
- assert(yasl_surface_display(surface) == state->display);
+ assert(yasl_private_surface_display(surface) == state->display);
assert(frame->target.pixels);
- struct yasl_native_frame native;
- assert(yasl_surface_get_native_frame(surface, &frame->target, &native));
+ struct yasl_private_native_frame native;
+ assert(yasl_private_surface_get_native_frame(surface, &frame->target, &native));
assert(native.drawable);
- struct yasl_vector2i size = yasl_surface_geometry(surface).size;
+ struct yasl_private_vector2i size = yasl_private_surface_geometry(surface).size;
assert(size.x == frame->target.size.x && size.y == frame->target.size.y);
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(surface, &frame->target, &damage));
+ struct yasl_private_damage_list damage = {.n = YASL_PRIVATE_DAMAGE_MAX + 1};
+ assert(!yasl_private_surface_present(surface, &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(surface, &invalid, &damage));
+ assert(!yasl_private_surface_present(surface, &invalid, &damage));
invalid = frame->target;
invalid.generation--;
- assert(!yasl_surface_present(surface, &invalid, &damage));
- assert(!yasl_surface_present(surface, &frame->target, NULL));
- assert(yasl_surface_present(surface, &frame->target, &damage));
- assert(!yasl_surface_get_native_frame(surface, &frame->target, &native));
- assert(!yasl_surface_present(surface, &frame->target, &damage));
+ assert(!yasl_private_surface_present(surface, &invalid, &damage));
+ assert(!yasl_private_surface_present(surface, &frame->target, NULL));
+ assert(yasl_private_surface_present(surface, &frame->target, &damage));
+ assert(!yasl_private_surface_get_native_frame(surface, &frame->target, &native));
+ assert(!yasl_private_surface_present(surface, &frame->target, &damage));
state->draws++;
- yasl_surface_destroy(surface);
+ yasl_private_surface_destroy(surface);
state->surface = NULL;
}
-static void test_window(enum yasl_backend request, bool null_spec)
+static void test_window(enum yasl_private_backend request, bool null_spec)
{
- struct yasl_display_spec spec = {.backend = request};
- struct state state = {.display = yasl_display_open(NULL, null_spec ? NULL : &spec)};
+ struct yasl_private_display_spec spec = {.backend = request};
+ struct state state = {.display = yasl_private_display_open(NULL, null_spec ? NULL : &spec)};
assert(state.display);
- assert(yasl_display_backend(state.display) == YASL_BACKEND_COCOA);
- struct yasl_window_cbs callbacks = {.draw = draw};
- struct yasl_window_spec surface = {
+ assert(yasl_private_display_backend(state.display) == YASL_PRIVATE_BACKEND_COCOA);
+ struct yasl_private_window_cbs callbacks = {.draw = draw};
+ struct yasl_private_window_spec surface = {
.title = "Native backend test", .size = {160, 100},
.cbs = &callbacks, .ud = &state,
};
- state.surface = yasl_surface_create_toplevel(state.display, &surface);
+ state.surface = yasl_private_surface_create_toplevel(state.display, &surface);
assert(state.surface);
assert(!state.draws);
callbacks.draw = NULL;
- yasl_surface_schedule_redraw(state.surface);
- uint64_t deadline = yasl_loop_now_ns() + 3000000000ull;
- while (!state.draws && yasl_loop_now_ns() < deadline) {
- yasl_display_dispatch(state.display, 0);
- yasl_display_flush(state.display);
+ yasl_private_surface_schedule_redraw(state.surface);
+ uint64_t deadline = yasl_private_loop_now_ns() + 3000000000ull;
+ while (!state.draws && yasl_private_loop_now_ns() < deadline) {
+ yasl_private_display_dispatch(state.display, 0);
+ yasl_private_display_flush(state.display);
nanosleep(&(struct timespec){.tv_nsec = 1000000}, NULL);
}
assert(state.draws == 1 && !state.surface);
- yasl_display_close(state.display);
+ yasl_private_display_close(state.display);
}
int main(void)
{
- test_window(YASL_BACKEND_AUTO, true);
- test_window(YASL_BACKEND_AUTO, false);
- test_window(YASL_BACKEND_COCOA, false);
+ test_window(YASL_PRIVATE_BACKEND_AUTO, true);
+ test_window(YASL_PRIVATE_BACKEND_AUTO, false);
+ test_window(YASL_PRIVATE_BACKEND_COCOA, false);
return 0;
}
diff --git a/tests/cocoa/test_ownership.m b/tests/cocoa/test_ownership.m
index 6d69907..4efd164 100644
--- a/tests/cocoa/test_ownership.m
+++ b/tests/cocoa/test_ownership.m
@@ -1,7 +1,9 @@
-#include "yasl/native.h"
-#include "yasl/native/cocoa.h"
+#include "common/private_native.h"
+#include "common/private_native_cocoa.h"
+#include "common/backend.h"
#import <AppKit/AppKit.h>
-#include "yasl/yasl.h"
+#import <Metal/Metal.h>
+#include "common/types.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
@@ -9,60 +11,98 @@
int main(void)
{
- struct yasl_display *d = yasl_display_open(NULL, NULL);
+ struct yasl_private_display *d = yasl_private_display_open(NULL, NULL);
assert(d);
- struct yasl_window_spec spec = {.title = "Ownership test", .size = {160, 100}};
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &spec);
+ assert(yasl_private_display_caps(d) & YASL_PRIVATE_CAP_TEXT_INPUT);
+ struct yasl_private_window_spec spec = {.title = "Ownership test", .size = {160, 100}};
+ struct yasl_surface *s = yasl_private_surface_create_toplevel(d, &spec);
assert(s);
- assert(yasl_display_get_native_handle(d) == (void *)NSApp);
- assert(yasl_cocoa_display_get_application(d) == NSApp);
- NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(s);
- assert(yasl_cocoa_surface_get_window(s) == window);
- assert(yasl_cocoa_surface_get_view(s) == window.contentView);
+ assert(yasl_private_display_get_native_handle(d) == (void *)NSApp);
+ assert(yasl_private_cocoa_display_get_application(d) == NSApp);
+ NSWindow *window = (NSWindow *)yasl_private_surface_get_native_handle(s);
+ assert(yasl_private_cocoa_surface_get_window(s) == window);
+ assert(yasl_private_cocoa_surface_get_view(s) == window.contentView);
assert([window isKindOfClass:[NSWindow class]] && window.contentView);
- struct yasl_event event;
- while (yasl_display_poll_event(d, &event)) {}
+ struct yasl_private_event event;
+ while (yasl_private_display_poll_event(d, &event)) {}
- assert(yasl_surface_set_size(s, (struct yasl_vector2i){180, 110}));
- assert(yasl_surface_set_fullscreen(s, false));
- assert(yasl_surface_set_maximized(s, false));
- assert(!yasl_surface_set_size(s, (struct yasl_vector2i){0, 100}));
+ struct yasl_private_window_spec gpu_spec = {
+ .flags = YASL_PRIVATE_SURFACE_HIDDEN | YASL_PRIVATE_SURFACE_UNDECORATED |
+ YASL_PRIVATE_SURFACE_FIXED_SIZE,
+ .external_gpu = true,
+ .title = "External GPU test",
+ .size = {160, 100},
+ };
+ struct yasl_surface *gpu = yasl_private_surface_create_toplevel(d, &gpu_spec);
+ assert(gpu && gpu->presenter == YASL_PRIVATE_PRESENTER_NONE);
+ CAMetalLayer *metal = (CAMetalLayer *)d->ops->surface_get_metal_layer(gpu);
+ assert(metal && [metal isKindOfClass:[CAMetalLayer class]] && !metal.device);
+ NSWindow *hidden = (NSWindow *)yasl_private_surface_get_native_handle(gpu);
+ assert(!hidden.isVisible && hidden.styleMask == NSWindowStyleMaskBorderless);
+ yasl_private_surface_destroy(gpu);
+
+ struct yasl_surface *gl = d->ops->surface_create_gl(d, &gpu_spec, NULL, NULL);
+ if (gl) {
+ assert(gl->presenter == YASL_PRIVATE_PRESENTER_GL);
+ assert(d->ops->gl_make_current(d, gl));
+ assert(d->ops->gl_get_proc_address(d, "glClear") != NULL);
+ assert(d->ops->gl_swap_interval(d, gl, 1));
+ assert(d->ops->gl_swap_buffers(d, gl));
+ assert(d->ops->gl_make_current(d, NULL));
+ d->ops->surface_destroy(gl);
+ }
+
+ assert(yasl_private_surface_set_size(s, (struct yasl_private_vector2i){180, 110}));
+ assert(yasl_private_surface_set_fullscreen(s, false));
+ assert(yasl_private_surface_set_maximized(s, false));
+ assert(!yasl_private_surface_set_size(s, (struct yasl_private_vector2i){0, 100}));
assert(errno == EINVAL);
- struct yasl_popup_spec popup_spec = {
+ struct yasl_private_popup_spec popup_spec = {
+ .positioner_explicit = true,
+ .anchor_edges = 4, .gravity = 3, .constraints = 63,
.size = {80, 40}, .anchor = {10, 10, 2, 2},
};
- struct yasl_surface *popup = yasl_surface_create_popup(s, &popup_spec);
+ struct yasl_surface *popup = yasl_private_surface_create_popup(s, &popup_spec);
assert(popup);
- assert(!yasl_surface_set_size(popup, (struct yasl_vector2i){80, 40}));
+ popup_spec.anchor_edges = 8;
+ popup_spec.gravity = 5;
+ assert(yasl_private_surface_popup_reposition(popup, &popup_spec));
+ assert(!yasl_private_surface_set_size(popup, (struct yasl_private_vector2i){80, 40}));
assert(errno == EINVAL);
- assert(!yasl_surface_set_fullscreen(popup, true) && errno == EINVAL);
- assert(!yasl_surface_set_maximized(popup, true) && errno == EINVAL);
- assert(!yasl_surface_minimize(popup) && errno == EINVAL);
- yasl_surface_destroy(popup);
- while (yasl_display_poll_event(d, &event)) {}
+ assert(!yasl_private_surface_set_fullscreen(popup, true) && errno == EINVAL);
+ assert(!yasl_private_surface_set_maximized(popup, true) && errno == EINVAL);
+ assert(!yasl_private_surface_minimize(popup) && errno == EINVAL);
+ yasl_private_surface_destroy(popup);
+ while (yasl_private_display_poll_event(d, &event)) {}
- id<NSTextInputClient> text_input = (id<NSTextInputClient>)yasl_cocoa_surface_get_view(s);
+ s->text_input_active = true;
+ s->text_surrounding = strdup("é漢");
+ s->text_length = strlen(s->text_surrounding);
+ s->text_begin = 0;
+ s->text_end = s->text_length;
+ assert(d->ops->surface_update_text_input(s));
+ id<NSTextInputClient> text_input = (id<NSTextInputClient>)yasl_private_cocoa_surface_get_view(s);
[text_input setMarkedText:@"é漢" selectedRange:NSMakeRange(1, 1)
replacementRange:NSMakeRange(NSNotFound, 0)];
- assert(strcmp(yasl_surface_ime_preedit(s), "é漢") == 0);
+ assert(strcmp(yasl_private_surface_ime_preedit(s), "é漢") == 0);
[text_input unmarkText];
- assert(yasl_surface_ime_preedit(s) == NULL);
- assert(yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_COMPOSITION && event.composition.active);
+ assert(yasl_private_surface_ime_preedit(s) == NULL);
+ assert(yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_COMPOSITION && event.composition.active);
assert(strcmp(event.composition.data, "é漢") == 0);
assert(event.composition.begin == 2 && event.composition.end == 5);
- assert(yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_COMPOSITION && !event.composition.active);
+ assert(yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_COMPOSITION && !event.composition.active);
assert(event.composition.begin == -1 && event.composition.end == -1);
- while (yasl_display_poll_event(d, &event)) {}
+ while (yasl_private_display_poll_event(d, &event)) {}
uint64_t request_ids[600];
@autoreleasepool {
for (int i = 0; i < 600; i++) {
char text[32];
snprintf(text, sizeof(text), "paste-%d", i);
- assert(yasl_clipboard_set(d, YASL_CLIPBOARD, text));
- request_ids[i] = yasl_clipboard_request(s, YASL_CLIPBOARD);
+ assert(yasl_private_clipboard_set(d, YASL_PRIVATE_CLIPBOARD, text));
+ request_ids[i] = yasl_private_clipboard_request(s, YASL_PRIVATE_CLIPBOARD);
assert(request_ids[i] != 0);
memset(text, 'x', sizeof(text));
}
@@ -71,32 +111,32 @@ int main(void)
for (int i = 0; i < 600; i++) {
char text[32];
snprintf(text, sizeof(text), "paste-%d", i);
- assert(yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == request_ids[i]);
- assert(event.paste.status == YASL_TRANSFER_OK && strcmp(event.paste.data, text) == 0);
+ assert(yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == request_ids[i]);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_OK && strcmp(event.paste.data, text) == 0);
}
const char *last = event.paste.data;
- assert(!yasl_display_poll_event(d, &event));
- @autoreleasepool { yasl_display_copy(d, YASL_CLIPBOARD, "new selection"); }
+ assert(!yasl_private_display_poll_event(d, &event));
+ @autoreleasepool { yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, "new selection"); }
assert(strcmp(last, "paste-599") == 0);
- assert(!yasl_clipboard_set(d, YASL_CLIPBOARD, "\xc3"));
+ assert(!yasl_private_clipboard_set(d, YASL_PRIVATE_CLIPBOARD, "\xc3"));
assert(errno == EILSEQ);
- assert(yasl_clipboard_set(d, YASL_CLIPBOARD, ""));
- uint64_t empty_id = yasl_clipboard_request(s, YASL_CLIPBOARD);
- assert(empty_id && yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == empty_id);
- assert(event.paste.status == YASL_TRANSFER_OK && !event.paste.len && !event.paste.data[0]);
+ assert(yasl_private_clipboard_set(d, YASL_PRIVATE_CLIPBOARD, ""));
+ uint64_t empty_id = yasl_private_clipboard_request(s, YASL_PRIVATE_CLIPBOARD);
+ assert(empty_id && yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == empty_id);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_OK && !event.paste.len && !event.paste.data[0]);
[NSPasteboard.generalPasteboard clearContents];
- uint64_t unavailable_id = yasl_clipboard_request(s, YASL_CLIPBOARD);
- assert(unavailable_id && yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == unavailable_id);
- assert(event.paste.status == YASL_TRANSFER_UNAVAILABLE && !event.paste.len);
- yasl_display_copy(d, YASL_CLIPBOARD, "legacy paste");
- yasl_display_paste(d, YASL_CLIPBOARD, s);
- assert(yasl_display_poll_event(d, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == 0);
- assert(event.paste.status == YASL_TRANSFER_OK && strcmp(event.text.data, "legacy paste") == 0);
- yasl_surface_destroy(s);
- yasl_display_close(d);
+ uint64_t unavailable_id = yasl_private_clipboard_request(s, YASL_PRIVATE_CLIPBOARD);
+ assert(unavailable_id && yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == unavailable_id);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_UNAVAILABLE && !event.paste.len);
+ yasl_private_display_copy(d, YASL_PRIVATE_CLIPBOARD, "legacy paste");
+ yasl_private_display_paste(d, YASL_PRIVATE_CLIPBOARD, s);
+ assert(yasl_private_display_poll_event(d, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == 0);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_OK && strcmp(event.text.data, "legacy paste") == 0);
+ yasl_private_surface_destroy(s);
+ yasl_private_display_close(d);
return 0;
}
diff --git a/tests/cocoa/test_tablet.m b/tests/cocoa/test_tablet.m
index 715a66e..8eb63d5 100644
--- a/tests/cocoa/test_tablet.m
+++ b/tests/cocoa/test_tablet.m
@@ -1,5 +1,5 @@
#import <AppKit/AppKit.h>
-#include <yasl/native.h>
+#include <common/private_native.h>
#include <assert.h>
/* A strict event double catches querying tablet-only properties on ordinary
@@ -15,6 +15,10 @@
@property NSPointingDeviceType tool;
@property float samplePressure;
@property NSPoint sampleTilt;
+@property double sampleRotation;
+@property double sampleTangential;
+@property NSInteger sampleDeviceID;
+@property NSInteger sampleToolID;
@end
@implementation TabletSample
@@ -33,70 +37,106 @@
assert(self.type == NSEventTypeTabletProximity || self.subtype == NSEventSubtypeTabletProximity);
return self.tool;
}
+- (double)rotation { return self.sampleRotation; }
+- (double)tangentialPressure { return self.sampleTangential; }
+- (NSInteger)pointingDeviceID { return self.sampleDeviceID; }
+- (NSInteger)pointingDeviceSerialNumber { return self.sampleToolID; }
@end
-static struct yasl_event next(struct yasl_surface *surface)
+static struct yasl_private_event next(struct yasl_surface *surface, enum yasl_private_event_type type)
{
- struct yasl_event event;
- while (yasl_surface_poll_event(surface, &event))
- return event;
- assert(!"Expected a pointer event");
- return (struct yasl_event){0};
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(surface, &event));
+ assert(event.type == type);
+ return event;
}
int main(void)
{
@autoreleasepool {
- struct yasl_display *display = yasl_display_open(NULL, NULL);
- assert(display && (yasl_display_caps(display) & YASL_CAP_TABLET));
- struct yasl_window_spec spec = {.title = "Tablet test", .size = {320, 240}};
- struct yasl_surface *surface = yasl_surface_create_toplevel(display, &spec);
+ struct yasl_private_display *display = yasl_private_display_open(NULL, NULL);
+ assert(display && (yasl_private_display_caps(display) & YASL_PRIVATE_CAP_TABLET));
+ struct yasl_private_window_spec spec = {.title = "Tablet test", .size = {320, 240}};
+ struct yasl_surface *surface = yasl_private_surface_create_toplevel(display, &spec);
assert(surface);
- NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(surface);
+ NSWindow *window = (NSWindow *)yasl_private_surface_get_native_handle(surface);
NSView *view = window.contentView;
- struct yasl_event event;
- while (yasl_surface_poll_event(surface, &event)) {}
+ struct yasl_private_event event;
+ while (yasl_private_surface_poll_event(surface, &event)) {}
TabletSample *sample = [TabletSample new];
NSEvent *native = (NSEvent *)sample;
sample.type = NSEventTypeTabletProximity;
sample.enteringProximity = YES;
sample.tool = NSPointingDeviceTypePen;
+ sample.sampleDeviceID = 17;
+ sample.sampleToolID = 29;
[view tabletProximity:native];
sample.type = NSEventTypeMouseMoved;
sample.subtype = NSEventSubtypeTabletPoint;
sample.locationInWindow = NSMakePoint(100, 120);
sample.sampleTilt = NSMakePoint(-0.5, 0.5);
+ sample.sampleRotation = 37.5;
+ sample.sampleTangential = -0.25;
[view mouseMoved:native];
- struct yasl_event ev = next(surface);
- assert(ev.pointer.device == YASL_PTR_DEV_PEN && ev.type == YASL_EVENT_POINTER_MOTION && !ev.pointer.pen.pressure);
+ struct yasl_private_event pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_ENTER && pen.pen.device_id == 17 && pen.pen.tool_id == 29);
+ struct yasl_private_event ev = next(surface, YASL_PRIVATE_EVENT_POINTER_MOTION);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN && ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && !ev.pointer.pen.pressure);
assert(ev.pointer.pen.tilt_x == -45 && ev.pointer.pen.tilt_y == -45);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_MOVE && pen.pen.device_id == 17 && pen.pen.tool_id == 29);
+ assert((pen.pen.axes_valid & (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT)) ==
+ (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT));
+ assert(pen.pen.rotation == 37.5 && pen.pen.tangential == -0.25);
+ assert((pen.pen.axes_valid & (YASL_PRIVATE_PEN_ROTATION | YASL_PRIVATE_PEN_TANGENTIAL)) ==
+ (YASL_PRIVATE_PEN_ROTATION | YASL_PRIVATE_PEN_TANGENTIAL));
sample.type = NSEventTypeLeftMouseDown;
sample.samplePressure = 0.5;
+ sample.buttonMask = NSEventButtonMaskPenTip;
[view mouseDown:native];
- ev = next(surface);
- assert(ev.pointer.device == YASL_PTR_DEV_PEN && ev.type == YASL_EVENT_POINTER_DOWN && ev.pointer.button == YASL_BUTTON_PRIMARY);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_DOWN);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN && ev.type == YASL_PRIVATE_EVENT_POINTER_DOWN && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY);
assert(ev.pointer.pen.pressure == 32767);
- struct yasl_vector2i position = ev.pointer.pos;
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_DOWN && pen.pen.in_contact && pen.pen.pressure == 0.5);
+ assert(pen.pen.buttons == YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY));
+ assert(pen.pen.changed_button == YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY));
+ struct yasl_private_vector2i position = ev.pointer.pos;
/* Native tablet events cover stationary pressure changes. */
sample.type = NSEventTypeTabletPoint;
sample.subtype = NSEventSubtypeMouseEvent;
sample.buttonMask = NSEventButtonMaskPenTip;
sample.samplePressure = 1.5;
[view tabletPoint:native];
- ev = next(surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_MOTION);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
assert(ev.pointer.pos.x == position.x && ev.pointer.pos.y == position.y);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_MOVE && pen.pen.pressure == 1.0);
+ sample.buttonMask |= NSEventButtonMaskPenLowerSide;
+ [view tabletPoint:native];
+ next(surface, YASL_PRIVATE_EVENT_POINTER_MOTION);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_BUTTON);
+ assert(pen.pen.buttons == (YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY) |
+ YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_SECONDARY)));
+ assert(pen.pen.changed_button == YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_SECONDARY));
+ sample.buttonMask = NSEventButtonMaskPenTip;
sample.samplePressure = 0; /* Zero does not release a held tip button. */
[view tabletPoint:native];
- assert(next(surface).type == YASL_EVENT_POINTER_MOTION);
+ assert(next(surface, YASL_PRIVATE_EVENT_POINTER_MOTION).type == YASL_PRIVATE_EVENT_POINTER_MOTION);
+ next(surface, YASL_PRIVATE_EVENT_PEN);
sample.buttonMask = 0;
[view tabletPoint:native];
- ev = next(surface);
- assert(ev.type == YASL_EVENT_POINTER_UP && !ev.pointer.pen.pressure && ev.pointer.device == YASL_PTR_DEV_PEN);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_UP);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_UP && !ev.pointer.pen.pressure && ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_UP && !pen.pen.in_contact && pen.pen.pressure == 0.0);
sample.type = NSEventTypeTabletProximity;
sample.enteringProximity = NO;
[view tabletProximity:native];
- assert(next(surface).type == YASL_EVENT_POINTER_LEAVE);
+ assert(next(surface, YASL_PRIVATE_EVENT_POINTER_LEAVE).type == YASL_PRIVATE_EVENT_POINTER_LEAVE);
+ assert(next(surface, YASL_PRIVATE_EVENT_PEN).pen.action == YASL_PRIVATE_PEN_LEAVE);
sample.enteringProximity = YES;
sample.tool = NSPointingDeviceTypeEraser;
[view tabletProximity:native];
@@ -104,20 +144,25 @@ int main(void)
sample.samplePressure = 0.75;
sample.buttonMask = NSEventButtonMaskPenTip;
[view tabletPoint:native];
- ev = next(surface);
- assert(ev.pointer.device == YASL_PTR_DEV_ERASER && ev.type == YASL_EVENT_POINTER_DOWN && ev.pointer.pen.pressure > 0);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_ENTER && pen.pen.tool == 2);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_DOWN);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && ev.type == YASL_PRIVATE_EVENT_POINTER_DOWN && ev.pointer.pen.pressure > 0);
+ pen = next(surface, YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_DOWN && pen.pen.tool == 2 && pen.pen.in_contact);
sample.type = NSEventTypeTabletProximity;
sample.enteringProximity = NO;
[view tabletProximity:native];
- ev = next(surface);
- assert(ev.pointer.device == YASL_PTR_DEV_ERASER && ev.type == YASL_EVENT_POINTER_LEAVE && !ev.pointer.pen.pressure);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_LEAVE);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && ev.type == YASL_PRIVATE_EVENT_POINTER_LEAVE && !ev.pointer.pen.pressure);
+ assert(next(surface, YASL_PRIVATE_EVENT_PEN).pen.action == YASL_PRIVATE_PEN_LEAVE);
sample.type = NSEventTypeMouseMoved;
[view mouseMoved:native];
- ev = next(surface);
- assert(ev.pointer.device == YASL_PTR_DEV_MOUSE && !ev.pointer.pen.pressure);
+ ev = next(surface, YASL_PRIVATE_EVENT_POINTER_MOTION);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE && !ev.pointer.pen.pressure);
[sample release];
- yasl_surface_destroy(surface);
- yasl_display_close(display);
+ yasl_private_surface_destroy(surface);
+ yasl_private_display_close(display);
}
return 0;
}
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);
+}
diff --git a/tests/helpers/run_surfaces.py b/tests/helpers/run_surfaces.py
new file mode 100644
index 0000000..f120e35
--- /dev/null
+++ b/tests/helpers/run_surfaces.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+"""Run the public surface/GPU contract tests on private Weston and Xwayland."""
+import os
+from pathlib import Path
+import subprocess
+import sys
+import tempfile
+import time
+
+def wait_for(process, ready):
+ deadline = time.monotonic() + 12
+ while time.monotonic() < deadline:
+ if process.poll() is not None:
+ raise RuntimeError('Display server stopped before readiness')
+ if ready():
+ return
+ time.sleep(0.02)
+ raise TimeoutError('Display server readiness')
+
+def main():
+ weston, xwayland, contract, hello, tablet, gl, vulkan, notepad = sys.argv[1:]
+ servers = []
+ with tempfile.TemporaryDirectory(prefix='yasl-surfaces-') as directory:
+ root = Path(directory)
+ env = os.environ.copy()
+ env.pop('WAYLAND_SOCKET', None)
+ env.update(XDG_RUNTIME_DIR=directory, WAYLAND_DISPLAY='yasl-test',
+ XDG_SESSION_TYPE='wayland', LIBGL_ALWAYS_SOFTWARE='1')
+ lavapipe = next(Path('/usr/share/vulkan/icd.d').glob('*lvp*.json'), None)
+ if lavapipe:
+ env['VK_DRIVER_FILES'] = str(lavapipe)
+ with (root/'weston.log').open('w+') as wl_log, (root/'xwayland.log').open('w+') as x_log:
+ try:
+ wl = subprocess.Popen([weston, '--backend=headless', '--renderer=gl',
+ '--socket=yasl-test', '--idle-time=0', '--no-config',
+ '--width=1024', '--height=768'], env=env, stdout=wl_log, stderr=wl_log)
+ servers.append(wl)
+ wait_for(wl, lambda: (root/'yasl-test').is_socket())
+ display_file = root/'display'
+ with display_file.open('w') as fd:
+ x = subprocess.Popen([xwayland, '-displayfd', str(fd.fileno()),
+ '-shm', '-noreset', '-nolisten', 'tcp'], env=env,
+ pass_fds=(fd.fileno(),), stdout=x_log, stderr=x_log)
+ servers.append(x)
+ wait_for(x, lambda: bool(display_file.read_text().strip()))
+ env['DISPLAY'] = ':' + display_file.read_text().strip()
+ for backend in ('wayland', 'x11'):
+ case = env.copy()
+ if backend == 'x11':
+ case.pop('WAYLAND_DISPLAY', None)
+ case['XDG_SESSION_TYPE'] = 'x11'
+ for binary, args in ((contract,[backend]), (gl,[backend]),
+ (vulkan,[backend]), (tablet,['--backend',backend,'--smoke-test']),
+ (notepad,['--smoke-test'])):
+ if binary == '-':
+ continue
+ print('Testing', Path(binary).name, backend, flush=True)
+ subprocess.run([binary, *args], env=case, check=True, timeout=15)
+ # hello runs until closed: it must survive its first frames.
+ if hello == '-':
+ continue
+ print('Testing', Path(hello).name, backend, flush=True)
+ process = subprocess.Popen([hello], env=case)
+ try:
+ process.wait(timeout=1)
+ raise RuntimeError(f'{Path(hello).name} exited with {process.returncode}')
+ except subprocess.TimeoutExpired:
+ process.terminate()
+ process.wait()
+ except BaseException:
+ for log in (wl_log,x_log):
+ log.flush();log.seek(0);print(log.read(), file=sys.stderr)
+ raise
+ finally:
+ for server in reversed(servers):
+ server.terminate()
+ try:
+ server.wait(timeout=5)
+ except subprocess.TimeoutExpired:
+ server.kill();server.wait()
+if __name__ == '__main__':
+ main()
diff --git a/tests/meson.build b/tests/meson.build
index cac62db..4cbf082 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,291 +1,105 @@
-test_exe = executable(
- 'yasl-test',
- 'test_lifecycle.c',
- include_directories: inc,
- link_with: yasl_lib.get_static_lib(),
- dependencies: deps,
-)
-
-add_test_setup('asan')
-add_test_setup('tsan')
-add_test_setup('msan')
-
-test('basic', test_exe)
-
-shared_dep = declare_dependency(
- link_with: yasl_lib.get_shared_lib(),
- include_directories: include_directories('../include'),
-)
-
-shared_api_test = executable(
- 'yasl-shared-api-test',
- 'test_lifecycle.c',
- dependencies: shared_dep,
-)
-test('shared-api', shared_api_test)
-
+python = find_program('python3', native: true)
+shared_dep = declare_dependency(link_with: yasl_lib.get_shared_lib(),
+ include_directories: include_directories('../include'))
+foreach kind : ['static', 'shared']
+ dep = kind == 'static' ? yasl_dep : shared_dep
+ public_test = executable('yasl-' + kind + '-api-test', 'test_lifecycle.c', dependencies: dep)
+ test(kind + '-api', public_test)
+endforeach
if add_languages('cpp', native: false, required: false)
- cpp = meson.get_compiler('cpp')
- cpp_api_test = executable(
- 'yasl-cpp-api-test',
- 'test_api.cpp',
- dependencies: shared_dep,
- cpp_args: cpp.get_supported_arguments('-pedantic-errors') + [
- '-DYASL_HAS_WAYLAND=' + (has_wayland ? '1' : '0'),
- '-DYASL_HAS_X11=' + (has_x11 ? '1' : '0'),
- '-DYASL_HAS_COCOA=' + (has_cocoa ? '1' : '0'),
- ],
- override_options: ['cpp_std=c++11'],
- )
- test('cpp-api', cpp_api_test)
+ cpp_api = executable('yasl-cpp-api-test', 'test_api.cpp', dependencies: shared_dep,
+ cpp_args: ['-pedantic-errors'], override_options: ['cpp_std=c++11'])
+ test('cpp-api', cpp_api)
endif
-
-python = find_program('python3', native: true)
-if system == 'linux' or system == 'darwin'
- nm = find_program('nm', native: false)
- export_args = ['--platform=' + system]
- if get_option('b_sanitize').contains('address')
- # Clang's ASan instrumentation exports these linker-generated markers.
- export_args += ['--allow-export=__start_asan_globals',
- '--allow-export=__stop_asan_globals']
- endif
- exported_headers = files(
- '../include/yasl/yasl.h',
- '../include/yasl/app.h',
- '../include/yasl/desktop.h',
- '../include/yasl/timing.h',
- '../include/yasl/loop.h',
- '../include/yasl/native.h',
- )
- if has_wayland
- exported_headers += files('../include/yasl/native/wayland.h')
- endif
- if has_x11
- exported_headers += files('../include/yasl/native/x11.h')
- endif
- if has_cocoa
- exported_headers += files('../include/yasl/native/cocoa.h')
+headers = files('../include/yasl/yasl.h', '../include/yasl/cpu.h', '../include/yasl/gl.h',
+ '../include/yasl/metal.h', '../include/yasl/desktop.h')
+if has_vulkan
+ headers += files('../include/yasl/vulkan.h')
+endif
+foreach backend : ['wayland', 'x11', 'cocoa']
+ enabled = {'wayland': has_wayland, 'x11': has_x11, 'cocoa': has_cocoa}[backend]
+ if enabled
+ headers += files('../include/yasl/native/' + backend + '.h')
endif
- test('public-exports', python,
- args: [files('helpers/check_exports.py')] + export_args +
- [nm, yasl_lib.get_shared_lib(), exported_headers],
- )
+endforeach
+nm = find_program('nm')
+export_args = ['--platform=' + system]
+if get_option('b_sanitize').contains('address')
+ export_args += ['--allow-export=__start_asan_globals', '--allow-export=__stop_asan_globals']
endif
-
-contracts_test = executable(
- 'yasl-contracts-test',
- 'common/test_contracts.c',
- include_directories: inc,
- dependencies: yasl_dep,
-)
-test('contracts', contracts_test)
-
-# Exercise the SDK-independent mappings even when their backend is disabled.
-# Enabled backends already provide their mapping through yasl_dep.
-keyboard_test_sources = files('common/test_keyboard.c')
+test('public-exports', python, args: [files('helpers/check_exports.py')] + export_args +
+ [nm, yasl_lib.get_shared_lib(), headers])
+
+foreach unit : ['contracts', 'utf8', 'timers', 'loop', 'selection', 'events', 'gl_options']
+ exe = executable('yasl-' + unit + '-test', 'common/test_' + unit + '.c',
+ include_directories: inc, dependencies: yasl_dep)
+ test(unit, exe)
+endforeach
+keyboard_sources = files('common/test_keyboard.c')
if not has_wayland
- keyboard_test_sources += files('../src/platform/wayland/keymap.c')
+ keyboard_sources += files('../src/platform/wayland/keymap.c')
endif
if not has_x11
- keyboard_test_sources += files('../src/platform/x11/keymap.c')
+ keyboard_sources += files('../src/platform/x11/keymap.c')
endif
if not has_cocoa
- keyboard_test_sources += files('../src/platform/cocoa/keymap.c')
+ keyboard_sources += files('../src/platform/cocoa/keymap.c')
endif
-keyboard_test = executable('yasl-keyboard-test', keyboard_test_sources,
- include_directories: inc, dependencies: yasl_dep,
-)
-test('keyboard', keyboard_test)
-
-utf8_test = executable('yasl-utf8-test', 'common/test_utf8.c',
- include_directories: inc, dependencies: yasl_dep,
-)
-test('utf8', utf8_test)
-
-timer_test = executable(
- 'yasl-timer-test',
- 'common/test_timers.c',
- include_directories: inc,
- dependencies: yasl_dep,
-)
-test('timers', timer_test)
-
-loop_test = executable(
- 'yasl-loop-test',
- 'common/test_loop.c',
- include_directories: inc,
- dependencies: [yasl_dep, dependency('threads')],
-)
-test('loop', loop_test)
-
+keyboard = executable('yasl-keyboard-test', keyboard_sources, include_directories: inc, dependencies: yasl_dep)
+test('keyboard', keyboard)
+alloc = executable('yasl-input-alloc-test', ['common/test_input_alloc.c', '../src/common/input.c'],
+ include_directories: inc, c_args: ['-Dmalloc=yasl_private_test_malloc'])
+test('input-allocation-failure', alloc)
if system == 'linux'
- desktop_test = executable(
- 'yasl-desktop-test',
- 'common/test_desktop.c',
- include_directories: inc,
- dependencies: [yasl_dep, dependency('threads')],
- )
- # A private session bus keeps the notification and portal checks away
- # from the user's desktop.
- dbus_run_session = find_program('dbus-run-session', required: false)
- if has_dbus and dbus_run_session.found()
- test('desktop', dbus_run_session, args: ['--', desktop_test])
+ desktop = executable('yasl-desktop-test', 'common/test_desktop.c', include_directories: inc, dependencies: yasl_dep)
+ dbus_run = find_program('dbus-run-session', required: false)
+ if has_dbus and dbus_run.found()
+ test('desktop', dbus_run, args: ['--', desktop])
else
- test('desktop', desktop_test)
+ test('desktop', desktop)
endif
endif
-
-app_test = executable(
- 'yasl-app-test',
- 'common/test_app.c',
- include_directories: inc,
- dependencies: yasl_dep,
-)
-test('app-runner', app_test)
-
-input_alloc_test = executable(
- 'yasl-input-alloc-test',
- ['common/test_input_alloc.c', '../src/common/input.c'],
- include_directories: inc,
- c_args: ['-Dmalloc=yasl_test_malloc'],
-)
-test('input-allocation-failure', input_alloc_test)
-
-selection_test = executable(
- 'yasl-selection-test',
- 'common/test_selection.c',
- dependencies: yasl_dep,
-)
-test('selection', selection_test)
-
-tablet_example_test = executable('yasl-tablet-example-test', 'common/test_tablet_example.c',
- dependencies: yasl_dep,
-)
-test('tablet-example', tablet_example_test)
-
+if has_wayland
+ foreach unit : ['state', 'clipboard', 'keyboard', 'input', 'tablet', 'cursor', 'relative_pointer', 'app_input', 'popup_positioner']
+ exe = executable('yasl-' + unit + '-wayland-test', 'wayland/test_' + unit + '.c',
+ include_directories: inc, dependencies: yasl_dep)
+ test(unit + '-wayland', exe)
+ endforeach
+endif
if has_x11
- state_x11_test = executable('yasl-state-x11-test', 'x11/test_state.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('state-x11', state_x11_test)
- tablet_x11_test = executable('yasl-tablet-x11-test', 'x11/test_tablet.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('tablet-x11', tablet_x11_test)
+ foreach unit : ['state', 'tablet']
+ exe = executable('yasl-' + unit + '-x11-test', 'x11/test_' + unit + '.c',
+ include_directories: inc, dependencies: yasl_dep)
+ test(unit + '-x11', exe)
+ endforeach
if get_option('x11_tablet_tests')
xorg = find_program('/usr/lib/Xorg', '/usr/lib/xorg/Xorg', 'Xorg')
- native_tablet_test = executable('yasl-tablet-x11-native-test', 'x11/test_tablet_native.c',
- dependencies: yasl_dep,
- )
- test('tablet-x11-native', python,
- args: [files('helpers/run_x11_tablet.py'), xorg, native_tablet_test], timeout: 30,
- )
+ native_tablet = executable('yasl-tablet-x11-native-test', 'x11/test_tablet_native.c',
+ include_directories: inc, dependencies: yasl_dep)
+ test('tablet-x11-native', python, args: [files('helpers/run_x11_tablet.py'), xorg, native_tablet], timeout: 30)
endif
-elif get_option('x11_tablet_tests')
- error('Native X11 tablet tests require the X11 backend.')
endif
-
-if has_wayland
- state_wayland_test = executable('yasl-state-wayland-test', 'wayland/test_state.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('state-wayland', state_wayland_test)
- clipboard_wayland_test = executable('yasl-clipboard-wayland-test', 'wayland/test_clipboard.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('clipboard-wayland', clipboard_wayland_test)
- keyboard_wayland_test = executable('yasl-keyboard-wayland-test', 'wayland/test_keyboard.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('keyboard-wayland', keyboard_wayland_test)
- ime_test = executable('yasl-ime-test', 'wayland/test_input.c',
- include_directories: inc,
- dependencies: yasl_dep,
- )
- test('ime-ownership', ime_test)
- app_input_test = executable('yasl-app-input-test', 'wayland/test_app_input.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('app-input-destroy', app_input_test)
- tablet_wayland_test = executable('yasl-tablet-wayland-test', 'wayland/test_tablet.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('tablet-wayland', tablet_wayland_test)
- cursor_wayland_test = executable('yasl-cursor-wayland-test', 'wayland/test_cursor.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('cursor-wayland', cursor_wayland_test)
- relative_pointer_test = executable('yasl-relative-pointer-wayland-test',
- 'wayland/test_relative_pointer.c',
- include_directories: inc, dependencies: yasl_dep,
- )
- test('relative-pointer-wayland', relative_pointer_test)
-endif
-
-benchmark_exe = executable(
- 'yasl-benchmark',
- 'benchmark.c',
- include_directories: inc,
- dependencies: yasl_dep,
-)
-benchmark('performance', benchmark_exe)
-
if get_option('integration_tests')
- hello_example_test = executable('yasl-hello-example-test', 'common/test_hello_example.c',
- dependencies: shared_dep,
- )
- if has_cocoa
- test('hello-cocoa-window', hello_example_test, timeout: 20)
- test('interactive-cocoa-window', interactive_example,
- args: ['--smoke-test'], timeout: 20,
- )
- native_test = executable('yasl-native-test', 'cocoa/test_native.c',
- dependencies: shared_dep,
- )
- test('native', native_test, timeout: 20)
- ownership_test = executable('yasl-ownership-test', 'cocoa/test_ownership.m',
- dependencies: [shared_dep, deps],
- )
- test('native-ownership', ownership_test, timeout: 20)
- keyboard_cocoa_test = executable('yasl-keyboard-cocoa-test', 'cocoa/test_keyboard.m',
- dependencies: [shared_dep, deps],
- )
- test('keyboard-cocoa', keyboard_cocoa_test, timeout: 20)
- tablet_cocoa_test = executable('yasl-tablet-cocoa-test', 'cocoa/test_tablet.m',
- dependencies: [shared_dep, deps],
- )
- test('tablet-cocoa', tablet_cocoa_test, timeout: 20)
- cursor_cocoa_test = executable('yasl-cursor-cocoa-test', 'cocoa/test_cursor.m',
- dependencies: [shared_dep, deps],
- )
- test('cursor-cocoa', cursor_cocoa_test, timeout: 20)
- test('tablet-cocoa-window', tablet_example,
- args: ['--backend', 'cocoa', '--smoke-test'], timeout: 20,
- )
- else
- if not has_wayland or not has_x11
- error('Linux integration tests require Wayland and X11.')
- endif
- backend_test = executable(
- 'yasl-backend-test',
- 'common/test_backends.c',
- dependencies: [shared_dep, deps],
- )
- input_x11_test = executable('yasl-input-x11-test', 'x11/test_input.c',
- include_directories: inc, dependencies: yasl_dep,
- )
+ integration = executable('yasl-surface-integration', 'common/test_surface_integration.c',
+ include_directories: inc, dependencies: yasl_dep)
+ gl_integration = executable('yasl-gl-integration', 'common/test_gl.c',
+ dependencies: yasl_dep)
+ vulkan_integration = '-'
+ if has_vulkan
+ vulkan_integration = executable('yasl-vulkan-integration', 'common/test_vulkan.c', dependencies: yasl_dep)
+ endif
+ if system == 'linux'
weston = find_program('weston')
xwayland = find_program('Xwayland')
- test('backends', python,
- args: [files('helpers/run_backends.py'), weston, xwayland,
- backend_test, timer_test, tablet_example, hello_example_test, input_x11_test,
- interactive_example, app_test, app_input_test],
- timeout: 60,
- )
+ test('surface-backends', python, args: [files('helpers/run_surfaces.py'), weston, xwayland,
+ integration, hello_example, tablet_example, gl_integration, vulkan_integration, notepad_example], timeout: 120)
+ elif has_cocoa
+ test('surface-cocoa', integration, args: ['cocoa'], timeout: 30)
+ foreach unit : ['native', 'ownership', 'keyboard', 'tablet', 'cursor']
+ extension = unit == 'native' ? '.c' : '.m'
+ exe = executable('yasl-' + unit + '-cocoa-test', 'cocoa/test_' + unit + extension,
+ include_directories: inc, dependencies: yasl_dep)
+ test(unit + '-cocoa', exe, timeout: 30)
+ endforeach
endif
endif
-
-events_test = executable('yasl-events-test', 'common/test_events.c',
- include_directories: inc, dependencies: [yasl_dep, dependency('threads')],
-)
-test('event-contracts', events_test)
diff --git a/tests/test_api.cpp b/tests/test_api.cpp
index c5859cd..c0693eb 100644
--- a/tests/test_api.cpp
+++ b/tests/test_api.cpp
@@ -1,89 +1,26 @@
-#include "yasl/native.h"
-#include "yasl/app.h"
+#include <yasl/yasl.h>
+#include <yasl/cpu.h>
+#include <yasl/gl.h>
+#include <yasl/metal.h>
+#include <yasl/desktop.h>
+#if YASL_HAS_VULKAN
+#include <yasl/vulkan.h>
+#endif
#if YASL_HAS_WAYLAND
-#include "yasl/native/wayland.h"
+#include <yasl/native/wayland.h>
#endif
#if YASL_HAS_X11
-#include "yasl/native/x11.h"
+#include <yasl/native/x11.h>
#endif
#if YASL_HAS_COCOA
-#include "yasl/native/cocoa.h"
+#include <yasl/native/cocoa.h>
#endif
-#include "yasl/desktop.h"
-#include "yasl/loop.h"
-#include <yasl/timing.h>
-#include <yasl/yasl.h>
#include <cassert>
-
int main()
{
- yasl_window_cbs callbacks{};
- yasl_window_spec window{};
- window.size = {640, 480};
- window.cbs = &callbacks;
- window.ud = &window;
- assert(!yasl_surface_create_toplevel(nullptr, &window));
- assert(!yasl_surface_create_native(nullptr, &window, &window));
-
- yasl_timing timing = yasl_surface_timing(nullptr);
- assert(timing.source == YASL_TIMING_UNKNOWN);
- assert(yasl_scale_to_device(10.0, 240) == 20);
- yasl_geometry geometry = yasl_surface_geometry(nullptr);
- assert(geometry.scale_120 == YASL_SCALE_UNIT);
- assert(!yasl_display_get_native_handle(nullptr));
- assert(!yasl_surface_get_native_handle(nullptr));
- yasl_native_frame native{};
- assert(!yasl_surface_get_native_frame(nullptr, nullptr, &native));
-
- yasl_loop *loop = yasl_loop_create();
- assert(loop);
- assert(yasl_loop_step(loop, 0) >= 0);
- yasl_loop_destroy(loop);
-
- yasl_message message{};
- assert(!yasl_display_post(nullptr, &message));
- assert(!yasl_frame_present(nullptr, nullptr, 0));
- assert(!yasl_display_poll_event(nullptr, nullptr));
- assert(!yasl_surface_set_size(nullptr, {640, 480}));
- assert(!yasl_surface_set_fullscreen(nullptr, true));
- assert(!yasl_surface_set_maximized(nullptr, true));
- assert(!yasl_surface_minimize(nullptr));
- assert(!yasl_surface_set_pacing(nullptr, YASL_PACING_CONTINUOUS));
- assert(!yasl_surface_set_callbacks(nullptr, nullptr, nullptr));
- assert(!yasl_clipboard_set(nullptr, YASL_CLIPBOARD, ""));
- assert(!yasl_clipboard_request(nullptr, YASL_CLIPBOARD));
- assert(!yasl_app_window(nullptr));
- yasl_app_exit(nullptr, YASL_APP_ERROR);
-
- yasl_event event{};
- event.key.key = YASL_KEY_A;
- assert(event.key.key == YASL_KEY_A);
- event.pointer.scroll = {0.25, -0.5};
- assert(event.pointer.scroll.x == 0.25 && event.pointer.scroll.y == -0.5);
- assert(!yasl_surface_poll_event(nullptr, &event));
- assert(!yasl_display_drag_start(nullptr, nullptr, nullptr, nullptr, nullptr));
- assert(!yasl_surface_drag_carry(nullptr, {0, 0}));
-
-#if YASL_HAS_WAYLAND
- assert(!yasl_wayland_display_get_wl_display(nullptr));
- assert(!yasl_wayland_surface_get_wl_surface(nullptr));
-#endif
-
-#if YASL_HAS_X11
- assert(!yasl_x11_display_get_display(nullptr));
- assert(!yasl_x11_surface_get_window(nullptr));
-#endif
-
-#if YASL_HAS_COCOA
- assert(!yasl_cocoa_display_get_application(nullptr));
- assert(!yasl_cocoa_surface_get_window(nullptr));
- assert(!yasl_cocoa_surface_get_view(nullptr));
-#endif
-
- assert(!yasl_display_open_uri(nullptr, "https://example.com"));
- assert(yasl_display_appearance(nullptr) == 0);
- assert(!yasl_surface_bell(nullptr));
- assert(yasl_executable_path(nullptr, 0) > 0);
-
- return 0;
+ yasl_event e{};
+ e.pen.x=1.5;e.pen.pressure=0.25;
+ assert(e.pen.pressure==0.25);
+ assert(!yasl_surface_create("invalid",-1,10,0));
+ yasl_shutdown();return 0;
}
diff --git a/tests/test_lifecycle.c b/tests/test_lifecycle.c
index 00d1264..a334fed 100644
--- a/tests/test_lifecycle.c
+++ b/tests/test_lifecycle.c
@@ -1,75 +1,24 @@
-#include "yasl/loop.h"
-#include "yasl/yasl.h"
+#include <yasl/yasl.h>
+#include <yasl/cpu.h>
+#include <yasl/gl.h>
+#include <yasl/desktop.h>
#include <assert.h>
-#include <poll.h>
-#include <stdio.h>
-#include <unistd.h>
-
-static void test_scaling(void)
-{
- assert(yasl_scale_to_device(10.0, 120) == 10);
- assert(yasl_scale_to_device(10.0, 240) == 20);
- assert(yasl_scale_to_logical(20, 240) == 10);
-}
-
-static int dummy_cb(int fd, short revents, void *ud)
-{
- (void)fd; (void)revents; (void)ud;
- return 0;
-}
-
-static void test_loop(void)
-{
- struct yasl_loop *loop = yasl_loop_create();
- assert(loop != NULL);
-
- int p[2];
- assert(pipe(p) == 0);
- int watch = yasl_loop_add_fd(loop, p[0], POLLIN, dummy_cb, NULL);
- assert(watch > 0);
- assert(yasl_loop_set_fd_events(loop, watch, POLLIN | POLLOUT) == 0);
-
- yasl_loop_kick(loop);
- int n = yasl_loop_step(loop, 10);
- assert(n >= 1);
-
- assert(yasl_loop_del_fd(loop, watch) == 0);
- close(p[0]);
- close(p[1]);
-
- yasl_loop_destroy(loop);
-}
-
-static void test_display_lifecycle_standalone(void)
-{
- struct yasl_display_spec spec = { .app_id = "org.yasl.test" };
- struct yasl_display *d = yasl_display_open(NULL, &spec);
- if (!d) return; /* Headless CI without Wayland */
-
- struct yasl_window_spec sspec = {
- .title = "Test Window",
- .size = { .x = 320, .y = 240 },
- };
- struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec);
- assert(s != NULL);
- assert(yasl_surface_display(s) == d);
-
- struct yasl_vector2i sz = yasl_surface_geometry(s).size;
- assert(sz.x > 0 && sz.y > 0);
-
- yasl_surface_schedule_redraw(s);
- yasl_display_flush(d);
- yasl_display_dispatch(d, 0);
-
- yasl_surface_destroy(s);
- yasl_display_close(d);
-}
-
int main(void)
{
- test_scaling();
- test_loop();
- test_display_lifecycle_standalone();
- printf("All YASL basic tests passed.\n");
- return 0;
+ yasl_shutdown(); yasl_wake();
+ yasl_event e={.type=YASL_EVENT_QUIT};
+ assert(yasl_wait_event(&e,0)==-1 && e.type==YASL_EVENT_NONE);
+ assert(yasl_get_error(NULL)==YASL_ERROR_NOT_INITIALIZED);
+ assert(!yasl_set_backend((enum yasl_backend)999));
+ assert(yasl_get_error(NULL)==YASL_ERROR_INVALID);
+ assert(!yasl_surface_create("bad",0,64,0));
+ assert(!yasl_surface_create("bad",64,64,16));
+ assert(yasl_set_app_id("org.yasl.api"));
+ assert(yasl_set_backend(YASL_BACKEND_AUTO));
+ yasl_surface_destroy(NULL);
+ assert(yasl_time_ns()>0);
+ const char *description=NULL;yasl_get_error(&description);assert(description);
+ int w=9,h=9;yasl_surface_get_size(NULL,&w,&h);assert(w==0&&h==0);
+ assert(yasl_executable_path(NULL,0)>0);
+ yasl_shutdown();return 0;
}
diff --git a/tests/wayland/test_app_input.c b/tests/wayland/test_app_input.c
index 7e0e9a0..c8e4d2b 100644
--- a/tests/wayland/test_app_input.c
+++ b/tests/wayland/test_app_input.c
@@ -1,132 +1,78 @@
-/* An input event callback that destroys its own surface. The app runner
- * must not touch the surface's entry after the callback, and must not
- * deliver the surface's remaining input. Needs a Wayland compositor. */
-#include "platform/wayland/internal.h"
-#include "yasl/app.h"
+/* The public event queue must retain FIFO order and discard events targeted
+ * at a surface when that surface is destroyed. Native input is injected
+ * through the backend queue, without requiring a compositor. */
+#include "yasl/yasl.h"
+#include "common/backend.h"
#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
+#include <string.h>
-struct test_state {
- bool initialized;
- int keys;
- int buttons, motions, resets;
- int end;
+static struct input_queue *surface_queue(struct yasl_surface *s)
+{
+ return &s->input;
+}
+
+static const struct yasl_private_backend_ops test_ops = {
+ .surface_input_queue = surface_queue,
};
-static void push_key(struct yasl_surface *s)
+static void setup(struct yasl_private_display *display, struct yasl_surface *surface)
{
- struct yasl_event ev = {
- .surface = s,
- .type = YASL_EVENT_KEY,
- .key = { .key = YASL_KEY_A, .action = YASL_KEY_PRESS },
- };
- assert(input_queue_push(&((struct wayland_surface *)s)->input, &ev));
+ *display = (struct yasl_private_display){.ops = &test_ops};
+ *surface = (struct yasl_surface){.display = display, .scale_120 = 120};
+ assert(yasl_private_events_open(display));
+ assert(yasl_private_events_register(surface));
}
-static enum yasl_app_result on_init(void *ud, struct yasl_display *d)
+static void destroy_surface(struct yasl_surface *surface)
{
- struct test_state *state = ud;
- state->initialized = true;
- if (state->end == 3) {
- /* With no event callback, a close request alone stops the runner. */
- struct yasl_surface *s = yasl_surface_create_toplevel(d,
- &(struct yasl_window_spec){ .title = "App Close Test", .size = {64, 64} });
- assert(s);
- yasl_surface_notify_close(s);
- return YASL_APP_CONTINUE;
- }
- if (state->end) {
- if (state->end == 1)
- yasl_display_notify_event(d, YASL_EVENT_DISPLAY_QUIT);
- else
- yasl_display_notify_event(d, YASL_EVENT_DISPLAY_LOST);
- return YASL_APP_CONTINUE;
- }
- struct yasl_surface *s = yasl_surface_create_toplevel(d,
- &(struct yasl_window_spec){ .title = "App Input Test", .size = {64, 64} });
- assert(s);
- struct input_queue *queue = &((struct wayland_surface *)s)->input;
- input_queue_clear(queue);
- struct yasl_event event = {.surface = s, .type = YASL_EVENT_POINTER_DOWN,
- .pointer = {.device = YASL_PTR_DEV_ERASER, .button = YASL_BUTTON_PRIMARY,
- .pos = {12, 34}, .pen = {.pressure = 50000, .tilt_x = -20, .tilt_y = 30}}};
- assert(input_queue_push(queue, &event));
- event.type = YASL_EVENT_POINTER_MOTION;
- event.pointer.pos = (struct yasl_vector2i){15, 39};
- assert(input_queue_push(queue, &event));
- struct yasl_event reset = {.surface = s, .type = YASL_EVENT_INPUT_RESET};
- assert(input_queue_push(queue, &reset));
- event.pointer.device = YASL_PTR_DEV_PEN;
- event.pointer.pos = (struct yasl_vector2i){100, 200};
- assert(input_queue_push(queue, &event));
- push_key(s);
- push_key(s);
- return YASL_APP_CONTINUE;
+ yasl_private_events_unregister(surface);
+ input_queue_clear(&surface->input);
}
-static enum yasl_app_result on_event(void *ud, const struct yasl_event *ev)
+static void test_fifo_and_destroy(void)
{
- struct test_state *state = ud;
- if (ev->type == YASL_EVENT_POINTER_DOWN) {
- assert(ev->pointer.device == YASL_PTR_DEV_ERASER);
- assert(ev->pointer.button == YASL_BUTTON_PRIMARY);
- assert(ev->pointer.pos.x == 12 && ev->pointer.pos.y == 34);
- assert(ev->pointer.pen.pressure == 50000);
- assert(ev->pointer.pen.tilt_x == -20 && ev->pointer.pen.tilt_y == 30);
- state->buttons++;
- } else if (ev->type == YASL_EVENT_POINTER_MOTION) {
- if (!state->motions) {
- assert(ev->pointer.device == YASL_PTR_DEV_ERASER);
- assert(ev->pointer.delta.x == 3 && ev->pointer.delta.y == 5);
- } else {
- assert(ev->pointer.device == YASL_PTR_DEV_PEN);
- assert(!ev->pointer.delta.x && !ev->pointer.delta.y);
- }
- assert(ev->pointer.pen.pressure == 50000);
- state->motions++;
- } else if (ev->type == YASL_EVENT_INPUT_RESET) {
- state->resets++;
- } else if (ev->type == YASL_EVENT_KEY) {
- state->keys++;
- yasl_surface_destroy(ev->surface);
- }
- return YASL_APP_CONTINUE;
+ struct yasl_private_display display;
+ struct yasl_surface surface;
+ setup(&display, &surface);
+
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_KEY,
+ .surface = &surface,
+ .key = {.key = YASL_KEY_A, .action = YASL_KEY_PRESS},
+ }));
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT,
+ .surface = &surface,
+ .text = {.data = "hello", .len = 5},
+ }));
+
+ struct yasl_private_event event;
+ assert(yasl_private_display_poll_event(&display, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_KEY && event.key.key == YASL_KEY_A);
+ assert(yasl_private_display_poll_event(&display, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_TEXT && event.text.len == 5);
+ assert(!strcmp(event.text.data, "hello"));
+
+ /* Queue multiple events, then destroy the target before consumption. */
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_KEY, .surface = &surface,
+ .key = {.key = YASL_KEY_B, .action = YASL_KEY_PRESS},
+ }));
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT, .surface = &surface,
+ .text = {.data = "discard", .len = 7},
+ }));
+ destroy_surface(&surface);
+ assert(!yasl_private_display_poll_event(&display, &event));
+ yasl_private_events_close(&display);
+
+ /* Public event names remain the event stream consumed by applications. */
+ assert(YASL_EVENT_KEY != YASL_EVENT_TEXT);
}
int main(void)
{
- if (!getenv("WAYLAND_DISPLAY"))
- return 77;
- struct test_state state = {0};
- int res = yasl_run(&(struct yasl_app_desc){
- .app_id = "org.yasl.test.app-input",
- .backend = YASL_BACKEND_WAYLAND,
- .userdata = &state,
- .init = on_init,
- .event = on_event,
- });
- /* A display variable may exist even when the test sandbox cannot connect
- * to that compositor. Keep this as an integration test in that case. */
- if (res < 0 && !state.initialized &&
- (errno == EACCES || errno == EPERM || errno == ENOENT ||
- errno == ECONNREFUSED || errno == ENODEV))
- return 77;
- assert(res == 0);
- assert(state.keys == 1);
- assert(state.buttons == 1 && state.motions == 2 && state.resets == 1);
- for (int end = 1; end <= 2; end++) {
- state = (struct test_state){.end = end};
- res = yasl_run(&(struct yasl_app_desc){
- .backend = YASL_BACKEND_WAYLAND, .userdata = &state, .init = on_init,
- });
- assert(end == 1 ? res == 0 : res < 0);
- }
- state = (struct test_state){.end = 3};
- res = yasl_run(&(struct yasl_app_desc){
- .backend = YASL_BACKEND_WAYLAND, .userdata = &state, .init = on_init,
- });
- assert(res == 0);
+ test_fifo_and_destroy();
return 0;
}
diff --git a/tests/wayland/test_clipboard.c b/tests/wayland/test_clipboard.c
index 1778ad2..0ee74b6 100644
--- a/tests/wayland/test_clipboard.c
+++ b/tests/wayland/test_clipboard.c
@@ -6,7 +6,7 @@ struct received {
int count;
size_t len;
uint64_t request_id;
- enum yasl_transfer_status status;
+ enum yasl_private_transfer_status status;
struct clipboard *clipboard;
bool forget_on_receive;
char text[32];
@@ -14,12 +14,12 @@ struct received {
static void receive(const char *text, size_t len, bool uri_list,
struct wl_surface *surface, uint64_t request_id,
- enum yasl_transfer_status status, void *ud)
+ enum yasl_private_transfer_status status, void *ud)
{
(void)surface;
struct received *r = ud;
assert(!uri_list && len < sizeof(r->text));
- if (status == YASL_TRANSFER_OK) {
+ if (status == YASL_PRIVATE_TRANSFER_OK) {
assert(text);
memcpy(r->text, text, len);
r->text[len] = '\0';
@@ -39,7 +39,7 @@ static void receive(const char *text, size_t len, bool uri_list,
int main(void)
{
struct received received = {0};
- struct clipboard c = {.loop = yasl_loop_create(), .receive = receive, .ud = &received};
+ struct clipboard c = {.loop = yasl_private_loop_create(), .receive = receive, .ud = &received};
received.clipboard = &c;
assert(c.loop);
const struct { const char *bytes; size_t len; bool valid; } cases[] = {
@@ -55,19 +55,19 @@ int main(void)
assert(pipe(fds) == 0);
struct transfer *transfer = start_transfer_text(&c, fds[0], false, false, c.text);
assert(transfer);
- yasl_timer_id timeout_id = transfer->timeout;
- assert(timeout_id && yasl_loop_timer_armed(c.loop, timeout_id));
+ yasl_private_timer_id timeout_id = transfer->timeout;
+ assert(timeout_id && yasl_private_loop_timer_armed(c.loop, timeout_id));
transfer->paste = true;
transfer->request_id = 42;
assert(write(fds[1], cases[i].bytes, cases[i].len) == (ssize_t)cases[i].len);
close(fds[1]);
for (int steps = 0; c.transfers && steps < 10; steps++)
- assert(yasl_loop_step(c.loop, 0) >= 0);
+ assert(yasl_private_loop_step(c.loop, 0) >= 0);
assert(!c.transfers);
- assert(!yasl_loop_timer_armed(c.loop, timeout_id));
+ assert(!yasl_private_loop_timer_armed(c.loop, timeout_id));
assert(received.count == 1);
assert(received.request_id == 42);
- assert(received.status == (cases[i].valid ? YASL_TRANSFER_OK : YASL_TRANSFER_FAILED));
+ assert(received.status == (cases[i].valid ? YASL_PRIVATE_TRANSFER_OK : YASL_PRIVATE_TRANSFER_FAILED));
if (cases[i].valid) {
assert(received.len == cases[i].len);
assert(memcmp(received.text, cases[i].bytes, received.len) == 0);
@@ -79,8 +79,8 @@ int main(void)
assert(pipe(cancel_fds) == 0);
struct transfer *pending = start_transfer_text(&c, cancel_fds[0], false, false, NULL);
assert(pending);
- yasl_timer_id cancel_timeout_id = pending->timeout;
- assert(cancel_timeout_id && yasl_loop_timer_armed(c.loop, cancel_timeout_id));
+ yasl_private_timer_id cancel_timeout_id = pending->timeout;
+ assert(cancel_timeout_id && yasl_private_loop_timer_armed(c.loop, cancel_timeout_id));
pending->paste = true;
pending->request_id = 99;
struct wl_surface *target = (struct wl_surface *)(uintptr_t)1;
@@ -88,7 +88,7 @@ int main(void)
clipboard_forget_surface(&c, target);
close(cancel_fds[1]);
assert(!c.transfers && received.count == 0);
- assert(!yasl_loop_timer_armed(c.loop, cancel_timeout_id));
+ assert(!yasl_private_loop_timer_armed(c.loop, cancel_timeout_id));
received.forget_on_receive = true;
int timeout_fds[2];
@@ -99,12 +99,12 @@ int main(void)
timed->request_id = 100;
struct wl_surface *timeout_target = (struct wl_surface *)(uintptr_t)2;
timed->drop_surface = timeout_target;
- yasl_timer_id timeout_id = timed->timeout;
- assert(yasl_loop_del_timer(c.loop, timeout_id));
+ yasl_private_timer_id timeout_id = timed->timeout;
+ assert(yasl_private_loop_del_timer(c.loop, timeout_id));
(void)transfer_timeout(timed, timeout_id, CLIPBOARD_TRANSFER_TIMEOUT_NS);
close(timeout_fds[1]);
assert(!c.transfers && received.count == 1);
- assert(received.request_id == 100 && received.status == YASL_TRANSFER_FAILED);
- yasl_loop_destroy(c.loop);
+ assert(received.request_id == 100 && received.status == YASL_PRIVATE_TRANSFER_FAILED);
+ yasl_private_loop_destroy(c.loop);
return 0;
}
diff --git a/tests/wayland/test_cursor.c b/tests/wayland/test_cursor.c
index eb729a3..3425821 100644
--- a/tests/wayland/test_cursor.c
+++ b/tests/wayland/test_cursor.c
@@ -51,9 +51,9 @@ static uint32_t pointer_version(struct wl_pointer *pointer)
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
- .scale_factor = 1, .cursor = YASL_CURSOR_TEXT};
+ .scale_factor = 1, .cursor = YASL_PRIVATE_CURSOR_TEXT};
surface.surface = (struct wl_surface *)&surface;
wl_surface_set_user_data(surface.surface, &surface);
display.surfaces = &surface;
@@ -64,7 +64,7 @@ int main(void)
tool.proxy = (struct zwp_tablet_tool_v2 *)&tool;
/* The example selects hidden before either input device has entered. */
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_HIDDEN);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_HIDDEN);
assert(!pointer_hides && !tool_hides);
pointer_enter(&seat, seat.pointer, 10, surface.surface, 0, 0);
assert(pointer_hides == 1 && pointer_serial == 10);
@@ -76,14 +76,16 @@ int main(void)
pointer_frame(&seat, seat.pointer);
tablet_tool_motion(&tool, tool.proxy, wl_fixed_from_int(56), wl_fixed_from_int(78));
tool_frame(&tool, tool.proxy, 0);
- struct yasl_event event;
- assert(yasl_surface_poll_event(&surface.base, &event));
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.device == YASL_PTR_DEV_MOUSE);
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE);
assert(event.pointer.pos.x == 12 && event.pointer.pos.y == 34);
- assert(yasl_surface_poll_event(&surface.base, &event));
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.device == YASL_PTR_DEV_PEN);
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PEN && event.pen.action == YASL_PRIVATE_PEN_ENTER);
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
assert(event.pointer.pos.x == 56 && event.pointer.pos.y == 78);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
/* Each new entry needs a request with its own serial. */
pointer_leave(&seat, seat.pointer, 12, surface.surface);
@@ -98,20 +100,20 @@ int main(void)
/* Restore a visible shape on both currently focused devices. */
pointer_device = seat.cursor_shape_dev = (struct wp_cursor_shape_device_v1 *)&seat;
tool.shape_dev = (struct wp_cursor_shape_device_v1 *)&tool;
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_ARROW);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_ARROW);
assert(pointer_shapes == 1 && tool_shapes == 1);
assert(pointer_shape == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
assert(tool_shape == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_HIDDEN);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_HIDDEN);
assert(pointer_hides == 3 && tool_hides == 3);
assert(pointer_shapes == 1 && tool_shapes == 1);
/* Updating an unfocused surface must not alter the active cursor. */
struct wayland_surface other = {.base.display = &display.base, .conn = &display};
- yasl_surface_set_cursor(&other.base, YASL_CURSOR_CROSSHAIR);
+ yasl_private_surface_set_cursor(&other.base, YASL_PRIVATE_CURSOR_CROSSHAIR);
assert(pointer_shapes == 1 && tool_shapes == 1);
- yasl_surface_set_cursor(&surface.base, (enum yasl_cursor)-1);
- yasl_surface_set_cursor(&surface.base, (enum yasl_cursor)(YASL_CURSOR_HIDDEN + 1));
+ yasl_private_surface_set_cursor(&surface.base, (enum yasl_private_cursor)-1);
+ yasl_private_surface_set_cursor(&surface.base, (enum yasl_private_cursor)(YASL_PRIVATE_CURSOR_HIDDEN + 1));
assert(pointer_hides == 3 && tool_hides == 3);
assert(pointer_shapes == 1 && tool_shapes == 1);
input_queue_clear(&surface.input);
diff --git a/tests/wayland/test_input.c b/tests/wayland/test_input.c
index f6112b6..2b5592a 100644
--- a/tests/wayland/test_input.c
+++ b/tests/wayland/test_input.c
@@ -1,17 +1,35 @@
#include "platform/wayland/internal.h"
#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+static void test_ime_capability(void)
+{
+ struct wayland_display display = {0};
+ struct wayland_surface w = {.conn = &display};
+ assert(!(wayland_display_caps(&display) & YASL_PRIVATE_CAP_TEXT_INPUT));
+ errno = 0;
+ assert(!wayland_surface_update_text_input(&w) && errno == ENOTSUP);
+ display.text_input_mgr = (struct zwp_text_input_manager_v3 *)&display;
+ assert(wayland_display_caps(&display) & YASL_PRIVATE_CAP_TEXT_INPUT);
+ w.base.text_input_active = true;
+ w.base.text_purpose = 1; /* Public YASL_TEXT_PASSWORD. */
+ /* A supported compositor can accept the requested state before a seat
+ * or keyboard focus has arrived. The enter callback applies it later. */
+ assert(wayland_surface_update_text_input(&w));
+}
static void test_popup_bounds(void)
{
struct seat seat = {.input_serial = 1};
- struct wayland_display d = {.base.ops = &yasl_wayland_backend, .seats = &seat};
+ struct wayland_display d = {.base.ops = &yasl_private_wayland_backend, .seats = &seat};
struct wayland_surface w = {.base.display = &d.base, .conn = &d};
w.parent = &w;
w.content.x = w.content.y = 1;
/* Invalid bounds must be rejected before accessing any protocol object. */
w.xdg_surface = (struct xdg_surface *)&w;
w.popup = (struct xdg_popup *)&w;
- struct yasl_popup_spec specs[] = {
+ struct yasl_private_popup_spec specs[] = {
{.size = {100, 100}, .content_offset = {INT_MAX, 0}, .content_size = {1, 0}},
{.size = {100, 100}, .content_offset = {0, INT_MAX}, .content_size = {0, 1}},
{.size = {100, 100}, .content_offset = {1, 0}, .content_size = {INT_MAX, 0}},
@@ -20,16 +38,18 @@ static void test_popup_bounds(void)
{.size = {100, 100}, .anchor = {0, INT_MIN, 1, 1}},
};
for (size_t i = 0; i < sizeof(specs) / sizeof(specs[0]); i++) {
- assert(!yasl_surface_create_popup(&w.base, &specs[i]));
- assert(!yasl_surface_popup_reposition(&w.base, &specs[i]));
+ assert(!yasl_private_surface_create_popup(&w.base, &specs[i]));
+ assert(!yasl_private_surface_popup_reposition(&w.base, &specs[i]));
}
}
int main(void)
{
+ test_ime_capability();
test_popup_bounds();
struct wayland_surface w = {0};
struct seat seat = {.ime_focus = &w};
+ w.base.text_input_active = true;
wayland_surface_set_callbacks(&w, NULL, NULL);
for (int i = 0; i < 600; i++) {
char text[32];
@@ -41,11 +61,38 @@ int main(void)
for (int i = 0; i < 600; i++) {
char text[32];
snprintf(text, sizeof(text), "commit-%d", i);
- struct yasl_event event;
+ struct yasl_private_event event;
assert(wayland_surface_poll_event(&w, &event));
- assert(event.type == YASL_EVENT_TEXT && event.surface == &w.base);
+ assert(event.type == YASL_PRIVATE_EVENT_TEXT && event.surface == &w.base);
assert(strcmp(event.text.data, text) == 0);
}
+ w.base.text_input_active = true;
+ w.base.text_surrounding = strdup("ab\xf0\x9f\x98\x80" "cd");
+ w.base.text_length = 8;
+ w.base.text_begin = 2;
+ w.base.text_end = 6;
+ w.base.text_revision = 41;
+ w.base.text_generation = 9;
+ text_input_listener.delete_surrounding_text(&seat, NULL, 2, 2);
+ text_input_listener.commit_string(&seat, NULL, "X");
+ text_input_listener.done(&seat, NULL, 601);
+ struct yasl_private_event edit;
+ assert(wayland_surface_poll_event(&w, &edit));
+ assert(edit.type == YASL_PRIVATE_EVENT_TEXT_EDIT && edit.surface == &w.base);
+ assert(strcmp(edit.text_edit.data, "X") == 0 && edit.text_edit.len == 1);
+ assert(edit.text_edit.begin == 2 && edit.text_edit.end == 8);
+ assert(edit.text_edit.revision == 41 && edit.text_edit.generation == 9);
+ struct yasl_private_event committed;
+ assert(!wayland_surface_poll_event(&w, &committed));
+
+ /* Deletion without a commit replaces the range with the empty string. */
+ text_input_listener.delete_surrounding_text(&seat, NULL, 2, 2);
+ text_input_listener.done(&seat, NULL, 602);
+ assert(wayland_surface_poll_event(&w, &edit));
+ assert(edit.type == YASL_PRIVATE_EVENT_TEXT_EDIT && edit.text_edit.len == 0);
+ assert(edit.text_edit.data[0] == '\0' && edit.text_edit.begin == 2 && edit.text_edit.end == 8);
+ assert(!wayland_surface_poll_event(&w, &committed));
input_queue_clear(&w.input);
+ free(w.base.text_surrounding);
return 0;
}
diff --git a/tests/wayland/test_keyboard.c b/tests/wayland/test_keyboard.c
index bce0a0c..ae4647f 100644
--- a/tests/wayland/test_keyboard.c
+++ b/tests/wayland/test_keyboard.c
@@ -1,18 +1,18 @@
#include "../../src/platform/wayland/keyboard.c"
#include <assert.h>
-static struct yasl_event next(struct wayland_surface *w, enum yasl_event_type type)
+static struct yasl_private_event next(struct wayland_surface *w, enum yasl_private_event_type type)
{
- struct yasl_event ev;
- assert(yasl_surface_poll_event(&w->base, &ev));
+ struct yasl_private_event ev;
+ assert(yasl_private_surface_poll_event(&w->base, &ev));
assert(ev.type == type && ev.surface == &w->base);
return ev;
}
static void empty(struct wayland_surface *w)
{
- struct yasl_event ev;
- assert(!yasl_surface_poll_event(&w->base, &ev));
+ struct yasl_private_event ev;
+ assert(!yasl_private_surface_poll_event(&w->base, &ev));
}
static void layout(struct seat *s, const char *name, const char *variant)
@@ -43,7 +43,7 @@ static void key(struct seat *s, uint32_t code, bool down)
int main(void)
{
- struct wayland_display d = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display d = {.base.ops = &yasl_private_wayland_backend};
d.xkb_ctx = xkb_context_new(0);
assert(d.xkb_ctx);
struct wayland_surface w = {.base.display = &d.base, .conn = &d};
@@ -59,65 +59,66 @@ int main(void)
xkb_compose_table_unref(table);
layout(&s, "us", NULL);
key(&s, KEY_A, true);
- struct yasl_event ev = next(&w, YASL_EVENT_KEY);
+ struct yasl_private_event ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.native_code == KEY_A);
assert(ev.key.codepoint == 'a' && ev.key.shifted == 'A' && !ev.key.mods);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "a") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "a") == 0);
modifiers(&s, XKB_MOD_NAME_SHIFT);
key(&s, KEY_A, false); /* Modifier changes cannot change physical identity. */
- ev = next(&w, YASL_EVENT_KEY);
+ ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.action == YASL_KEY_RELEASE);
- assert(ev.key.mods == YASL_MOD_SHIFT);
+ assert(ev.key.mods == YASL_PRIVATE_MOD_SHIFT);
empty(&w);
key(&s, KEY_A, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "A") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "A") == 0);
modifiers(&s, XKB_MOD_NAME_CAPS);
key(&s, KEY_A, true);
- assert(next(&w, YASL_EVENT_KEY).key.mods == YASL_MOD_CAPS);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "A") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.mods == YASL_PRIVATE_MOD_CAPS);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "A") == 0);
const char *shortcuts[] = {XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_LOGO};
for (size_t i = 0; i < sizeof(shortcuts)/sizeof(shortcuts[0]); i++) {
modifiers(&s, shortcuts[i]);
key(&s, KEY_A, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
empty(&w); /* Shortcut characters never leak into committed text. */
}
layout(&s, "fr", NULL);
key(&s, KEY_A, true);
- ev = next(&w, YASL_EVENT_KEY);
+ ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.codepoint == 'q');
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "q") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "q") == 0);
layout(&s, "de", NULL);
modifiers(&s, "Mod5"); /* AltGr is text input, not an Alt shortcut. */
key(&s, KEY_E, true);
- assert(next(&w, YASL_EVENT_KEY).key.key == YASL_KEY_E);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "€") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.key == YASL_KEY_E);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "€") == 0);
layout(&s, "us", "intl");
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
empty(&w);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "é") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "é") == 0);
assert(keyboard_dispatch_key(&s, &w, KEY_E, YASL_KEY_REPEAT));
- assert(next(&w, YASL_EVENT_KEY).key.action == YASL_KEY_REPEAT);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.action == YASL_KEY_REPEAT);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
keyboard_reset_keys(&s, &w);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
s.ime_focus = &w;
+ w.base.text_input_active = true;
text_input_listener.commit_string(&s, NULL, "字");
text_input_listener.done(&s, NULL, 0);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "字") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "字") == 0);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
empty(&w);
xkb_compose_state_unref(s.compose);
xkb_state_unref(s.xkb_state);
diff --git a/tests/wayland/test_popup_positioner.c b/tests/wayland/test_popup_positioner.c
new file mode 100644
index 0000000..86778f6
--- /dev/null
+++ b/tests/wayland/test_popup_positioner.c
@@ -0,0 +1,93 @@
+/* Capture xdg_positioner requests to verify explicit placement and the legacy
+ * beside mapping without requiring a compositor. */
+#include "platform/wayland/internal.h"
+#include <assert.h>
+
+struct recorded_positioner {
+ int width, height;
+ int rect_x, rect_y, rect_width, rect_height;
+ uint32_t anchor, gravity, constraints;
+ bool reactive;
+};
+
+static struct recorded_positioner record;
+static uint64_t fake_positioner_storage[8];
+#define FAKE_POSITIONER ((struct xdg_positioner *)fake_positioner_storage)
+static struct xdg_positioner *fake_create(struct xdg_wm_base *base)
+{ (void)base; record = (struct recorded_positioner){0}; return FAKE_POSITIONER; }
+static void fake_size(struct xdg_positioner *pos, int32_t width, int32_t height)
+{ assert(pos == FAKE_POSITIONER); record.width = width; record.height = height; }
+static void fake_rect(struct xdg_positioner *pos, int32_t x, int32_t y, int32_t width, int32_t height)
+{ assert(pos == FAKE_POSITIONER); record.rect_x=x; record.rect_y=y; record.rect_width=width; record.rect_height=height; }
+static void fake_anchor(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.anchor = value; }
+static void fake_gravity(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.gravity = value; }
+static void fake_constraints(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.constraints = value; }
+static uint32_t fake_version(struct xdg_positioner *pos)
+{ assert(pos == FAKE_POSITIONER); return XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION; }
+static void fake_reactive(struct xdg_positioner *pos)
+{ assert(pos == FAKE_POSITIONER); record.reactive = true; }
+
+#define xdg_wm_base_create_positioner fake_create
+#define xdg_positioner_set_size fake_size
+#define xdg_positioner_set_anchor_rect fake_rect
+#define xdg_positioner_set_anchor fake_anchor
+#define xdg_positioner_set_gravity fake_gravity
+#define xdg_positioner_set_constraint_adjustment fake_constraints
+#define xdg_positioner_get_version fake_version
+#define xdg_positioner_set_reactive fake_reactive
+#include "../../src/platform/wayland/popup.c"
+
+int main(void)
+{
+ struct wayland_display display = {.wm_base = (struct xdg_wm_base *)&record};
+ struct wayland_surface parent = {
+ .scale_120 = 120,
+ .content = {.x = 3, .y = 4},
+ };
+ struct wayland_surface popup = {
+ .conn = &display,
+ .parent = &parent,
+ .scale_120 = 120,
+ .content = {.width = 48, .height = 36},
+ };
+ struct yasl_private_popup_spec spec = {
+ .size = {64, 48},
+ .anchor = {13, 24, 8, 6},
+ .beside = true,
+ };
+
+ struct xdg_positioner *positioner = popup_positioner(&popup, &spec);
+ assert(positioner == FAKE_POSITIONER);
+ assert(record.width == 48 && record.height == 36);
+ assert(record.rect_x == 10 && record.rect_y == 20 &&
+ record.rect_width == 8 && record.rect_height == 6);
+ assert(record.anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT);
+ assert(record.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
+ assert(record.constraints == (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y));
+ assert(record.reactive);
+
+ spec.positioner_explicit = true;
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_NONE;
+ spec.gravity = XDG_POSITIONER_GRAVITY_RIGHT;
+ spec.constraints = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
+ assert(popup_spec_valid(&parent, &spec));
+ positioner = popup_positioner(&popup, &spec);
+ assert(positioner == FAKE_POSITIONER);
+ assert(record.anchor == XDG_POSITIONER_ANCHOR_NONE);
+ assert(record.gravity == XDG_POSITIONER_GRAVITY_RIGHT);
+ assert(record.constraints == spec.constraints);
+
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT + 1;
+ assert(!popup_spec_valid(&parent, &spec));
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_NONE;
+ spec.constraints = 1u << 9;
+ assert(!popup_spec_valid(&parent, &spec));
+ return 0;
+}
diff --git a/tests/wayland/test_relative_pointer.c b/tests/wayland/test_relative_pointer.c
index bcc41e3..d44238d 100644
--- a/tests/wayland/test_relative_pointer.c
+++ b/tests/wayland/test_relative_pointer.c
@@ -65,10 +65,10 @@ static void shape_device_destroy(struct wp_cursor_shape_device_v1 *device) { ass
#define wl_pointer_release pointer_release
#include "../../src/platform/wayland/pointer.c"
-static struct yasl_event next_event(struct wayland_surface *w)
+static struct yasl_private_event next_event(struct wayland_surface *w)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(&w->base, &event));
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&w->base, &event));
return event;
}
@@ -85,9 +85,9 @@ static void relative_move(struct seat *s, double dx, double dy)
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
- .scale_factor = 2, .cursor = YASL_CURSOR_TEXT};
+ .scale_factor = 2, .cursor = YASL_PRIVATE_CURSOR_TEXT};
surface.surface = (struct wl_surface *)&surface;
wl_surface_set_user_data(surface.surface, &surface);
display.surfaces = &surface;
@@ -95,10 +95,10 @@ int main(void)
seat.pointer = (struct wl_pointer *)&seat;
seat.cursor_shape_dev = (struct wp_cursor_shape_device_v1 *)&seat;
display.seats = &seat;
- struct yasl_event event;
+ struct yasl_private_event event;
/* Without both protocols the surface stays in absolute mode. */
- assert(!yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(!yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(!surface.relative && !locks);
display.relative_pointer_mgr = (struct zwp_relative_pointer_manager_v1 *)&display;
display.pointer_constraints = (struct zwp_pointer_constraints_v1 *)&display;
@@ -107,10 +107,10 @@ int main(void)
pointer_frame(&seat, seat.pointer);
assert(pointer_shapes == 1);
event = next_event(&surface);
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.pos.x == 10);
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.pos.x == 10);
/* Relative mode locks persistently on the pointer's seat and hides the cursor. */
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(locks == 1 && locked_surface == surface.surface && locked_wl_pointer == seat.pointer);
assert(lock_lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
assert(pointer_hides == 1 && surface.lock_seat == &seat);
@@ -121,14 +121,14 @@ int main(void)
event = next_event(&surface);
assert(event.pointer.pos.x == 14 && event.pointer.pos.y == 10);
assert(event.pointer.delta.x == 4 && event.pointer.delta.y == 0);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
/* Locked: relative samples in device pixels, position frozen at the lock. */
pointer_locked(&surface, surface.pointer_lock);
relative_move(&seat, 3.5, -2);
relative_move(&seat, 1000, 0);
event = next_event(&surface);
- assert(event.type == YASL_EVENT_POINTER_MOTION);
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION);
assert(event.pointer.pos.x == 14 && event.pointer.pos.y == 10);
assert(event.pointer.delta.x == 7 && event.pointer.delta.y == -4);
event = next_event(&surface);
@@ -137,7 +137,7 @@ int main(void)
/* Deactivation (e.g. focus loss) returns to absolute motion without unlocking. */
pointer_unlocked(&surface, surface.pointer_lock);
relative_move(&seat, 5, 5);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
move_to(&seat, 8, 5);
event = next_event(&surface);
assert(event.pointer.delta.x == 2 && event.pointer.delta.y == 0);
@@ -145,12 +145,12 @@ int main(void)
pointer_locked(&surface, surface.pointer_lock);
/* Returning to normal destroys the lock and restores the chosen cursor. */
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_NORMAL));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_NORMAL));
assert(unlocks == 1 && !surface.pointer_lock && !surface.input.relative);
assert(pointer_shapes == 2);
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_NORMAL));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_NORMAL));
assert(unlocks == 1);
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(locks == 2 && pointer_hides == 2);
pointer_locked(&surface, surface.pointer_lock);
diff --git a/tests/wayland/test_state.c b/tests/wayland/test_state.c
index 2da26e5..1ce9189 100644
--- a/tests/wayland/test_state.c
+++ b/tests/wayland/test_state.c
@@ -1,6 +1,20 @@
-#include "../../src/platform/wayland/shell.c"
+#include "platform/wayland/internal.h"
#include <assert.h>
+static uint32_t acknowledged_serial;
+static unsigned acknowledge_count;
+static void test_ack_configure(struct xdg_surface *surface, uint32_t serial);
+#define xdg_surface_ack_configure test_ack_configure
+#include "../../src/platform/wayland/shell.c"
+#undef xdg_surface_ack_configure
+
+static void test_ack_configure(struct xdg_surface *surface, uint32_t serial)
+{
+ (void)surface;
+ acknowledged_serial = serial;
+ acknowledge_count++;
+}
+
struct notifications {
int count;
uint32_t state;
@@ -9,7 +23,7 @@ struct notifications {
static void state_changed(struct yasl_surface *surface, uint32_t state, void *ud)
{
struct notifications *notifications = ud;
- assert(yasl_surface_state(surface) == state);
+ assert(yasl_private_surface_state(surface) == state);
notifications->count++;
notifications->state = state;
}
@@ -24,33 +38,33 @@ static void configure(struct wayland_surface *surface, uint32_t *states, size_t
int main(void)
{
struct notifications notifications = {0};
- struct wayland_surface surface = {.base.state = YASL_STATE_CSD};
- wayland_surface_set_callbacks(&surface, &(struct yasl_window_cbs){
+ struct wayland_surface surface = {.base.state = YASL_PRIVATE_STATE_CSD};
+ wayland_surface_set_callbacks(&surface, &(struct yasl_private_window_cbs){
.state = state_changed}, &notifications);
- assert(yasl_surface_state(&surface.base) == YASL_STATE_CSD);
+ assert(yasl_private_surface_state(&surface.base) == YASL_PRIVATE_STATE_CSD);
uint32_t fullscreen[] = {XDG_TOPLEVEL_STATE_FULLSCREEN,
XDG_TOPLEVEL_STATE_ACTIVATED, XDG_TOPLEVEL_STATE_FULLSCREEN, 31, UINT32_MAX};
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
assert(notifications.count == 1);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
assert(notifications.count == 1);
/* Decoration changes preserve the other flags and do not notify twice. */
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
assert(notifications.count == 2);
- assert(notifications.state == (YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
assert(notifications.count == 2);
uint32_t maximized[] = {XDG_TOPLEVEL_STATE_MAXIMIZED, XDG_TOPLEVEL_STATE_SUSPENDED};
configure(&surface, maximized, sizeof(maximized) / sizeof(*maximized));
assert(notifications.count == 3);
- assert(notifications.state == (YASL_STATE_MAXIMIZED | YASL_STATE_SUSPENDED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_SUSPENDED));
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
assert(notifications.count == 4);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_MAXIMIZED | YASL_STATE_SUSPENDED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_SUSPENDED));
/* Each tiled edge maps to the same portable flag; changing edges alone
* leaves the reported state unchanged. */
@@ -59,17 +73,38 @@ int main(void)
for (size_t i = 0; i < sizeof(edges) / sizeof(*edges); i++) {
configure(&surface, &edges[i], 1);
assert(notifications.count == 5);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_TILED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_TILED));
}
configure(&surface, edges, 0);
assert(notifications.count == 6);
- assert(notifications.state == YASL_STATE_CSD);
+ assert(notifications.state == YASL_PRIVATE_STATE_CSD);
/* State still advances when applications have not installed callbacks. */
wayland_surface_set_callbacks(&surface, NULL, NULL);
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
- assert(yasl_surface_state(&surface.base) ==
- (YASL_STATE_CSD | YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(yasl_private_surface_state(&surface.base) ==
+ (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
assert(notifications.count == 6);
+
+ /* External presentation has no SHM commit callback to acknowledge xdg
+ * configures. Apply geometry and acknowledge before renderer submission. */
+ struct wayland_surface gpu = {
+ .base.presenter = YASL_PRIVATE_PRESENTER_VULKAN,
+ .width = 0, .height = 0,
+ .logical_width = 64, .logical_height = 64,
+ .req_width = 64, .req_height = 64,
+ .scale_120 = YASL_PRIVATE_SCALE_UNIT,
+ .pending_scale_120 = 180,
+ };
+ acknowledge_count = 0;
+ xdg_surface_configure(&gpu, (struct xdg_surface *)&gpu, 1234);
+ assert(acknowledge_count == 1 && acknowledged_serial == 1234);
+ assert(!gpu.has_pending_serial && !gpu.size_pending);
+ assert(gpu.configured && gpu.width == 96 && gpu.height == 96);
+
+ /* CPU presentation keeps its existing deferred ack with the SHM commit. */
+ struct wayland_surface cpu = {.base.presenter = YASL_PRIVATE_PRESENTER_CPU};
+ xdg_surface_configure(&cpu, (struct xdg_surface *)&cpu, 5678);
+ assert(acknowledge_count == 1 && cpu.has_pending_serial && cpu.want_draw);
return 0;
}
diff --git a/tests/wayland/test_tablet.c b/tests/wayland/test_tablet.c
index c76ddf8..f47fbfa 100644
--- a/tests/wayland/test_tablet.c
+++ b/tests/wayland/test_tablet.c
@@ -1,63 +1,101 @@
#include "../../src/platform/wayland/pointer.c"
#include <assert.h>
-static struct yasl_event next(struct wayland_surface *surface)
+static struct yasl_private_event next_raw(struct wayland_surface *surface)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(&surface->base, &event));
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&surface->base, &event));
assert(event.surface == &surface->base);
return event;
}
+static struct yasl_private_event next_pointer(struct wayland_surface *surface)
+{
+ struct yasl_private_event event;
+ do { event = next_raw(surface); } while (event.type == YASL_PRIVATE_EVENT_PEN);
+ return event;
+}
+
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
.scale_factor = 1.5};
struct seat seat = {.conn = &display, .tablet_focus = &surface};
- struct tablet_tool tool = {.seat = &seat};
+ struct tablet_tool tool = {.seat = &seat, .device_id = 77, .tool_id = 88, .kind = 1};
seat.tool = &tool;
tablet_tool_motion(&tool, NULL, wl_fixed_from_int(100), wl_fixed_from_int(120));
tool_pressure(&tool, NULL, 32768);
tool_tilt(&tool, NULL, wl_fixed_from_int(-35), wl_fixed_from_int(42));
+ tool_distance(&tool, NULL, 16384);
+ tool_rotation(&tool, NULL, wl_fixed_from_int(17));
+ tool_slider(&tool, NULL, -32768);
+ pen_action_push(&tool, YASL_PRIVATE_PEN_ENTER, 0);
tablet_tool_down(&tool, NULL, 1);
tool_frame(&tool, NULL, 0);
- struct yasl_event ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.device == YASL_PTR_DEV_PEN);
+ struct yasl_private_event pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_ENTER && !pen.pen.in_contact);
+ assert(pen.pen.device_id == 77 && pen.pen.tool_id == 88);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_DOWN && pen.pen.in_contact);
+ assert(pen.pen.buttons & YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY));
+ assert(pen.pen.x == 150 && pen.pen.y == 180);
+ assert(fabs(pen.pen.pressure - (32768.0 / 65535.0)) < 0.00001);
+ assert(pen.pen.axes_valid == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT |
+ YASL_PRIVATE_PEN_DISTANCE | YASL_PRIVATE_PEN_ROTATION | YASL_PRIVATE_PEN_TANGENTIAL));
+ assert(pen.pen.axes_changed == pen.pen.axes_valid);
+ assert(fabs(pen.pen.distance - 16384.0 / 65535.0) < 0.00001);
+ assert(pen.pen.rotation == 17 && pen.pen.tangential == -32768.0 / 65535.0);
+ struct yasl_private_event ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
assert(ev.pointer.pos.x == 150 && ev.pointer.pos.y == 180 && ev.pointer.pen.pressure == 32768);
assert(ev.pointer.pen.tilt_x == -35 && ev.pointer.pen.tilt_y == 42);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_DOWN && ev.pointer.button == YASL_BUTTON_PRIMARY && ev.pointer.pen.pressure == 32768);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_DOWN && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && ev.pointer.pen.pressure == 32768);
/* Stationary pressure and tilt changes are still motion samples. */
tool_pressure(&tool, NULL, 100000);
tool_tilt(&tool, NULL, wl_fixed_from_int(-120), wl_fixed_from_int(120));
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_MOVE);
+ assert(pen.pen.axes_changed == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT));
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
assert(ev.pointer.pos.x == 150 && ev.pointer.pos.y == 180);
assert(ev.pointer.pen.tilt_x == -90 && ev.pointer.pen.tilt_y == 90);
tablet_tool_up(&tool, NULL);
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_UP && ev.pointer.button == YASL_BUTTON_PRIMARY && !ev.pointer.pen.pressure);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_UP);
+ assert(!pen.pen.in_contact && pen.pen.pressure == 0);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_UP && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && !ev.pointer.pen.pressure);
tool_type(&tool, NULL, ZWP_TABLET_TOOL_V2_TYPE_ERASER);
tool_pressure(&tool, NULL, 22000);
tool_frame(&tool, NULL, 0);
- assert(next(&surface).pointer.device == YASL_PTR_DEV_ERASER);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.tool == 2);
+ assert(next_pointer(&surface).pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
tool_wheel(&tool, NULL, 0, 1);
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PTR_DEV_ERASER);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.axes_changed == YASL_PRIVATE_PEN_WHEEL);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
assert(ev.pointer.scroll.x == 0 && ev.pointer.scroll.y == 1);
tablet_tool_proximity_out(&tool, NULL);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_LEAVE);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
assert(!seat.tool && !seat.tablet_focus && !seat.tool_buttons);
- assert(!(yasl_display_caps(&display.base) & YASL_CAP_TABLET));
+ assert(!(yasl_private_display_caps(&display.base) & YASL_PRIVATE_CAP_TABLET));
display.tablet_mgr = (void *)&display; /* Capability depends on protocol availability. */
- assert(yasl_display_caps(&display.base) & YASL_CAP_TABLET);
+ assert(yasl_private_display_caps(&display.base) & YASL_PRIVATE_CAP_TABLET);
seat.pointer_focus = &surface;
/* A compositor may describe the same detent in three ways. value120 wins,
@@ -67,13 +105,32 @@ int main(void)
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_VERTICAL_SCROLL, 30);
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_HORIZONTAL_SCROLL, -60);
pointer_frame(&seat, NULL);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PTR_DEV_MOUSE);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE);
assert(ev.pointer.scroll.x == -0.5 && ev.pointer.scroll.y == 0.25);
- struct yasl_event unused;
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ assert(ev.pointer.scroll_valid == 1);
+ assert(ev.pointer.scroll_source == 1 && ev.pointer.scroll_phase == 0);
+ struct yasl_private_event unused;
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
+ pointer_frame(&seat, NULL);
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
+
+ /* Finger scrolling carries pixel offsets and coherent gesture phases. */
+ pointer_axis_source(&seat, NULL, WL_POINTER_AXIS_SOURCE_FINGER);
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(1.25));
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(-2.5));
+ pointer_frame(&seat, NULL);
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 1 && ev.pointer.scroll_source == 2);
+ assert(ev.pointer.pixel_scroll.x == -3.75 && ev.pointer.pixel_scroll.y == 1.875);
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(1.25));
+ pointer_frame(&seat, NULL);
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 2 && ev.pointer.scroll.y == 0.125);
+ pointer_axis_stop(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL);
pointer_frame(&seat, NULL);
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 3 && ev.pointer.scroll.x == 0 && ev.pointer.scroll.y == 0);
/* Stops preserve offsets from the same frame. Repeated tiny movements
* must be visible immediately rather than held until a whole detent. */
@@ -83,17 +140,19 @@ int main(void)
pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(-2.5));
pointer_axis_stop(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL);
pointer_frame(&seat, NULL);
- ev = next(&surface);
+ ev = next_pointer(&surface);
assert(ev.pointer.scroll.x == -0.25 && ev.pointer.scroll.y == 0.125);
+ assert(ev.pointer.scroll_source == 2 && ev.pointer.scroll_phase == 3);
+ assert(ev.pointer.pixel_scroll.x == -3.75 && ev.pointer.pixel_scroll.y == 1.875);
}
pointer_axis_discrete(&seat, NULL, WL_POINTER_AXIS_HORIZONTAL_SCROLL, 2);
pointer_frame(&seat, NULL);
- ev = next(&surface);
+ ev = next_pointer(&surface);
assert(ev.pointer.scroll.x == 2 && ev.pointer.scroll.y == 0);
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_VERTICAL_SCROLL, 60);
seat_pointer_reset(&seat);
pointer_frame(&seat, NULL);
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
input_queue_clear(&surface.input);
return 0;
}
diff --git a/tests/x11/inputtest-protocol.h b/tests/x11/inputtest-protocol.h
index 18f62ba..2a94a55 100644
--- a/tests/x11/inputtest-protocol.h
+++ b/tests/x11/inputtest-protocol.h
@@ -22,8 +22,8 @@
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef YASL_TEST_INPUTTEST_PROTOCOL_H
-#define YASL_TEST_INPUTTEST_PROTOCOL_H
+#ifndef YASL_PRIVATE_TEST_INPUTTEST_PROTOCOL_H
+#define YASL_PRIVATE_TEST_INPUTTEST_PROTOCOL_H
#include <stdint.h>
diff --git a/tests/x11/test_input.c b/tests/x11/test_input.c
index c2eca37..ccad859 100644
--- a/tests/x11/test_input.c
+++ b/tests/x11/test_input.c
@@ -8,10 +8,10 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
{
Window requestor = XCreateSimpleWindow(d->native, DefaultRootWindow(d->native),
0, 0, 1, 1, 0, 0, 0);
- Atom property = XInternAtom(d->native, "YASL_TEST_STRING", False);
+ Atom property = XInternAtom(d->native, "YASL_PRIVATE_TEST_STRING", False);
XSelectionRequestEvent request = {.display = d->native, .requestor = requestor,
.selection = d->clipboard, .target = XA_STRING, .property = property};
- yasl_display_copy(&d->base, YASL_CLIPBOARD, "café £");
+ yasl_private_display_copy(&d->base, YASL_PRIVATE_CLIPBOARD, "café £");
selection_request(d, &request);
Atom actual;
int format;
@@ -22,7 +22,7 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
assert(actual == XA_STRING && format == 8 && count == 6);
assert(memcmp(data, "caf\xe9 \xa3", count) == 0);
XFree(data);
- yasl_display_copy(&d->base, YASL_CLIPBOARD, "字");
+ yasl_private_display_copy(&d->base, YASL_PRIVATE_CLIPBOARD, "字");
selection_request(d, &request);
assert(XGetWindowProperty(d->native, requestor, property, 0, 100, True,
AnyPropertyType, &actual, &format, &count, &left, &data) == Success);
@@ -44,12 +44,12 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
size_t len;
int format;
const char *expected;
- enum yasl_transfer_status status;
+ enum yasl_private_transfer_status status;
} cases[] = {
- {XA_STRING, "caf\xe9 \xa3", 6, 8, "café £", YASL_TRANSFER_OK},
- {d->utf8, "", 0, 8, "", YASL_TRANSFER_OK},
- {d->utf8, "\xff", 1, 8, NULL, YASL_TRANSFER_FAILED},
- {d->incr, NULL, 1, 32, NULL, YASL_TRANSFER_FAILED},
+ {XA_STRING, "caf\xe9 \xa3", 6, 8, "café £", YASL_PRIVATE_TRANSFER_OK},
+ {d->utf8, "", 0, 8, "", YASL_PRIVATE_TRANSFER_OK},
+ {d->utf8, "\xff", 1, 8, NULL, YASL_PRIVATE_TRANSFER_FAILED},
+ {d->incr, NULL, 1, 32, NULL, YASL_PRIVATE_TRANSFER_FAILED},
};
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
struct paste_request *pending = calloc(1, sizeof(*pending));
@@ -59,7 +59,7 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
0, 0, 1, 1, 0, 0, 0);
pending->target = s;
pending->id = (uint64_t)i + 1;
- pending->timeout = yasl_loop_add_timer(d->loop, PASTE_TIMEOUT_NS,
+ pending->timeout = yasl_private_loop_add_timer(d->loop, PASTE_TIMEOUT_NS,
paste_timeout, pending);
assert(pending->timeout);
pending->next = d->pastes;
@@ -71,21 +71,21 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
cases[i].format, PropModeReplace, bytes, (int)cases[i].len);
XSelectionEvent reply = {.requestor = pending->window, .property = property};
selection_notify(d, &reply);
- struct yasl_event event;
- assert(yasl_surface_poll_event(&s->base, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == i + 1);
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&s->base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == i + 1);
assert(event.paste.status == cases[i].status);
- if (cases[i].status == YASL_TRANSFER_OK) {
+ if (cases[i].status == YASL_PRIVATE_TRANSFER_OK) {
assert(event.text.len == strlen(cases[i].expected));
assert(strcmp(event.text.data, cases[i].expected) == 0);
}
if (cases[i].type == d->incr) {
assert(d->pastes == pending && !pending->target);
- assert(yasl_loop_del_timer(d->loop, pending->timeout));
+ assert(yasl_private_loop_del_timer(d->loop, pending->timeout));
pending->timeout = 0;
paste_timeout(pending, 0, PASTE_TIMEOUT_NS);
}
- assert(!yasl_surface_poll_event(&s->base, &event));
+ assert(!yasl_private_surface_poll_event(&s->base, &event));
}
struct paste_request *rejected = calloc(1, sizeof(*rejected));
@@ -99,10 +99,10 @@ static void check_selection_encoding(struct x11_display *d, struct x11_surface *
d->pastes = rejected;
XSelectionEvent no_property = {.requestor = rejected->window, .property = None};
selection_notify(d, &no_property);
- struct yasl_event event;
- assert(yasl_surface_poll_event(&s->base, &event));
- assert(event.type == YASL_EVENT_PASTE && event.paste.request_id == 99);
- assert(event.paste.status == YASL_TRANSFER_FAILED);
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&s->base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == 99);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_FAILED);
}
/* Own the XSETTINGS selection with one Net/DoubleClickTime value. */
@@ -111,7 +111,7 @@ static void check_double_click(struct x11_display *d)
/* No settings owner and no portal: the default applies. */
unsetenv("DBUS_SESSION_BUS_ADDRESS");
unsetenv("XDG_RUNTIME_DIR");
- assert(yasl_display_double_click_ms(&d->base) == YASL_DOUBLE_CLICK_MS_DEFAULT);
+ assert(yasl_private_display_double_click_ms(&d->base) == YASL_PRIVATE_DOUBLE_CLICK_MS_DEFAULT);
char name[32];
snprintf(name, sizeof(name), "_XSETTINGS_S%d", d->screen);
@@ -129,64 +129,64 @@ static void check_double_click(struct x11_display *d)
XChangeProperty(d->native, owner, property, property, 8, PropModeReplace,
blob, sizeof(blob));
XSync(d->native, False);
- assert(yasl_display_double_click_ms(&d->base) == 250);
+ assert(yasl_private_display_double_click_ms(&d->base) == 250);
XDestroyWindow(d->native, owner);
XSync(d->native, False);
- assert(yasl_display_double_click_ms(&d->base) == YASL_DOUBLE_CLICK_MS_DEFAULT);
+ assert(yasl_private_display_double_click_ms(&d->base) == YASL_PRIVATE_DOUBLE_CLICK_MS_DEFAULT);
}
-static struct yasl_event wait_paste(struct yasl_display *display, uint64_t id)
+static struct yasl_private_event wait_paste(struct yasl_private_display *display, uint64_t id)
{
- struct yasl_event event;
- for (int i = 0; i < 256 && yasl_display_poll_event(display, &event); i++)
- if (event.type == YASL_EVENT_PASTE && event.paste.request_id == id)
+ struct yasl_private_event event;
+ for (int i = 0; i < 256 && yasl_private_display_poll_event(display, &event); i++)
+ if (event.type == YASL_PRIVATE_EVENT_PASTE && event.paste.request_id == id)
return event;
assert(!"expected paste completion was not queued");
- return (struct yasl_event){0};
+ return (struct yasl_private_event){0};
}
static void check_request_completion(struct x11_display *d, struct x11_surface *s)
{
assert(surface_input_queue(&s->base) == &s->input);
- assert(copy_text(&d->base, YASL_CLIPBOARD, ""));
+ assert(copy_text(&d->base, YASL_PRIVATE_CLIPBOARD, ""));
XSync(d->native, False);
assert(XGetSelectionOwner(d->native, d->clipboard) == d->selection_window);
- assert(request_paste(&d->base, YASL_CLIPBOARD, &s->base, 101));
- struct yasl_event event = wait_paste(&d->base, 101);
- assert(event.paste.status == YASL_TRANSFER_OK && event.paste.len == 0);
+ assert(request_paste(&d->base, YASL_PRIVATE_CLIPBOARD, &s->base, 101));
+ struct yasl_private_event event = wait_paste(&d->base, 101);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_OK && event.paste.len == 0);
assert(event.paste.data && !event.paste.data[0]);
XSetSelectionOwner(d->native, d->clipboard, None, CurrentTime);
XSync(d->native, False);
- assert(request_paste(&d->base, YASL_CLIPBOARD, &s->base, 102));
+ assert(request_paste(&d->base, YASL_PRIVATE_CLIPBOARD, &s->base, 102));
XSync(d->native, False);
dispatch(&d->base);
event = wait_paste(&d->base, 102);
- assert(event.paste.status == YASL_TRANSFER_UNAVAILABLE);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_UNAVAILABLE);
Window silent_owner = XCreateSimpleWindow(d->native, DefaultRootWindow(d->native),
0, 0, 1, 1, 0, 0, 0);
XSetSelectionOwner(d->native, d->clipboard, silent_owner, CurrentTime);
XSync(d->native, False);
- assert(request_paste(&d->base, YASL_CLIPBOARD, &s->base, 103));
+ assert(request_paste(&d->base, YASL_PRIVATE_CLIPBOARD, &s->base, 103));
struct paste_request *timed = d->pastes;
assert(timed && timed->id == 103 && timed->timeout);
- assert(yasl_loop_del_timer(d->loop, timed->timeout));
+ assert(yasl_private_loop_del_timer(d->loop, timed->timeout));
timed->timeout = 0;
paste_timeout(timed, 0, PASTE_TIMEOUT_NS);
event = wait_paste(&d->base, 103);
- assert(event.paste.status == YASL_TRANSFER_FAILED);
+ assert(event.paste.status == YASL_PRIVATE_TRANSFER_FAILED);
- struct yasl_window_spec spec = {.title = "Cancelled paste", .size = {80, 60}};
- struct yasl_surface *cancel_target = yasl_surface_create_toplevel(&d->base, &spec);
+ struct yasl_private_window_spec spec = {.title = "Cancelled paste", .size = {80, 60}};
+ struct yasl_surface *cancel_target = yasl_private_surface_create_toplevel(&d->base, &spec);
assert(cancel_target);
- assert(request_paste(&d->base, YASL_CLIPBOARD, cancel_target, 104));
+ assert(request_paste(&d->base, YASL_PRIVATE_CLIPBOARD, cancel_target, 104));
assert(d->pastes && d->pastes->target == (struct x11_surface *)cancel_target);
- yasl_timer_id timeout = d->pastes->timeout;
- yasl_surface_destroy(cancel_target);
+ yasl_private_timer_id timeout = d->pastes->timeout;
+ yasl_private_surface_destroy(cancel_target);
assert(d->pastes && !d->pastes->target && d->pastes->id == 0);
- assert(yasl_loop_del_timer(d->loop, timeout));
+ assert(yasl_private_loop_del_timer(d->loop, timeout));
d->pastes->timeout = 0;
XSelectionEvent late_reply = {
.requestor = d->pastes->window,
@@ -200,23 +200,23 @@ static void check_request_completion(struct x11_display *d, struct x11_surface *
XSync(d->native, False);
}
-static struct yasl_event next_composition(struct yasl_display *display)
+static struct yasl_private_event next_composition(struct yasl_private_display *display)
{
- struct yasl_event event;
- for (int i = 0; i < 256 && yasl_display_poll_event(display, &event); i++)
- if (event.type == YASL_EVENT_COMPOSITION)
+ struct yasl_private_event event;
+ for (int i = 0; i < 256 && yasl_private_display_poll_event(display, &event); i++)
+ if (event.type == YASL_PRIVATE_EVENT_COMPOSITION)
return event;
assert(!"expected composition snapshot was not queued");
- return (struct yasl_event){0};
+ return (struct yasl_private_event){0};
}
-static void drain_display_events(struct yasl_display *display)
+static void drain_display_events(struct yasl_private_display *display)
{
- struct yasl_event event;
- while (yasl_display_poll_event(display, &event)) {}
+ struct yasl_private_event event;
+ while (yasl_private_display_poll_event(display, &event)) {}
}
-static void check_xim_callbacks(struct yasl_display *display, struct x11_surface *s)
+static void check_xim_callbacks(struct yasl_private_display *display, struct x11_surface *s)
{
const char *old_locale = setlocale(LC_CTYPE, NULL);
char *saved_locale = old_locale ? strdup(old_locale) : NULL;
@@ -235,7 +235,7 @@ static void check_xim_callbacks(struct yasl_display *display, struct x11_surface
};
xim_preedit_draw(NULL, (XPointer)s, (XPointer)&draw);
assert(s->ime_preedit && strcmp(s->ime_preedit, "A😀B") == 0);
- struct yasl_event event = next_composition(display);
+ struct yasl_private_event event = next_composition(display);
assert(event.composition.active && event.composition.len == 6);
assert(event.composition.begin == 5 && event.composition.end == 5);
@@ -271,8 +271,8 @@ static void check_xim_callbacks(struct yasl_display *display, struct x11_surface
draw.chg_length = 0;
xim_preedit_draw(NULL, (XPointer)s, (XPointer)&draw);
assert(strcmp(s->ime_preedit, "AéZB") == 0);
- struct yasl_event unused;
- assert(!yasl_display_poll_event(display, &unused));
+ struct yasl_private_event unused;
+ assert(!yasl_private_display_poll_event(display, &unused));
wchar_t empty[] = {0};
XIMText deletion = {.length = 0, .encoding_is_wchar = True,
@@ -305,12 +305,12 @@ static void check_xim_callbacks(struct yasl_display *display, struct x11_surface
int main(void)
{
- struct yasl_display_spec ds = {.backend = YASL_BACKEND_X11};
- struct yasl_display *base = yasl_display_open(NULL, &ds);
+ struct yasl_private_display_spec ds = {.backend = YASL_PRIVATE_BACKEND_X11};
+ struct yasl_private_display *base = yasl_private_display_open(NULL, &ds);
assert(base);
struct x11_display *d = (struct x11_display *)base;
- struct yasl_window_spec spec = {.title = "Keyboard fallback", .size = {100, 100}};
- struct yasl_surface *surface = yasl_surface_create_toplevel(base, &spec);
+ struct yasl_private_window_spec spec = {.title = "Keyboard fallback", .size = {100, 100}};
+ struct yasl_surface *surface = yasl_private_surface_create_toplevel(base, &spec);
assert(surface);
struct x11_surface *s = (struct x11_surface *)surface;
XIC saved_ic = s->ic;
@@ -335,22 +335,22 @@ int main(void)
input_queue_clear(&s->input);
/* Native creation and keymap updates may already have queued focus or
* reset input on the shared display stream. Isolate this synthetic key. */
- struct yasl_event event;
- while (yasl_surface_poll_event(surface, &event)) {}
+ struct yasl_private_event event;
+ while (yasl_private_surface_poll_event(surface, &event)) {}
XKeyEvent native = {.type = KeyPress, .display = d->native,
.window = s->window, .keycode = code};
key_event(s, &native, false);
- assert(yasl_surface_poll_event(surface, &event));
- assert(event.type == YASL_EVENT_KEY && event.key.key == YASL_KEY_A);
+ assert(yasl_private_surface_poll_event(surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_KEY && event.key.key == YASL_KEY_A);
assert(event.key.codepoint == cases[i].label);
- assert(yasl_surface_poll_event(surface, &event));
- assert(event.type == YASL_EVENT_TEXT && event.text.len == strlen(cases[i].text));
+ assert(yasl_private_surface_poll_event(surface, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_TEXT && event.text.len == strlen(cases[i].text));
assert(strcmp(event.text.data, cases[i].text) == 0);
- assert(!yasl_surface_poll_event(surface, &event));
+ assert(!yasl_private_surface_poll_event(surface, &event));
native.type = KeyRelease;
key_event(s, &native, false);
- assert(yasl_surface_poll_event(surface, &event) && event.type == YASL_EVENT_KEY);
- assert(!yasl_surface_poll_event(surface, &event));
+ assert(yasl_private_surface_poll_event(surface, &event) && event.type == YASL_PRIVATE_EVENT_KEY);
+ assert(!yasl_private_surface_poll_event(surface, &event));
}
XChangeKeyboardMapping(d->native, code, width, saved, 1);
XSync(d->native, False);
@@ -363,14 +363,14 @@ int main(void)
check_xim_callbacks(base, s);
/* Test CSD interactive actions, window menu, and IME caret */
- assert(yasl_display_caps(base) & YASL_CAP_CSD);
- yasl_surface_set_ime_caret(surface, (struct yasl_rect2i){10, 20, 2, 16});
- assert(yasl_surface_ime_preedit(surface) == NULL);
+ assert(yasl_private_display_caps(base) & YASL_PRIVATE_CAP_CSD);
+ yasl_private_surface_set_ime_caret(surface, (struct yasl_private_rect2i){10, 20, 2, 16});
+ assert(yasl_private_surface_ime_preedit(surface) == NULL);
int begin = -1, end = -1;
- assert(!yasl_surface_ime_preedit_cursor(surface, &begin, &end));
- assert(yasl_surface_show_window_menu(surface, (struct yasl_vector2i){50, 50}));
+ assert(!yasl_private_surface_ime_preedit_cursor(surface, &begin, &end));
+ assert(yasl_private_surface_show_window_menu(surface, (struct yasl_private_vector2i){50, 50}));
- yasl_surface_destroy(surface);
- yasl_display_close(base);
+ yasl_private_surface_destroy(surface);
+ yasl_private_display_close(base);
return 0;
}
diff --git a/tests/x11/test_state.c b/tests/x11/test_state.c
index abc0851..4696e60 100644
--- a/tests/x11/test_state.c
+++ b/tests/x11/test_state.c
@@ -31,7 +31,7 @@ int state_property(Display *display, Window window, Atom property,
static void state_changed(struct yasl_surface *surface, uint32_t state, void *ud)
{
(void)ud;
- assert(yasl_surface_state(surface) == state);
+ assert(yasl_private_surface_state(surface) == state);
reported_state = state;
notifications++;
}
@@ -93,39 +93,39 @@ static void test_xsettings(void)
int main(void)
{
test_xsettings();
- struct x11_display display = {.base.ops = &yasl_x11_backend,
+ struct x11_display display = {.base.ops = &yasl_private_x11_backend,
.net_state = 10, .fullscreen = 20, .maximized_h = 21, .maximized_v = 22};
display.native = (Display *)&display;
struct x11_surface surface = {.base = {.display = &display.base,
- .state = YASL_STATE_ACTIVATED}, .window = 42};
- set_callbacks(&surface.base, &(struct yasl_window_cbs){.state = state_changed}, NULL);
+ .state = YASL_PRIVATE_STATE_ACTIVATED}, .window = 42};
+ set_callbacks(&surface.base, &(struct yasl_private_window_cbs){.state = state_changed}, NULL);
properties[0] = display.fullscreen;
property_count = 1;
update_state(&surface);
assert(notifications == 1);
- assert(reported_state == (YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(reported_state == (YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
update_state(&surface);
assert(notifications == 1);
/* Both maximized axes are required; activation survives property changes. */
properties[0] = display.maximized_h;
update_state(&surface);
- assert(notifications == 2 && reported_state == YASL_STATE_ACTIVATED);
+ assert(notifications == 2 && reported_state == YASL_PRIVATE_STATE_ACTIVATED);
properties[1] = display.maximized_v;
property_count = 2;
update_state(&surface);
assert(notifications == 3);
- assert(reported_state == (YASL_STATE_MAXIMIZED | YASL_STATE_ACTIVATED));
+ assert(reported_state == (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_ACTIVATED));
properties[2] = display.fullscreen;
property_count = 3;
update_state(&surface);
assert(notifications == 4);
- assert(reported_state == (YASL_STATE_FULLSCREEN | YASL_STATE_MAXIMIZED | YASL_STATE_ACTIVATED));
+ assert(reported_state == (YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_ACTIVATED));
property_count = 0;
update_state(&surface);
- assert(notifications == 5 && reported_state == YASL_STATE_ACTIVATED);
+ assert(notifications == 5 && reported_state == YASL_PRIVATE_STATE_ACTIVATED);
update_state(&surface);
assert(notifications == 5);
return 0;
diff --git a/tests/x11/test_tablet.c b/tests/x11/test_tablet.c
index 243ae00..be5da4c 100644
--- a/tests/x11/test_tablet.c
+++ b/tests/x11/test_tablet.c
@@ -1,10 +1,18 @@
/* Exercise native XI2 samples through the backend and public input queue. */
#include "../../src/platform/x11/window.c"
-static struct yasl_event next(struct x11_surface *surface)
+static struct yasl_private_event next(struct x11_surface *surface)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(&surface->base, &event));
+ struct yasl_private_event event;
+ /* This backend unit harness owns a standalone input queue, without a
+ * registered display event FIFO. Read rich private events directly. */
+ static unsigned count;
+ count++;
+ if (!input_queue_pop(&surface->input, &event)) {
+ fprintf(stderr, "missing private event at expectation %u (queued=%zu reset=%d)\n",
+ count, surface->input.count, surface->input.reset_pending);
+ abort();
+ }
assert(event.surface == &surface->base);
return event;
}
@@ -13,51 +21,51 @@ struct drag_test_recorder {
int over_count;
int leave_count;
int drop_count;
- struct yasl_vector2i last_pos;
+ struct yasl_private_vector2i last_pos;
};
-static void on_test_drag(struct yasl_surface *s, enum yasl_drag_event ev,
- struct yasl_vector2i pos, void *ud)
+static void on_test_drag(struct yasl_surface *s, enum yasl_private_drag_event ev,
+ struct yasl_private_vector2i pos, void *ud)
{
(void)s;
struct drag_test_recorder *rec = ud;
rec->last_pos = pos;
- if (ev == YASL_DRAG_OVER) rec->over_count++;
- else if (ev == YASL_DRAG_LEAVE) rec->leave_count++;
- else if (ev == YASL_DRAG_DROP) rec->drop_count++;
+ if (ev == YASL_PRIVATE_DRAG_OVER) rec->over_count++;
+ else if (ev == YASL_PRIVATE_DRAG_LEAVE) rec->leave_count++;
+ else if (ev == YASL_PRIVATE_DRAG_DROP) rec->drop_count++;
}
struct drop_test_recorder {
int over_count;
int leave_count;
- struct yasl_vector2i last_pos;
+ struct yasl_private_vector2i last_pos;
};
-static void on_test_drop(struct yasl_surface *s, enum yasl_drop_event ev,
- struct yasl_vector2i pos, void *ud)
+static void on_test_drop(struct yasl_surface *s, enum yasl_private_drop_event ev,
+ struct yasl_private_vector2i pos, void *ud)
{
(void)s;
struct drop_test_recorder *rec = ud;
rec->last_pos = pos;
- if (ev == YASL_DROP_OVER) rec->over_count++;
- else if (ev == YASL_DROP_LEAVE) rec->leave_count++;
+ if (ev == YASL_PRIVATE_DROP_OVER) rec->over_count++;
+ else if (ev == YASL_PRIVATE_DROP_LEAVE) rec->leave_count++;
}
-static void on_test_drag_end(void *ud, enum yasl_drag_end how)
+static void on_test_drag_end(void *ud, enum yasl_private_drag_end how)
{
- enum yasl_drag_end *res = ud;
+ enum yasl_private_drag_end *res = ud;
*res = how;
}
static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
{
/* 1. Caps */
- assert(caps(&d->base) & YASL_CAP_POPUPS);
- assert(caps(&d->base) & YASL_CAP_DRAG);
- assert(caps(&d->base) & YASL_CAP_DRAG_CARRY);
+ assert(caps(&d->base) & YASL_PRIVATE_CAP_POPUPS);
+ assert(caps(&d->base) & YASL_PRIVATE_CAP_DRAG);
+ assert(caps(&d->base) & YASL_PRIVATE_CAP_DRAG_CARRY);
/* 2. Popups: spec validation, calculation, creation, reposition, destruction */
- struct yasl_popup_spec invalid_specs[] = {
+ struct yasl_private_popup_spec invalid_specs[] = {
{.size = {0, 100}},
{.size = {100, 0}},
{.size = {35000, 100}},
@@ -70,7 +78,7 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
assert(!surface_create_popup(&s->base, &invalid_specs[i]));
}
- struct yasl_popup_spec valid_spec = {
+ struct yasl_private_popup_spec valid_spec = {
.size = {100, 120},
.anchor = {30, 40, 50, 60},
.beside = false,
@@ -78,12 +86,40 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
};
assert(popup_spec_valid(s, &valid_spec));
int x = 0, y = 0;
- popup_calculate_position(d, s, &valid_spec, &x, &y);
+ struct yasl_private_vector2i actual_size;
+ popup_calculate_position(d, s, &valid_spec, &x, &y, &actual_size);
assert(x == 30 - 5);
assert(y == 40 + 60 - 10);
+ /* Explicit XDG-style anchor/gravity stays exact unless a constraint allows a fit. */
+ struct yasl_private_popup_spec positioned = {
+ .positioner_explicit = true,
+ .anchor_edges = 2, /* bottom */
+ .gravity = 2, /* below */
+ .size = {100, 120}, .anchor = {100, 100, 40, 20},
+ .content_offset = {5, 10},
+ };
+ popup_calculate_position(d, s, &positioned, &x, &y, &actual_size);
+ assert(x == 68 && y == 110 && actual_size.x == 100 && actual_size.y == 120);
+ positioned.anchor_edges = 4; /* right edge */
+ positioned.gravity = 4; /* to the right */
+ positioned.anchor = (struct yasl_private_rect2i){1900, 100, 20, 20};
+ positioned.constraints = 4; /* flip X */
+ popup_calculate_position(d, s, &positioned, &x, &y, &actual_size);
+ assert(x == 1800 && actual_size.x == 100);
+ positioned.gravity = 0;
+ positioned.constraints = 1; /* slide X */
+ popup_calculate_position(d, s, &positioned, &x, &y, &actual_size);
+ assert(x + actual_size.x == 1920);
+ positioned.content_offset = (struct yasl_private_vector2i){0, 0};
+ positioned.gravity = 4;
+ positioned.constraints = 16; /* resize X */
+ positioned.anchor = (struct yasl_private_rect2i){1880, 100, 20, 20};
+ popup_calculate_position(d, s, &positioned, &x, &y, &actual_size);
+ assert(x == 1920 - actual_size.x && actual_size.x == 20);
+
valid_spec.beside = true;
- popup_calculate_position(d, s, &valid_spec, &x, &y);
+ popup_calculate_position(d, s, &valid_spec, &x, &y, &actual_size);
assert(x == 30 + 50 - 5);
assert(y == 40 - 10);
@@ -94,7 +130,7 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
assert(popup->parent == s);
assert(popup->size.x == 100 && popup->size.y == 120);
- struct yasl_popup_spec repo_spec = {
+ struct yasl_private_popup_spec repo_spec = {
.size = {150, 180},
.anchor = {10, 20, 30, 40},
.beside = false,
@@ -113,24 +149,24 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
struct drag_test_recorder rec1 = {0};
struct drag_test_recorder rec2 = {0};
- struct yasl_window_cbs cbs1 = {.drag = on_test_drag};
- struct yasl_window_cbs cbs2 = {.drag = on_test_drag};
+ struct yasl_private_window_cbs cbs1 = {.drag = on_test_drag};
+ struct yasl_private_window_cbs cbs2 = {.drag = on_test_drag};
set_callbacks(&s->base, &cbs1, &rec1);
set_callbacks(&s2.base, &cbs2, &rec2);
- enum yasl_drag_end end_reason = (enum yasl_drag_end)-1;
- struct yasl_drag_listener l = {.end = on_test_drag_end};
+ enum yasl_private_drag_end end_reason = (enum yasl_private_drag_end)-1;
+ struct yasl_private_drag_listener l = {.end = on_test_drag_end};
assert(drag_start(&d->base, &s->base, NULL, &l, &end_reason));
assert(d->drag.active);
- /* Motion on s (window 42) -> YASL_DRAG_OVER on s */
+ /* Motion on s (window 42) -> YASL_PRIVATE_DRAG_OVER on s */
XIDeviceEvent mev = {.evtype = XI_Motion, .sourceid = 8, .event = 42, .event_x = 12.0, .event_y = 34.0};
XGenericEventCookie cookie = {.evtype = XI_Motion, .data = &mev};
xi_event(d, &cookie);
assert(rec1.over_count == 1);
assert(rec1.last_pos.x == 12 && rec1.last_pos.y == 34);
- /* Motion on s2 (window 43) -> YASL_DRAG_LEAVE on s, YASL_DRAG_OVER on s2 */
+ /* Motion on s2 (window 43) -> YASL_PRIVATE_DRAG_LEAVE on s, YASL_PRIVATE_DRAG_OVER on s2 */
mev.event = 43;
mev.event_x = 56.0;
mev.event_y = 78.0;
@@ -139,12 +175,12 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
assert(rec2.over_count == 1);
assert(rec2.last_pos.x == 56 && rec2.last_pos.y == 78);
- /* ButtonRelease -> YASL_DRAG_DROP on s2 and drag end */
+ /* ButtonRelease -> YASL_PRIVATE_DRAG_DROP on s2 and drag end */
XIDeviceEvent rel = {.evtype = XI_ButtonRelease, .sourceid = 8, .event = 43, .detail = 1};
cookie = (XGenericEventCookie){.evtype = XI_ButtonRelease, .data = &rel};
xi_event(d, &cookie);
assert(rec2.drop_count == 1);
- assert(end_reason == YASL_DRAG_DROPPED);
+ assert(end_reason == YASL_PRIVATE_DRAG_DROPPED);
assert(!d->drag.active);
/* Drag cancel */
@@ -155,7 +191,7 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
assert(rec1.over_count == 2);
drag_cancel(&d->base);
assert(rec1.leave_count == 2);
- assert(end_reason == YASL_DRAG_CANCELLED);
+ assert(end_reason == YASL_PRIVATE_DRAG_CANCELLED);
assert(!d->drag.active);
/* Hierarchy change cancels drag and pushes reset */
@@ -164,18 +200,18 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
XIHierarchyEvent hiev = {.evtype = XI_HierarchyChanged, .flags = XISlaveRemoved};
cookie = (XGenericEventCookie){.evtype = XI_HierarchyChanged, .data = &hiev};
xi_event(d, &cookie);
- assert(end_reason == YASL_DRAG_CANCELLED);
+ assert(end_reason == YASL_PRIVATE_DRAG_CANCELLED);
assert(!d->drag.active);
- struct yasl_event reset_ev;
- assert(yasl_surface_poll_event(&s->base, &reset_ev));
- assert(reset_ev.type == YASL_EVENT_INPUT_RESET);
+ struct yasl_private_event reset_ev;
+ assert(yasl_private_surface_poll_event(&s->base, &reset_ev));
+ assert(reset_ev.type == YASL_PRIVATE_EVENT_INPUT_RESET);
/* 4. Drag image parameter */
uint32_t pixels[16] = {0xFF00FF00};
- struct yasl_drag_image img = {.pixels = pixels, .size = {4, 4}, .hotspot = {2, 2}};
+ struct yasl_private_drag_image img = {.pixels = pixels, .size = {4, 4}, .hotspot = {2, 2}};
assert(drag_start(&d->base, &s->base, &img, &l, &end_reason));
assert(d->drag.active);
- assert(drag_carry(&s->base, (struct yasl_vector2i){10, 10}));
+ assert(drag_carry(&s->base, (struct yasl_private_vector2i){10, 10}));
drag_cancel(&d->base);
/* 5. XDND drop-target events and URI parsing */
@@ -246,11 +282,11 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
assert(drec.leave_count == 2);
assert(d->pending_drop.active);
- /* Push YASL_EVENT_DROP */
- push(s, (struct yasl_event){.type = YASL_EVENT_DROP}, "file:///sample.png\r\n", 20);
- struct yasl_event drop_ev;
- assert(yasl_surface_poll_event(&s->base, &drop_ev));
- assert(drop_ev.type == YASL_EVENT_DROP);
+ /* Push YASL_PRIVATE_EVENT_DROP */
+ push(s, (struct yasl_private_event){.type = YASL_PRIVATE_EVENT_DROP}, "file:///sample.png\r\n", 20);
+ struct yasl_private_event drop_ev;
+ assert(yasl_private_surface_poll_event(&s->base, &drop_ev));
+ assert(drop_ev.type == YASL_PRIVATE_EVENT_DROP);
assert(drop_ev.text.len == 20);
assert(!strcmp(drop_ev.text.data, "file:///sample.png\r\n"));
@@ -262,10 +298,18 @@ static void test_x11_gaps(struct x11_display *d, struct x11_surface *s)
int main(void)
{
+ /* External GPU surfaces retain geometry without allocating CPU targets. */
+ struct x11_surface external = {0};
+ external.base.presenter = YASL_PRIVATE_PRESENTER_NONE;
+ assert(resize(&external, (struct yasl_private_vector2i){640, 480}));
+ assert(external.size.x == 640 && external.size.y == 480 && !external.image && !external.pixels);
+
struct x11_display display = {
- .base.ops = &yasl_x11_backend, .abs_pressure = 10, .abs_tilt_x = 11, .abs_tilt_y = 12,
+ .base.ops = &yasl_private_x11_backend, .abs_pressure = 10, .abs_tilt_x = 11, .abs_tilt_y = 12,
};
- struct x11_surface surface = {.base.display = &display.base, .window = 42};
+ struct x11_surface surface = {.base = {.display = &display.base,
+ .creation_flags = YASL_PRIVATE_SURFACE_CPU,
+ .presenter = YASL_PRIVATE_PRESENTER_CPU}, .window = 42};
display.surfaces = &surface;
XIValuatorClassInfo pressure = {.type = XIValuatorClass, .number = 2,
.label = 10, .min = 100, .max = 1100, .mode = XIModeAbsolute};
@@ -277,7 +321,7 @@ int main(void)
XIDeviceInfo info = {.deviceid = 8, .name = "Tablet pen", .num_classes = 3, .classes = classes};
struct x11_pointer pointer = {0};
pointer_info(&display, &pointer, &info);
- assert(pointer.device == YASL_PTR_DEV_PEN);
+ assert(pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
display.pointers = &pointer; /* Cache avoids requiring a real X server. */
unsigned char mask[1] = {0};
@@ -290,9 +334,15 @@ int main(void)
.mods.effective = ShiftMask, .valuators = {sizeof(mask), mask, values}};
XGenericEventCookie cookie = {.evtype = XI_ButtonPress, .data = &sample};
xi_event(&display, &cookie);
- struct yasl_event ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_DOWN && ev.pointer.button == YASL_BUTTON_PRIMARY && ev.pointer.device == YASL_PTR_DEV_PEN);
- assert(ev.pointer.pos.x == 201 && ev.pointer.pos.y == 175 && ev.pointer.mods == YASL_MOD_SHIFT);
+ struct yasl_private_event ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_PEN && ev.pen.device_id == 8 && !ev.pen.tool_id);
+ assert(ev.pen.tool == 1 && ev.pen.action == YASL_PRIVATE_PEN_DOWN && ev.pen.in_contact);
+ assert((ev.pen.axes_valid & (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT)) ==
+ (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT));
+ assert(ev.pen.axes_changed == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT));
+ ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_DOWN && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
+ assert(ev.pointer.pos.x == 201 && ev.pointer.pos.y == 175 && ev.pointer.mods == YASL_PRIVATE_MOD_SHIFT);
assert(ev.pointer.pen.pressure == 32768 && ev.pointer.pen.tilt_x == -35 && ev.pointer.pen.tilt_y == 42);
/* XI2 sends only changed axes, with values packed in mask order. */
@@ -302,36 +352,48 @@ int main(void)
sample.evtype = cookie.evtype = XI_Motion;
xi_event(&display, &cookie);
ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
+ assert(ev.type == YASL_PRIVATE_EVENT_PEN && ev.pen.action == YASL_PRIVATE_PEN_MOVE &&
+ ev.pen.axes_valid == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT) &&
+ ev.pen.axes_changed == YASL_PRIVATE_PEN_PRESSURE && ev.pen.pressure == 1.0);
+ ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
assert(ev.pointer.pen.tilt_x == -35 && ev.pointer.pen.tilt_y == 42);
values[0] = 5000;
xi_event(&display, &cookie);
+ assert(next(&surface).type == YASL_PRIVATE_EVENT_PEN);
assert(next(&surface).pointer.pen.pressure == 65535);
values[0] = -50;
xi_event(&display, &cookie);
+ assert(next(&surface).type == YASL_PRIVATE_EVENT_PEN);
assert(next(&surface).pointer.pen.pressure == 0);
info.name = "Tablet ERASER";
pointer_info(&display, &pointer, &info);
- assert(pointer.device == YASL_PTR_DEV_ERASER);
+ assert(pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
values[0] = 900;
sample.evtype = cookie.evtype = XI_ButtonPress;
xi_event(&display, &cookie);
ev = next(&surface);
- assert(ev.pointer.device == YASL_PTR_DEV_ERASER && ev.pointer.pen.pressure > 0);
+ assert(ev.type == YASL_PRIVATE_EVENT_PEN && ev.pen.tool == 2 && ev.pen.action == YASL_PRIVATE_PEN_DOWN);
+ ev = next(&surface);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && ev.pointer.pen.pressure > 0);
/* Release must clear pressure even when the driver omits that valuator. */
sample.valuators.mask_len = 0;
sample.evtype = cookie.evtype = XI_ButtonRelease;
xi_event(&display, &cookie);
ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_UP && ev.pointer.button == YASL_BUTTON_PRIMARY && ev.pointer.pen.pressure == 0);
- assert(ev.pointer.device == YASL_PTR_DEV_ERASER);
+ assert(ev.type == YASL_PRIVATE_EVENT_PEN && ev.pen.action == YASL_PRIVATE_PEN_UP && !ev.pen.in_contact);
+ ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_UP && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && ev.pointer.pen.pressure == 0);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
XIEnterEvent crossing = {.sourceid = 8, .event = 42, .event_x = 200, .event_y = 175};
cookie = (XGenericEventCookie){.evtype = XI_Leave, .data = &crossing};
xi_event(&display, &cookie);
ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
+ assert(ev.type == YASL_PRIVATE_EVENT_PEN && ev.pen.action == YASL_PRIVATE_PEN_LEAVE);
+ ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
/* No tablet axes must produce an ordinary, pressure-free mouse. */
info.num_classes = 0;
@@ -340,24 +402,48 @@ int main(void)
sample.detail = 3;
xi_pointer_event(&surface, &sample);
ev = next(&surface);
- assert(ev.pointer.device == YASL_PTR_DEV_MOUSE && ev.pointer.button == YASL_BUTTON_SECONDARY && ev.pointer.pen.pressure == 0);
+ assert(ev.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE && ev.pointer.button == YASL_PRIVATE_BUTTON_SECONDARY && ev.pointer.pen.pressure == 0);
for (int button = 4; button <= 7; button++) {
sample.detail = button;
sample.evtype = XI_ButtonPress;
xi_pointer_event(&surface, &sample);
ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_SCROLL);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL);
assert(ev.pointer.scroll.x == (button == 6 ? -1 : button == 7 ? 1 : 0));
assert(ev.pointer.scroll.y == (button == 4 ? -1 : button == 5 ? 1 : 0));
+ assert(ev.pointer.scroll_valid == 1u && ev.pointer.scroll_source == 1u && ev.pointer.scroll_phase == 2u);
sample.evtype = XI_ButtonRelease;
xi_pointer_event(&surface, &sample);
- struct yasl_event unused;
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ struct yasl_private_event unused;
+ assert(!input_queue_pop(&surface.input, &unused));
}
+ /* XI2 smooth-scroll valuators preserve fractional line data and source. */
+ XIValuatorClassInfo scroll_valuator = {.type = XIValuatorClass, .number = 9,
+ .value = 0, .mode = XIModeRelative};
+ XIScrollClassInfo scroll_class = {.type = XIScrollClass, .number = 9,
+ .scroll_type = XIScrollTypeVertical, .increment = 2.0};
+ XIAnyClassInfo *scroll_classes[] = {(void *)&scroll_valuator, (void *)&scroll_class};
+ info.name = "Test touchpad";
+ info.num_classes = 2;
+ info.classes = scroll_classes;
+ struct x11_pointer touchpad = {0};
+ pointer_info(&display, &touchpad, &info);
+ display.pointers = &touchpad;
+ unsigned char scroll_mask[2] = {0};
+ XISetMask(scroll_mask, 9);
+ double scroll_value[] = {-1.0};
+ sample.evtype = XI_Motion;
+ sample.valuators = (XIValuatorState){sizeof(scroll_mask), scroll_mask, scroll_value};
+ xi_pointer_event(&surface, &sample);
+ assert(next(&surface).type == YASL_PRIVATE_EVENT_POINTER_MOTION);
+ ev = next(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL && ev.pointer.scroll_valid == 1u &&
+ ev.pointer.scroll_source == 2u && ev.pointer.scroll.y == -0.5);
+ input_queue_clear(&surface.input);
assert(pointer_button(2) == 1 && pointer_button(8) == 3);
- pointer.pressure = (struct tablet_axis){2, 1, 1, 50};
+ pointer.pressure = (struct tablet_axis){2, 1, 1, 50, true};
assert(pressure_value(&pointer.pressure) == 0);
- pointer.tilt_x = (struct tablet_axis){4, -90, 90, -200};
+ pointer.tilt_x = (struct tablet_axis){4, -90, 90, -200, true};
assert(tilt_value(&pointer.tilt_x) == -90);
pointer.tilt_x.value = 200;
assert(tilt_value(&pointer.tilt_x) == 90);
diff --git a/tests/x11/test_tablet_native.c b/tests/x11/test_tablet_native.c
index 706a5cc..828082c 100644
--- a/tests/x11/test_tablet_native.c
+++ b/tests/x11/test_tablet_native.c
@@ -2,7 +2,7 @@
#define main tablet_example_main
#include "../../examples/tablet.c"
#undef main
-#include <yasl/native.h>
+#include <common/private_native.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -55,24 +55,24 @@ static int connect_tool(const char *path)
return fd;
}
-static void native_draw(struct yasl_surface *surface, struct yasl_frame *frame, void *ud)
+static void native_draw(struct yasl_surface *surface, struct yasl_private_frame *frame, void *ud)
{
(void)surface;
draw(ud, surface, frame);
}
-static void native_configure(struct yasl_surface *surface, struct yasl_geometry geometry, void *ud)
+static void native_configure(struct yasl_surface *surface, struct yasl_private_geometry geometry, void *ud)
{
- input(ud, &(struct yasl_event){.surface = surface, .type = YASL_EVENT_WINDOW_RESIZE,
+ input(ud, &(struct yasl_private_event){.surface = surface, .type = YASL_PRIVATE_EVENT_WINDOW_RESIZE,
.resize = {.geometry = geometry}});
}
-static void native_input(struct app *app, const struct yasl_event *event)
+static void native_input(struct app *app, const struct yasl_private_event *event)
{
input(app, event);
}
-static void pump(int fd, struct yasl_display *display, struct yasl_surface *surface, struct app *app)
+static void pump(int fd, struct yasl_private_display *display, struct yasl_surface *surface, struct app *app)
{
xf86ITEventWaitForSync sync = {{sizeof(sync), XF86IT_EVENT_WAIT_FOR_SYNC}};
send_all(fd, &sync, sizeof(sync));
@@ -81,14 +81,14 @@ static void pump(int fd, struct yasl_display *display, struct yasl_surface *surf
assert(response.type == XF86IT_RESPONSE_SYNC_FINISHED && response.length == sizeof(response));
/* The driver acknowledgment guarantees input processing has finished.
* Round-trip on YASL's X connection before draining its event queue. */
- XSync(yasl_display_get_native_handle(display), False);
- assert(yasl_display_dispatch(display, 0) == 0);
- struct yasl_event event;
- while (yasl_surface_poll_event(surface, &event)) {
+ XSync(yasl_private_display_get_native_handle(display), False);
+ assert(yasl_private_display_dispatch(display, 0) == 0);
+ struct yasl_private_event event;
+ while (yasl_private_surface_poll_event(surface, &event)) {
native_input(app, &event);
- yasl_surface_schedule_redraw(surface);
+ yasl_private_surface_schedule_redraw(surface);
}
- yasl_display_flush(display);
+ yasl_private_display_flush(display);
assert(!app->failed);
}
@@ -116,23 +116,23 @@ static void set_eraser_property(Display *display)
int main(int argc, char **argv)
{
assert(argc == 3); /* pen socket, eraser socket */
- struct app app = {.tablet_supported = true, .backend = YASL_BACKEND_X11};
- struct yasl_display_spec ds = {.backend = YASL_BACKEND_X11};
- struct yasl_display *display = yasl_display_open(NULL, &ds);
- assert(display && (yasl_display_caps(display) & YASL_CAP_TABLET));
- struct yasl_window_spec ss = {.title = "YASL native pressure test", .size = {500, 400}};
- struct yasl_surface *surface = yasl_surface_create_toplevel(display, &ss);
+ struct app app = {.tablet_supported = true, .backend = YASL_PRIVATE_BACKEND_X11};
+ struct yasl_private_display_spec ds = {.backend = YASL_PRIVATE_BACKEND_X11};
+ struct yasl_private_display *display = yasl_private_display_open(NULL, &ds);
+ assert(display && (yasl_private_display_caps(display) & YASL_PRIVATE_CAP_TABLET));
+ struct yasl_private_window_spec ss = {.title = "YASL native pressure test", .size = {500, 400}};
+ struct yasl_surface *surface = yasl_private_surface_create_toplevel(display, &ss);
assert(surface);
- struct yasl_window_cbs cbs = {.draw = native_draw, .configure = native_configure};
- yasl_surface_set_callbacks(surface, &cbs, &app);
- yasl_surface_schedule_redraw(surface);
- Display *x = yasl_display_get_native_handle(display);
- Window window = (Window)(uintptr_t)yasl_surface_get_native_handle(surface);
+ struct yasl_private_window_cbs cbs = {.draw = native_draw, .configure = native_configure};
+ yasl_private_surface_set_callbacks(surface, &cbs, &app);
+ yasl_private_surface_schedule_redraw(surface);
+ Display *x = yasl_private_display_get_native_handle(display);
+ Window window = (Window)(uintptr_t)yasl_private_surface_get_native_handle(surface);
XMoveWindow(x, window, 0, 0);
XSetInputFocus(x, window, RevertToParent, CurrentTime);
XSync(x, False);
- assert(yasl_display_dispatch(display, 0) == 0);
- yasl_display_flush(display);
+ assert(yasl_private_display_dispatch(display, 0) == 0);
+ yasl_private_display_flush(display);
set_eraser_property(x);
int pen_fd = connect_tool(argv[1]), eraser_fd = connect_tool(argv[2]);
xf86ITEventMotion motion = {.header = {sizeof(motion), XF86IT_EVENT_MOTION}, .is_absolute = 1};
@@ -144,7 +144,7 @@ int main(int argc, char **argv)
send_all(pen_fd, &proximity, sizeof(proximity));
send_all(pen_fd, &motion, sizeof(motion));
pump(pen_fd, display, surface, &app);
- assert(app.visible && !app.down && app.pointer.device == YASL_PTR_DEV_PEN);
+ assert(app.visible && !app.down && app.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
assert(app.pointer.pos.x == 150 && app.pointer.pos.y == 200);
assert(app.canvas[(size_t)200 * app.geometry.size.x + 150] == PAPER);
xf86ITEventButton button = {.header = {sizeof(button), XF86IT_EVENT_BUTTON},
@@ -177,7 +177,7 @@ int main(int argc, char **argv)
button.valuators.valuators[4] = 1000;
send_all(eraser_fd, &button, sizeof(button));
pump(eraser_fd, display, surface, &app);
- assert(app.down && app.pointer.device == YASL_PTR_DEV_ERASER && app.pointer.pen.pressure == 65535);
+ assert(app.down && app.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && app.pointer.pen.pressure == 65535);
assert(app.canvas[(size_t)200 * app.geometry.size.x + 150] == PAPER &&
app.canvas[(size_t)200 * app.geometry.size.x + 170] == PAPER);
button.is_press = 0;
@@ -187,8 +187,8 @@ int main(int argc, char **argv)
close(pen_fd);
close(eraser_fd);
free(app.canvas);
- yasl_surface_destroy(surface);
- yasl_display_close(display);
+ yasl_private_surface_destroy(surface);
+ yasl_private_display_close(display);
puts("Native Xorg pen pressure, stationary pressure, release, and eraser drawing passed.");
return 0;
}