commit d93fb26

uint  ·  2026-06-06 00:52:58 +0000 UTC
parent ce3c902
Decode keycodes to symbols, store on keymap
2 files changed,  +125, -4
+118, -3
  1@@ -1,15 +1,87 @@
  2 #include <stdbool.h>
  3-#include <stdio.h>
  4 #include <stdlib.h>
  5 
  6 #include <X11/Xlib.h>
  7+#include <X11/keysym.h>
  8 
  9 #include "maus.h"
 10 
 11+typedef struct {
 12+	KeySym  x11;
 13+	MausKey maus;
 14+} KeyMapEntry;
 15+
 16+static const KeyMapEntry keymap[] = {
 17+	{ XK_BackSpace,    MAUS_KEY_BACKSPACE }, { XK_Tab,              MAUS_KEY_TAB },
 18+	{ XK_Return,       MAUS_KEY_ENTER },     { XK_Escape,           MAUS_KEY_ESCAPE },
 19+	{ XK_apostrophe,   MAUS_KEY_APOSTROPHE },{ XK_comma,            MAUS_KEY_COMMA },
 20+	{ XK_space,        MAUS_KEY_SPACE },     { XK_minus,            MAUS_KEY_MINUS },
 21+	{ XK_period,       MAUS_KEY_PERIOD },    { XK_slash,            MAUS_KEY_SLASH },
 22+	{ XK_semicolon,    MAUS_KEY_SEMICOLON }, { XK_equal,            MAUS_KEY_EQUAL },
 23+	{ XK_Delete,       MAUS_KEY_DELETE },    { XK_Left,             MAUS_KEY_LEFT },
 24+	{ XK_Right,        MAUS_KEY_RIGHT },     { XK_Up,               MAUS_KEY_UP },
 25+	{ XK_Down,         MAUS_KEY_DOWN },      { XK_Home,             MAUS_KEY_HOME },
 26+	{ XK_End,          MAUS_KEY_END },       { XK_Page_Up,          MAUS_KEY_PAGE_UP },
 27+	{ XK_Page_Down,    MAUS_KEY_PAGE_DOWN }, { XK_Insert,           MAUS_KEY_INSERT },
 28+	{ XK_Shift_L,      MAUS_KEY_SHIFT_L },   { XK_Shift_R,          MAUS_KEY_SHIFT_R },
 29+	{ XK_Control_L,    MAUS_KEY_CONTROL_L }, { XK_Control_R,        MAUS_KEY_CONTROL_R },
 30+	{ XK_Alt_L,        MAUS_KEY_ALT_L },     { XK_Alt_R,            MAUS_KEY_ALT_R },
 31+	{ XK_Super_L,      MAUS_KEY_SUPER_L },   { XK_Super_R,          MAUS_KEY_SUPER_R },
 32+	{ XK_Caps_Lock,    MAUS_KEY_CAPS_LOCK }, { XK_Num_Lock,         MAUS_KEY_NUM_LOCK },
 33+	{ XK_Pause,        MAUS_KEY_PAUSE },     { XK_Menu,             MAUS_KEY_MENU },
 34+	{ XK_KP_Add,       MAUS_KEY_KP_ADD },    { XK_KP_Enter,         MAUS_KEY_KP_ENTER },
 35+	{ XK_bracketright, MAUS_KEY_RIGHT_BRACKET }, { XK_grave,        MAUS_KEY_GRAVE },
 36+	{ XK_Scroll_Lock,  MAUS_KEY_SCROLL_LOCK },   { XK_Print,        MAUS_KEY_PRINT_SCREEN },
 37+	{ XK_KP_Decimal,   MAUS_KEY_KP_DECIMAL },    { XK_KP_Divide,    MAUS_KEY_KP_DIVIDE },
 38+	{ XK_KP_Multiply,  MAUS_KEY_KP_MULTIPLY },   { XK_KP_Subtract,  MAUS_KEY_KP_SUBTRACT },
 39+	{ XK_bracketleft,  MAUS_KEY_LEFT_BRACKET },  { XK_backslash,    MAUS_KEY_BACKSLASH },
 40+	{ XK_KP_Equal,     MAUS_KEY_KP_EQUAL },
 41+};
 42+
 43+static void build_keymap(Maus* mw);
 44 static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw);
 45+static MausKey keysym_to_mauskey(KeySym sym);
 46+
 47+static void build_keymap(Maus* mw)
 48+{
 49+	int min_code = 0;
 50+	int max_code = 0;
 51+	int syms_per_code = 0;
 52+
 53+	/* can be called multiple times during lieftime
 54+	   so initial calloc may not be enough */
 55+	for (int i = 0; i < MAUS_KEYCODE_LAST; i++)
 56+		mw->keymap[i] = MAUS_KEY_NONE;
 57+
 58+	XDisplayKeycodes(mw->display, &min_code, &max_code);
 59+	KeySym* syms = XGetKeyboardMapping(
 60+		mw->display, min_code,
 61+		max_code - min_code + 1, &syms_per_code
 62+	);
 63+	if (!syms)
 64+		return;
 65+	if (syms_per_code <= 0) {
 66+		XFree(syms);
 67+		return;
 68+	}
 69+
 70+	for (int code = min_code; code <= max_code && code < MAUS_KEYCODE_LAST; code++) {
 71+		for (int col = 0; col < syms_per_code; col++) {
 72+			KeySym sym = syms[(code - min_code) * syms_per_code + col];
 73+			mw->keymap[code] = keysym_to_mauskey(sym);
 74+			if (mw->keymap[code] != MAUS_KEY_NONE)
 75+				break;
 76+		}
 77+	}
 78+
 79+	XFree(syms);
 80+}
 81 
 82 static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
 83 {
 84+	uint32_t code = 0;
 85+	MausKey key = MAUS_KEY_NONE;
 86+
 87 	switch (xev->type) {
 88 		case ClientMessage:
 89 			if ((Atom)xev->xclient.data.l[0] == mw->atoms[MAUS_ATOM_WM_DELETE_WINDOW]) {
 90@@ -18,16 +90,35 @@ static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
 91 			}
 92 			break;
 93 
 94+		case MappingNotify:
 95+			XRefreshKeyboardMapping(&xev->xmapping);
 96+			build_keymap(mw);
 97+			break;
 98+
 99 		case KeyPress:
100 			ev->type = MAUS_EV_KEY;
101-			ev->key.code = xev->xkey.keycode;
102+			code = xev->xkey.keycode;
103+			key = code < MAUS_KEYCODE_LAST ? mw->keymap[code] : MAUS_KEY_NONE;
104+			ev->key.code = code;
105+			ev->key.key = key;
106 			ev->key.pressed = true;
107+			if (code < MAUS_KEYCODE_LAST)
108+				mw->key_codes[code] = true;
109+			if (key != MAUS_KEY_NONE)
110+				mw->key_syms[key] = true;
111 			return true;
112 
113 		case KeyRelease:
114 			ev->type = MAUS_EV_KEY;
115-			ev->key.code = xev->xkey.keycode;
116+			code = xev->xkey.keycode;
117+			key = code < MAUS_KEYCODE_LAST ? mw->keymap[code] : MAUS_KEY_NONE;
118+			ev->key.code = code;
119+			ev->key.key = key;
120 			ev->key.pressed = false;
121+			if (code < MAUS_KEYCODE_LAST)
122+				mw->key_codes[code] = false;
123+			if (key != MAUS_KEY_NONE)
124+				mw->key_syms[key] = false;
125 			return true;
126 
127 		case ButtonPress:
128@@ -62,6 +153,28 @@ static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
129 	return false;
130 }
131 
132+static MausKey keysym_to_mauskey(KeySym sym)
133+{
134+	if (sym >= XK_0 && sym <= XK_9)
135+		return MAUS_KEY_0 + (sym - XK_0);
136+	if (sym >= XK_A && sym <= XK_Z)
137+		return MAUS_KEY_A + (sym - XK_A);
138+	if (sym >= XK_a && sym <= XK_z)
139+		return MAUS_KEY_A + (sym - XK_a);
140+	if (sym >= XK_F1 && sym <= XK_F12)
141+		return MAUS_KEY_F1 + (sym - XK_F1);
142+	if (sym >= XK_KP_0 && sym <= XK_KP_9)
143+		return MAUS_KEY_KP_0 + (sym - XK_KP_0);
144+
145+	for (size_t i = 0; i < sizeof(keymap)/ sizeof(keymap[0]); i++) {
146+		if (keymap[i].x11 == sym)
147+			return keymap[i].maus;
148+	}
149+
150+	return MAUS_KEY_NONE;
151+}
152+
153+
154 bool maus_close(Maus* mw)
155 {
156 	if (mw->pixels)
157@@ -145,6 +258,8 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
158 	win->y = y;
159 	win->pixels = px;
160 
161+	build_keymap(win);
162+
163 	return win;
164 }
165 
+7, -1
 1@@ -6,6 +6,10 @@
 2 
 3 #include <X11/Xlib.h>
 4 
 5+#include "maus_keys.h"
 6+
 7+#define MAUS_KEYCODE_LAST 256
 8+
 9 typedef enum {
10 	MAUS_ATOM_WM_DELETE_WINDOW,
11 	MAUS_ATOM_LAST,
12@@ -24,7 +28,9 @@ typedef struct {
13 	int32_t        y;
14 
15 	uint32_t*      pixels;
16-	bool           keys[256];
17+	bool           key_codes[MAUS_KEYCODE_LAST]; /* physical keys */
18+	bool           key_syms[MAUS_KEY_LAST];      /* logical keys */
19+	MausKey        keymap[MAUS_KEYCODE_LAST];    /* X11 keycode->MausKey */
20 } Maus;
21 
22 #endif /* MAUS_X11_H */