diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 22:12:02 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 22:12:02 +0300 |
| commit | 94c5e361fbb229b0cd6853e2102a7d95f1f358b3 (patch) | |
| tree | 3c0f11af9dcb84dac8067a31a6979acd6dd56fbf /tests/x11 | |
| parent | 08dc9047098d6d96791024ac7d8f5837633673ef (diff) | |
better public interface and doxygen
Diffstat (limited to 'tests/x11')
| -rw-r--r-- | tests/x11/test_input.c | 123 | ||||
| -rw-r--r-- | tests/x11/test_tablet.c | 13 |
2 files changed, 136 insertions, 0 deletions
diff --git a/tests/x11/test_input.c b/tests/x11/test_input.c new file mode 100644 index 0000000..11dca4f --- /dev/null +++ b/tests/x11/test_input.c @@ -0,0 +1,123 @@ +/* An isolated real X server supplies the keymap; disabling this surface's XIC + * deliberately exercises text insertion when no input method is available. */ +#include "../../src/x11/window.c" + +static void check_selection_encoding(struct x11_display *d, struct x11_surface *s) +{ + Window requestor = XCreateSimpleWindow(d->native, DefaultRootWindow(d->native), + 0, 0, 1, 1, 0, 0, 0); + Atom property = XInternAtom(d->native, "YASL_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é £"); + selection_request(d, &request); + Atom actual; + int format; + unsigned long count, left; + unsigned char *data = NULL; + assert(XGetWindowProperty(d->native, requestor, property, 0, 100, True, + AnyPropertyType, &actual, &format, &count, &left, &data) == Success); + 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, "字"); + selection_request(d, &request); + assert(XGetWindowProperty(d->native, requestor, property, 0, 100, True, + AnyPropertyType, &actual, &format, &count, &left, &data) == Success); + assert(actual == None); /* Never mislabel UTF-8 as Latin-1. */ + if (data) XFree(data); + request.target = d->targets; + selection_request(d, &request); + assert(XGetWindowProperty(d->native, requestor, property, 0, 100, True, + AnyPropertyType, &actual, &format, &count, &left, &data) == Success); + assert(actual == XA_ATOM && format == 32 && count == 2); + assert(((Atom *)data)[0] == d->targets && ((Atom *)data)[1] == d->utf8); + XFree(data); + XDestroyWindow(d->native, requestor); + + /* Simulate a legacy owner returning STRING to the paste conversion window, + * then an empty UTF-8 owner and malformed UTF-8. */ + const struct { Atom type; const char *bytes; size_t len; const char *expected; } cases[] = { + {XA_STRING, "caf\xe9 \xa3", 6, "café £"}, + {d->utf8, "", 0, ""}, + {d->utf8, "\xff", 1, NULL}, + }; + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct paste_request *pending = calloc(1, sizeof(*pending)); + assert(pending); + pending->window = XCreateSimpleWindow(d->native, DefaultRootWindow(d->native), + 0, 0, 1, 1, 0, 0, 0); + pending->target = s; + pending->next = d->pastes; + d->pastes = pending; + XChangeProperty(d->native, pending->window, property, cases[i].type, 8, + PropModeReplace, (const unsigned char *)cases[i].bytes, (int)cases[i].len); + XSelectionEvent reply = {.requestor = pending->window, .property = property}; + selection_notify(d, &reply); + struct yasl_input_event event; + if (cases[i].expected) { + assert(yasl_surface_input_poll(&s->base, &event)); + assert(event.kind == YASL_INPUT_PASTE); + assert(event.paste.len == strlen(cases[i].expected)); + assert(strcmp(event.paste.text, cases[i].expected) == 0); + } + assert(!yasl_surface_input_poll(&s->base, &event)); + } +} + +int main(void) +{ + struct yasl_display_spec ds = {.backend = YASL_BACKEND_X11}; + struct yasl_display *base = yasl_display_open(NULL, &ds); + assert(base); + struct x11_display *d = (struct x11_display *)base; + struct yasl_surface_spec spec = {.title = "Keyboard fallback", .size = {100, 100}}; + struct yasl_surface *surface = yasl_surface_create_toplevel(base, &spec); + assert(surface); + struct x11_surface *s = (struct x11_surface *)surface; + XIC saved_ic = s->ic; + s->ic = NULL; + unsigned code = XKeysymToKeycode(d->native, XK_a); + int width = 0; + KeySym *saved = XGetKeyboardMapping(d->native, code, 1, &width); + assert(saved && width >= 2); + KeySym *symbols = calloc((size_t)width, sizeof(*symbols)); + assert(symbols); + const struct { KeySym symbol, shifted; const char *text; uint32_t label; } cases[] = { + {XK_eacute, XK_Eacute, "é", 0xe9}, + {0x01000416, 0x01000416, "Ж", 0x416}, + {0x0101f600, 0x0101f600, "😀", 0x1f600}, + }; + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + symbols[0] = cases[i].symbol; + symbols[1] = cases[i].shifted; + XChangeKeyboardMapping(d->native, code, width, symbols, 1); + XSync(d->native, False); + dispatch(base); + input_queue_clear(&s->input); + XKeyEvent native = {.type = KeyPress, .display = d->native, + .window = s->window, .keycode = code}; + key_event(s, &native, false); + struct yasl_input_event event; + assert(yasl_surface_input_poll(surface, &event)); + assert(event.kind == YASL_INPUT_KEY && event.key.key == YASL_KEY_A); + assert(event.key.codepoint == cases[i].label); + assert(yasl_surface_input_poll(surface, &event)); + assert(event.kind == YASL_INPUT_TEXT && event.text.len == strlen(cases[i].text)); + assert(strcmp(event.text.text, cases[i].text) == 0); + assert(!yasl_surface_input_poll(surface, &event)); + native.type = KeyRelease; + key_event(s, &native, false); + assert(yasl_surface_input_poll(surface, &event) && event.kind == YASL_INPUT_KEY); + assert(!yasl_surface_input_poll(surface, &event)); + } + XChangeKeyboardMapping(d->native, code, width, saved, 1); + XSync(d->native, False); + free(symbols); + XFree(saved); + s->ic = saved_ic; + check_selection_encoding(d, s); + yasl_surface_destroy(surface); + yasl_display_close(base); + return 0; +} diff --git a/tests/x11/test_tablet.c b/tests/x11/test_tablet.c index c35a266..ba815cb 100644 --- a/tests/x11/test_tablet.c +++ b/tests/x11/test_tablet.c @@ -341,6 +341,19 @@ int main(void) xi_pointer_event(&surface, &sample); ev = next(&surface); assert(ev.device == YASL_PTR_DEV_MOUSE && ev.button == 2 && ev.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.kind == YASL_PTR_SCROLL); + assert(ev.scroll.x == (button == 6 ? -1 : button == 7 ? 1 : 0)); + assert(ev.scroll.y == (button == 4 ? -1 : button == 5 ? 1 : 0)); + sample.evtype = XI_ButtonRelease; + xi_pointer_event(&surface, &sample); + struct yasl_input_event unused; + assert(!yasl_surface_input_poll(&surface.base, &unused)); + } assert(pointer_button(2) == 1 && pointer_button(8) == 3); pointer.pressure = (struct tablet_axis){2, 1, 1, 50}; assert(pressure_value(&pointer.pressure) == 0); |
