From ae85a3a60af3553ebd07a7b6985de9e2285e7ec3 Mon Sep 17 00:00:00 2001 From: Paul Khuong Date: Sat, 21 Feb 2026 15:36:39 -0500 Subject: [PATCH] Add support for X11 keypresses We convert XKeyEvents to a string, and look for exactly one-byte translations: assume those are 8-bit keycodes. Leave everything else untranslated. I think the KeySym could give us shift/control, if we want that. --- thirteen.h | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/thirteen.h b/thirteen.h index 37ab3db..610025c 100644 --- a/thirteen.h +++ b/thirteen.h @@ -1588,6 +1588,7 @@ namespace Thirteen int (*XStoreName)(Display*, Window, const char*) = nullptr; int (*XPending)(Display*) = nullptr; int (*XNextEvent)(Display*, XEvent*) = nullptr; + int (*XLookupString)(XKeyEvent *, char *, int, KeySym *, XComposeStatus *); int (*XDestroyWindow)(Display*, Window) = nullptr; int (*XCloseDisplay)(Display*) = nullptr; XSizeHints* (*XAllocSizeHints)() = nullptr; @@ -1657,6 +1658,10 @@ namespace Thirteen if (!XNextEvent) return false; + XLookupString = (int(*)(XKeyEvent *, char *, int, KeySym *, XComposeStatus *)) dlsym(x11Library, "XLookupString"); + if (!XLookupString) + return false; + XDestroyWindow = (int(*)(Display*,Window)) dlsym(x11Library, "XDestroyWindow"); if (!XDestroyWindow) return false; @@ -1833,6 +1838,20 @@ namespace Thirteen } } + int remapKeyEvent(XKeyEvent &event) + { + KeySym keysym = 0; + char buf[8] = {}; + int rc = XLookupString(&event, buf, sizeof(buf), &keysym, NULL); + + // rc == number of characters wruitten to `buf`. We expect + // exactly 1 for ASCII characters. + if (rc != 1) + return -1; + + return buf[0]; + } + void PumpMessages() { XEvent event; @@ -1841,14 +1860,17 @@ namespace Thirteen XNextEvent(x11Display, &event); switch (event.type) { - // TODO: these are hardware-dependent, need to unify key codes across platforms case KeyPress: - // if (event.xkey.keycode < 256) - // keys[event.xkey.keycode] = true; + if (int keycode = remapKeyEvent(event.xkey); unsigned(keycode) < 256) + { + keys[keycode] = true; + } break; case KeyRelease: - // if (event.xkey.keycode < 256) - // keys[event.xkey.keycode] = true; + if (int keycode = remapKeyEvent(event.xkey); unsigned(keycode) < 256) + { + keys[keycode] = false; + } break; case ButtonPress: mouseButtons[remapMouseButton(event.xbutton.button)] = true;