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 */