diff options
Diffstat (limited to 'tests/common')
| -rw-r--r-- | tests/common/test_backends.c | 495 | ||||
| -rw-r--r-- | tests/common/test_contracts.c | 24 | ||||
| -rw-r--r-- | tests/common/test_events.c | 19 | ||||
| -rw-r--r-- | tests/common/test_surface_integration.c | 20 |
4 files changed, 43 insertions, 515 deletions
diff --git a/tests/common/test_backends.c b/tests/common/test_backends.c deleted file mode 100644 index 7eba57f..0000000 --- a/tests/common/test_backends.c +++ /dev/null @@ -1,495 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include "common/private_native.h" -#if YASL_HAS_WAYLAND -#include "common/private_native_wayland.h" -#endif -#if YASL_HAS_X11 -#include "common/private_native_x11.h" -#endif -#include "common/private_loop.h" -#include "common/types.h" - -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <assert.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/timerfd.h> -#include <time.h> -#include <unistd.h> - -struct window { - struct yasl_surface *surface; - struct yasl_private_display *display; - int draws, configures, closes; - bool destroy_on_draw, destroy_on_configure; -}; - -struct pump { - struct yasl_private_loop *loop; - struct yasl_private_display *displays[2]; - int ticks; -}; - -static int tick(int fd, short events, void *ud) -{ - (void)events; - uint64_t expirations; - assert(read(fd, &expirations, sizeof(expirations)) == sizeof(expirations)); - struct pump *p = ud; - for (int i = 0; i < 2; i++) { - if (p->displays[i]) { - yasl_private_display_dispatch(p->displays[i], 0); - yasl_private_display_flush(p->displays[i]); - } - } - if (--p->ticks == 0) yasl_private_loop_quit(p->loop); - return 0; -} - -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_private_loop_add_fd(loop, timer, POLLIN, tick, &p); - assert(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_private_frame *frame, void *ud) -{ - struct window *w = ud; - assert(s == w->surface); - assert(frame->surface == s); - 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_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_private_damage_list damage = {.n = YASL_PRIVATE_DAMAGE_MAX + 1}; - assert(!yasl_private_surface_present(s, &frame->target, &damage)); - damage.n = -2; - assert(!yasl_private_surface_present(s, &frame->target, &damage)); - damage.n = 1; - damage.rects[0].width = -1; - assert(!yasl_private_surface_present(s, &frame->target, &damage)); - damage.n = -1; - struct yasl_private_framebuffer invalid = frame->target; - invalid.size.x++; - assert(!yasl_private_surface_present(s, &invalid, &damage)); - invalid = frame->target; - invalid.generation--; - assert(!yasl_private_surface_present(s, &invalid, &damage)); - invalid = frame->target; - invalid.pixels = (uint32_t *)(uintptr_t)1; - 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_private_surface_destroy(s); w->surface = NULL; } -} - -static void configure(struct yasl_surface *s, struct yasl_private_geometry geometry, void *ud) -{ - struct window *w = ud; - assert(w->surface == s); - 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_private_surface_geometry(s).scale_120); - w->configures++; - if (w->destroy_on_configure) { yasl_private_surface_destroy(s); w->surface = NULL; } -} - -static void draw_without_present(struct yasl_surface *s, struct yasl_private_frame *frame, void *ud) -{ - (void)s; - struct window *w = ud; - size_t count = (size_t)frame->target.size.x * (size_t)frame->target.size.y; - for (size_t i = 0; i < count; i++) frame->target.pixels[i] = 0xff000000; - w->draws++; -} - -static void close_window(struct yasl_surface *s, void *ud) -{ - struct window *w = ud; - assert(s == w->surface); - w->closes++; - yasl_private_surface_destroy(s); - w->surface = NULL; -} - -static const struct yasl_private_window_cbs callbacks = { - .draw = draw, .configure = configure, .close = close_window, -}; - -static void attach(struct window *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_private_display *d) -{ - 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_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_private_loop *loop, struct yasl_private_display *d, struct window *w) -{ - 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_private_surface_read_pixels(w->surface, pixels, count - 1, &size)); - assert(!pixels[0]); - 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_private_window_cbs skip = callbacks; - skip.draw = draw_without_present; - yasl_private_surface_set_callbacks(w->surface, &skip, w); - for (int i = 0; i < 4; i++) { - yasl_private_surface_schedule_redraw(w->surface); - pump(loop, d, NULL); - 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); - } - } - - attach(w); - yasl_private_surface_schedule_redraw(w->surface); - pump(loop, d, NULL); - memset(pixels, 0, count * sizeof(*pixels)); - 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_private_loop *loop, struct yasl_private_display *d) -{ - struct window w = {.display = d, .destroy_on_draw = true}; - { - 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_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_private_surface_schedule_redraw(w.surface); - pump(loop, d, NULL); - assert(w.draws == 1 && !w.surface); -} - -static void x11_behavior(struct yasl_private_loop *loop, struct yasl_private_display *d, struct window *w) -{ - 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_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_private_surface_set_title(w->surface, "Updated title"); - char *title = NULL; - assert(XFetchName(native, window, &title)); - assert(strcmp(title, "Updated title") == 0); - XFree(title); - XResizeWindow(native, window, 200, 120); - XFlush(native); - pump(loop, d, NULL); - assert(w->configures > 0); - 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_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_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; - } - } - assert(saw_motion); - XEvent key = {0}; - key.xkey = (XKeyEvent){.type = KeyPress, .display = native, .window = window, - .root = DefaultRootWindow(native), .same_screen = True, - .keycode = XKeysymToKeycode(native, XK_a)}; - XSendEvent(native, window, False, KeyPressMask, &key); - XFlush(native); - 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_private_event event; - while (yasl_private_surface_poll_event(w->surface, &event)) { - assert(event.surface == w->surface); - 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_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_PRIVATE_EVENT_TEXT) { - assert(event.text.len == 1 && event.text.data[0] == 'a'); - saw_text = true; - } - } - assert(saw_key && saw_paste && saw_text); - /* Physical identity survives modifier and layout changes, including a - * release whose modifiers differ from its press. */ - key.xkey.state = ShiftMask; - XSendEvent(native, window, False, KeyPressMask, &key); - key.xkey.type = KeyRelease; - key.xkey.state = 0; - XSendEvent(native, window, False, KeyReleaseMask, &key); - XFlush(native); - pump(loop, d, NULL); - int key_count = 0, text_count = 0; - 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_PRIVATE_EVENT_TEXT) { - assert(event.text.len == 1 && event.text.data[0] == 'A'); - text_count++; - } - } - assert(key_count == 2 && text_count == 1); - key.xkey.type = KeyPress; - key.xkey.state = ControlMask; - XSendEvent(native, window, False, KeyPressMask, &key); - XFlush(native); - pump(loop, d, NULL); - 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); - assert(saved_symbols && symbols_per_key >= 2); - KeySym *changed_symbols = calloc((size_t)symbols_per_key, sizeof(KeySym)); - assert(changed_symbols); - changed_symbols[0] = XK_q; - changed_symbols[1] = XK_Q; - XChangeKeyboardMapping(native, key.xkey.keycode, symbols_per_key, changed_symbols, 1); - XSync(native, False); - pump(loop, d, NULL); /* Consume MappingNotify before translating the key. */ - key.xkey.state = 0; - XSendEvent(native, window, False, KeyPressMask, &key); - XFlush(native); - pump(loop, d, NULL); - saw_key = saw_text = false; - 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_PRIVATE_EVENT_TEXT) { - assert(event.text.len == 1 && event.text.data[0] == 'q'); - saw_text = true; - } - } - assert(saw_key && saw_text); - XChangeKeyboardMapping(native, key.xkey.keycode, symbols_per_key, saved_symbols, 1); - free(changed_symbols); - XFree(saved_symbols); - XSync(native, False); - pump(loop, d, NULL); - - for (unsigned button = 4; button <= 7; button++) { - XEvent wheel = {.xbutton = {.type = ButtonPress, .display = native, - .window = window, .root = DefaultRootWindow(native), - .same_screen = True, .button = button}}; - /* Direct delivery exercises the core fallback even with XI2 enabled. */ - XSendEvent(native, window, False, NoEventMask, &wheel); - wheel.xbutton.type = ButtonRelease; - XSendEvent(native, window, False, NoEventMask, &wheel); - XFlush(native); - pump(loop, d, NULL); - 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_private_surface_poll_event(w->surface, &event)); - } - 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_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_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_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_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_private_display_spec ds = {.backend = YASL_PRIVATE_BACKEND_X11}; - struct yasl_private_display *owner = yasl_private_display_open(loop, &ds); - assert(owner); - yasl_private_display_copy(owner, YASL_PRIVATE_CLIPBOARD, "external"); - struct window other = create(d), cancelled = create(d); - 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_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_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_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)}}; - XSendEvent(native, window, False, NoEventMask, &key); - XFlush(native); - pump(loop, d, NULL); - assert(w->closes == 1 && !w->surface); -} - -int main(int argc, char **argv) -{ - assert(argc >= 2); - struct yasl_private_loop *loop = yasl_private_loop_create(); - assert(loop); - if (strcmp(argv[1], "failure") == 0) { - 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_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_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_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_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_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_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_private_surface_schedule_redraw(w.surface); - pump(loop, d, NULL); - assert(w.draws > 0); - test_read_pixels(loop, d, &w); - if (yasl_private_display_backend(d) == YASL_PRIVATE_BACKEND_X11) - x11_behavior(loop, d, &w); - 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_private_display_close(d); - } - 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 be84586..f9f427f 100644 --- a/tests/common/test_contracts.c +++ b/tests/common/test_contracts.c @@ -117,10 +117,10 @@ static bool present(struct yasl_surface *s, const struct yasl_private_framebuffe return true; } 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_private_display *d, enum yasl_private_selection sel, struct yasl_surface *s) -{ (void)d; (void)sel; (void)s; pastes++; } +static bool copy(struct yasl_private_display *d, enum yasl_private_selection sel, const char *text) +{ (void)d; (void)sel; (void)text; copies++; return true; } +static bool paste(struct yasl_private_display *d, enum yasl_private_selection sel, struct yasl_surface *s, uint64_t id) +{ (void)d; (void)sel; (void)s; assert(id); pastes++; return true; } 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; } @@ -260,7 +260,7 @@ static void test_native(void) static void test_validation(void) { const struct yasl_private_backend_ops ops = {.surface_present = present, - .display_caps = caps, .display_copy = copy, .display_paste = paste, + .display_caps = caps, .display_copy_text = copy, .display_request_paste = paste, .surface_create_toplevel = create}; struct yasl_private_display d = {.ops = &ops}; struct yasl_surface s = {.display = &d, .frame_generation = 1}; @@ -293,14 +293,16 @@ static void test_validation(void) assert(yasl_private_surface_present(&s, &fb, &damage) && received.n == -1); damage.n = 0; 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(yasl_private_events_open(&d)); + yasl_private_clipboard_set(&d, YASL_PRIVATE_PRIMARY, "no alias"); + yasl_private_clipboard_set(&d, (enum yasl_private_selection)255, "invalid"); + yasl_private_clipboard_request(&s, YASL_PRIVATE_PRIMARY); + yasl_private_clipboard_request(&s, (enum yasl_private_selection)255); assert(!copies && !pastes); - yasl_private_display_copy(&d, YASL_PRIVATE_CLIPBOARD, "yes"); - yasl_private_display_paste(&d, YASL_PRIVATE_CLIPBOARD, &s); + yasl_private_clipboard_set(&d, YASL_PRIVATE_CLIPBOARD, "yes"); + yasl_private_clipboard_request(&s, YASL_PRIVATE_CLIPBOARD); assert(copies == 1 && pastes == 1); + yasl_private_events_close(&d); 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); diff --git a/tests/common/test_events.c b/tests/common/test_events.c index fcfc118..e9f61da 100644 --- a/tests/common/test_events.c +++ b/tests/common/test_events.c @@ -179,20 +179,23 @@ static void test_failures(void) } -static void test_legacy_poll_does_not_spin(void) +static void test_fifo_preserves_notifications(void) { struct yasl_private_display d; struct yasl_surface a, b; setup(&d, &a, &b); yasl_private_surface_notify_state(&a, YASL_PRIVATE_STATE_ACTIVATED); yasl_private_surface_notify_close(&b); - assert(yasl_private_events_pending(&d)); + yasl_private_surface_notify_composition(&a, "preedit", 0, 7); + assert(input_queue_push(&b.input, &(struct yasl_private_event){ + .type = YASL_PRIVATE_EVENT_PEN, .surface = &b})); + const enum yasl_private_event_type types[] = {YASL_PRIVATE_EVENT_WINDOW_STATE, + YASL_PRIVATE_EVENT_WINDOW_CLOSE, YASL_PRIVATE_EVENT_COMPOSITION, YASL_PRIVATE_EVENT_PEN}; 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); + for (size_t i = 0; i < sizeof(types) / sizeof(*types); ++i) { + assert(yasl_private_display_poll_event(&d, &ev)); + assert(ev.type == types[i] && ev.surface == (i % 2 ? &b : &a)); + } assert(!yasl_private_events_pending(&d)); teardown(&d, &a, &b); } @@ -203,6 +206,6 @@ int main(void) test_post_cleanup(); test_damage(); test_failures(); - test_legacy_poll_does_not_spin(); + test_fifo_preserves_notifications(); return 0; } diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c index 2752208..7cc938a 100644 --- a/tests/common/test_surface_integration.c +++ b/tests/common/test_surface_integration.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include <yasl/yasl.h> #include <yasl/cpu.h> +#include <yasl/gl.h> #include "common/backend.h" #include <assert.h> #include <pthread.h> @@ -8,6 +9,9 @@ #include <string.h> #include <time.h> #include <stdio.h> +#if YASL_HAS_COCOA +void yasl_test_frame_tick(struct yasl_surface *surface); +#endif static void drain(void) { yasl_event e;int n=0; @@ -32,6 +36,15 @@ int main(int argc,char **argv) 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); + if(backend==YASL_BACKEND_COCOA) { + assert(!(yasl_surface_features(s)&YASL_CAP_OPENGL)); + assert(!yasl_gl_surface_create("unsupported GL",64,64,0,NULL,NULL)); + assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + assert(!yasl_gl_make_current(NULL)); + assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + assert(!yasl_gl_get_proc_address("glClear")); + assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + } /* 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++) { @@ -79,7 +92,12 @@ int main(int argc,char **argv) 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); +#if YASL_HAS_COCOA + yasl_test_frame_tick(s); +#endif + uint64_t deadline=yasl_private_loop_now_ns()+3000000000ull; + while(!refreshes && yasl_private_loop_now_ns()<deadline)assert(yasl_wait_event(&e,20)>=0); + assert(refreshes>0); yasl_surface_set_refresh_callback(s,NULL,NULL); yasl_surface_destroy(s); assert(!yasl_set_backend(backend)); |
