commit 7b9a480

uint  ·  2026-06-23 00:01:18 +0000 UTC
parent 6608b81
Add event polling, event handling, key->mauskey translations
1 files changed,  +208, -0
+208, -0
  1@@ -1,11 +1,43 @@
  2 #include <windows.h>
  3+#include <windowsx.h>
  4 
  5 #include "maus.h"
  6+#include "maus_input.h"
  7 #include "maus_win.h"
  8 
  9+typedef struct {
 10+	UINT    vk;
 11+	MausKey maus;
 12+} KeyMapEntry;
 13+
 14 static bool fb_create(Maus* mw);
 15+static void fb_destroy(Maus* mw);
 16+static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw);
 17+static MausKey vk_to_mauskey(UINT vk);
 18+static UINT resolve_lr(UINT vk, LPARAM lparam);
 19+static char translate_text(UINT vk, UINT scan);
 20 static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
 21 
 22+static const KeyMapEntry keymap[] = {
 23+	{ VK_BACK,     MAUS_KEY_BACKSPACE }, { VK_TAB,      MAUS_KEY_TAB },
 24+	{ VK_RETURN,   MAUS_KEY_ENTER },     { VK_ESCAPE,   MAUS_KEY_ESCAPE },
 25+	{ VK_SPACE,    MAUS_KEY_SPACE },     { VK_DELETE,   MAUS_KEY_DELETE },
 26+	{ VK_LEFT,     MAUS_KEY_LEFT },      { VK_RIGHT,    MAUS_KEY_RIGHT },
 27+	{ VK_UP,       MAUS_KEY_UP },        { VK_DOWN,     MAUS_KEY_DOWN },
 28+	{ VK_HOME,     MAUS_KEY_HOME },      { VK_END,      MAUS_KEY_END },
 29+	{ VK_PRIOR,    MAUS_KEY_PAGE_UP },   { VK_NEXT,     MAUS_KEY_PAGE_DOWN },
 30+	{ VK_INSERT,   MAUS_KEY_INSERT },    { VK_CAPITAL,  MAUS_KEY_CAPS_LOCK },
 31+	{ VK_NUMLOCK,  MAUS_KEY_NUM_LOCK },  { VK_SCROLL,   MAUS_KEY_SCROLL_LOCK },
 32+	{ VK_PAUSE,    MAUS_KEY_PAUSE },     { VK_SNAPSHOT, MAUS_KEY_PRINT_SCREEN },
 33+	{ VK_APPS,     MAUS_KEY_MENU },      { VK_LSHIFT,   MAUS_KEY_SHIFT_L },
 34+	{ VK_RSHIFT,   MAUS_KEY_SHIFT_R },   { VK_LCONTROL, MAUS_KEY_CONTROL_L },
 35+	{ VK_RCONTROL, MAUS_KEY_CONTROL_R }, { VK_LMENU,    MAUS_KEY_ALT_L },
 36+	{ VK_RMENU,    MAUS_KEY_ALT_R },     { VK_LWIN,     MAUS_KEY_SUPER_L },
 37+	{ VK_RWIN,     MAUS_KEY_SUPER_R },   { VK_ADD,      MAUS_KEY_KP_ADD },
 38+	{ VK_SUBTRACT, MAUS_KEY_KP_SUBTRACT },{ VK_MULTIPLY, MAUS_KEY_KP_MULTIPLY },
 39+	{ VK_DIVIDE,   MAUS_KEY_KP_DIVIDE }, { VK_DECIMAL,  MAUS_KEY_KP_DECIMAL },
 40+};
 41+
 42 static bool fb_create(Maus* mw)
 43 {
 44 	MausBackend* be = &mw->backend;
 45@@ -56,6 +88,157 @@ static void fb_destroy(Maus* mw)
 46 	mw->stride = 0;
 47 }
 48 
 49+static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
 50+{
 51+	UINT scan;
 52+	UINT vk;
 53+	int delta;
 54+	MausMouseButton mbtype;
 55+
 56+	switch (msg->message) {
 57+		case WM_QUIT:
 58+			ev->type = MAUS_EV_CLOSE;
 59+			return true;
 60+
 61+		case WM_MOUSEMOVE:
 62+			ev->type = MAUS_EV_MOUSE_MOTION;
 63+			ev->mouse.motion.x = GET_X_LPARAM(msg->lParam);
 64+			ev->mouse.motion.y = GET_Y_LPARAM(msg->lParam);
 65+			return true;
 66+
 67+		case WM_LBUTTONDOWN:
 68+			ev->type = MAUS_EV_MOUSE_BUTTON;
 69+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
 70+			ev->mouse.button.pressed = true;
 71+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = true;
 72+			return true;
 73+		case WM_LBUTTONUP:
 74+			ev->type = MAUS_EV_MOUSE_BUTTON;
 75+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
 76+			ev->mouse.button.pressed = false;
 77+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = false;
 78+			return true;
 79+
 80+		case WM_RBUTTONDOWN:
 81+			ev->type = MAUS_EV_MOUSE_BUTTON;
 82+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
 83+			ev->mouse.button.pressed = true;
 84+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = true;
 85+			return true;
 86+		case WM_RBUTTONUP:
 87+			ev->type = MAUS_EV_MOUSE_BUTTON;
 88+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
 89+			ev->mouse.button.pressed = false;
 90+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = false;
 91+			return true;
 92+
 93+		case WM_MBUTTONDOWN:
 94+			ev->type = MAUS_EV_MOUSE_BUTTON;
 95+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
 96+			ev->mouse.button.pressed = true;
 97+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = true;
 98+			return true;
 99+		case WM_MBUTTONUP:
100+			ev->type = MAUS_EV_MOUSE_BUTTON;
101+			ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
102+			ev->mouse.button.pressed = false;
103+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = false;
104+			return true;
105+
106+		case WM_MOUSEWHEEL:
107+			delta = GET_WHEEL_DELTA_WPARAM(msg->wParam);
108+			mbtype = (delta > 0) ? MAUS_MOUSE_BUTTON_SCROLL_UP
109+			                     : MAUS_MOUSE_BUTTON_SCROLL_DOWN;
110+			ev->type = MAUS_EV_MOUSE_BUTTON;
111+			ev->mouse.button.button = mbtype;
112+			ev->mouse.button.pressed = true;
113+			return true;
114+
115+		case WM_KEYDOWN:
116+		case WM_SYSKEYDOWN:
117+			scan = (UINT)((msg->lParam >> 16) & 0xFF);
118+			vk = resolve_lr((UINT)msg->wParam, msg->lParam);
119+
120+			ev->type = MAUS_EV_KEY;
121+			ev->key.code = (uint32_t)msg->wParam;
122+			ev->key.pressed = true;
123+			ev->key.key = vk_to_mauskey(vk);
124+			ev->key.text = translate_text((UINT)msg->wParam, scan);
125+
126+			if (ev->key.code < MAUS_KEYCODE_LAST)
127+				mw->key_codes[ev->key.code] = true;
128+			if (ev->key.key != MAUS_KEY_NONE)
129+				mw->key_syms[ev->key.key] = true;
130+			return true;
131+
132+		case WM_KEYUP:
133+		case WM_SYSKEYUP:
134+			vk = resolve_lr((UINT)msg->wParam, msg->lParam);
135+
136+			ev->type = MAUS_EV_KEY;
137+			ev->key.code = (uint32_t)msg->wParam;
138+			ev->key.pressed = false;
139+			ev->key.key = vk_to_mauskey(vk);
140+			ev->key.text = 0;
141+
142+			if (ev->key.code < MAUS_KEYCODE_LAST)
143+				mw->key_codes[ev->key.code] = false;
144+			if (ev->key.key != MAUS_KEY_NONE)
145+				mw->key_syms[ev->key.key] = false;
146+			return true;
147+	}
148+
149+	return false;
150+}
151+
152+static MausKey vk_to_mauskey(UINT vk)
153+{
154+	if (vk >= 'A' && vk <= 'Z')
155+		return (MausKey)(MAUS_KEY_A + (vk - 'A'));
156+	if (vk >= '0' && vk <= '9')
157+		return (MausKey)(MAUS_KEY_0 + (vk - '0'));
158+	if (vk >= VK_F1 && vk <= VK_F12)
159+		return (MausKey)(MAUS_KEY_F1 + (vk - VK_F1));
160+	if (vk >= VK_NUMPAD0 && vk <= VK_NUMPAD9)
161+		return (MausKey)(MAUS_KEY_KP_0 + (vk - VK_NUMPAD0));
162+
163+	for (size_t i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++) {
164+		if (keymap[i].vk == vk)
165+			return keymap[i].maus;
166+	}
167+
168+	return MAUS_KEY_NONE;
169+}
170+
171+static UINT resolve_lr(UINT vk, LPARAM lparam)
172+{
173+	UINT scan = (UINT)((lparam >> 16) & 0xFF);
174+	int  ext  = (lparam & (1 << 24)) != 0;
175+
176+	if (vk == VK_SHIFT)
177+		return MapVirtualKey(scan, MAPVK_VSC_TO_VK_EX);
178+	if (vk == VK_CONTROL)
179+		return ext ? VK_RCONTROL : VK_LCONTROL;
180+	if (vk == VK_MENU)
181+		return ext ? VK_RMENU : VK_LMENU;
182+
183+	return vk;
184+}
185+
186+static char translate_text(UINT vk, UINT scan)
187+{
188+	BYTE state[256];
189+	if (!GetKeyboardState(state))
190+		return 0;
191+
192+	WCHAR buf[4];
193+	int n = ToUnicode(vk, scan, state, buf, 4, 0);
194+	if (n == 1 && buf[0] < 0x80)
195+		return (buf[0] == '\r') ? '\n' : (char)buf[0];
196+
197+	return 0;
198+}
199+
200 static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
201 {
202 	if (msg == WM_DESTROY) {
203@@ -158,12 +341,37 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
204 
205 bool maus_event_poll(Maus* mw, MausEvent* ev)
206 {
207+	MSG msg;
208+	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
209+		TranslateMessage(&msg);
210+		DispatchMessage(&msg);
211+		ev->type = MAUS_EV_NONE;
212+
213+		if (handle_event(&msg, ev, mw))
214+			return true;
215+	}
216 
217+	return false;
218 }
219 
220 void maus_event_wait(Maus* mw, MausEvent* ev)
221 {
222+	MSG msg;
223 
224+	for (;;) {
225+		int r = GetMessage(&msg, NULL, 0, 0);
226+		if (r <= 0) {
227+			ev->type = MAUS_EV_CLOSE;
228+			return;
229+		}
230+
231+		TranslateMessage(&msg);
232+		DispatchMessage(&msg);
233+		ev->type = MAUS_EV_NONE;
234+
235+		if (handle_event(&msg, ev, mw))
236+			return;
237+	}
238 }
239 
240 void maus_present(Maus* mw)