summaryrefslogtreecommitdiff
path: root/tests/x11
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 22:12:02 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 22:12:02 +0300
commit94c5e361fbb229b0cd6853e2102a7d95f1f358b3 (patch)
tree3c0f11af9dcb84dac8067a31a6979acd6dd56fbf /tests/x11
parent08dc9047098d6d96791024ac7d8f5837633673ef (diff)
better public interface and doxygen
Diffstat (limited to 'tests/x11')
-rw-r--r--tests/x11/test_input.c123
-rw-r--r--tests/x11/test_tablet.c13
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);