diff options
Diffstat (limited to 'tests/wayland/test_app_input.c')
| -rw-r--r-- | tests/wayland/test_app_input.c | 174 |
1 files changed, 60 insertions, 114 deletions
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; } |
