From cd2ab1c4b6423c8a56c58ddeb48a31ff7f3b9ff9 Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 31 May 2026 10:42:55 +0300 Subject: [PATCH] ui: platform-neutral Keycode enum; map SDL keycodes once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KeyData.key was a raw u32 carrying SDL_Keycode values, so app code had to reinterpret it as SDL_Keycode (xx e.key) — a leaky, unchecked cross-platform cast only valid because the backend happened to be SDL. Add a neutral Keycode enum; translate_sdl_event maps SDL_Keycode to it via keycode_from_sdl. App code compares e.key == .escape with no platform type and no cast; a new backend maps its own native codes in one place. --- library/modules/ui/events.sx | 43 +++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/library/modules/ui/events.sx b/library/modules/ui/events.sx index 81b40ed..bef218a 100755 --- a/library/modules/ui/events.sx +++ b/library/modules/ui/events.sx @@ -12,7 +12,24 @@ MouseButton :: enum { MouseButtonData :: struct { position: Point; button: MouseButton; } MouseMotionData :: struct { position: Point; delta: Point; } MouseWheelData :: struct { position: Point; delta: Point; } -KeyData :: struct { key: u32; } + +// Platform-neutral keycode. Each backend translates its native codes to this +// (see `keycode_from_sdl`), so app code never depends on a platform key enum. +Keycode :: enum { + unknown; + escape; + enter; + space; + tab; + backspace; + delete; + left; + right; + up; + down; +} + +KeyData :: struct { key: Keycode; } ResizeData :: struct { size: Size; } Event :: enum { @@ -38,6 +55,26 @@ event_position :: (e: *Event) -> ?Point { null; } +// Map a platform (SDL) keycode to the neutral `Keycode`. Only the keys the app +// consumes are mapped; everything else is `.unknown`. Letters/digits arrive via +// `text_input`, not here. +// TODO: extend as more keys are needed. +keycode_from_sdl :: (k: SDL_Keycode) -> Keycode { + if k == { + case .escape: return .escape; + case .return_key: return .enter; + case .space: return .space; + case .tab: return .tab; + case .backspace: return .backspace; + case .delete_key: return .delete; + case .left: return .left; + case .right: return .right; + case .up: return .up; + case .down: return .down; + } + .unknown; +} + // Translate SDL_Event → our Event type translate_sdl_event :: (sdl: *SDL_Event) -> Event { if sdl.* == { @@ -45,10 +82,10 @@ translate_sdl_event :: (sdl: *SDL_Event) -> Event { return .quit; } case .key_down: (data) { - return .key_down(.{ key = xx data.key }); + return .key_down(.{ key = keycode_from_sdl(data.key) }); } case .key_up: (data) { - return .key_up(.{ key = xx data.key }); + return .key_up(.{ key = keycode_from_sdl(data.key) }); } case .mouse_motion: (data) { return .mouse_moved(.{