#import "modules/std.sx"; #import "modules/ffi/sdl3.sx"; #import "modules/ui/types.sx"; MouseButton :: enum { none; left; middle; right; } MouseButtonData :: struct { position: Point; button: MouseButton; } MouseMotionData :: struct { position: Point; delta: Point; } MouseWheelData :: struct { position: Point; delta: Point; } // 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 { none; quit; mouse_down: MouseButtonData; mouse_up: MouseButtonData; mouse_moved: MouseMotionData; mouse_wheel: MouseWheelData; key_down: KeyData; key_up: KeyData; text_input: string; window_resize: ResizeData; } event_position :: (e: *Event) -> ?Point { if e == { case .mouse_down: (d) { return d.position; } case .mouse_up: (d) { return d.position; } case .mouse_moved: (d) { return d.position; } case .mouse_wheel: (d) { return d.position; } } 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 == { case .quit: { return .quit; } case .key_down: (data) { return .key_down(.{ key = keycode_from_sdl(data.key) }); } case .key_up: (data) { return .key_up(.{ key = keycode_from_sdl(data.key) }); } case .mouse_motion: (data) { return .mouse_moved(.{ position = .{ x = data.x, y = data.y }, delta = .{ x = data.xrel, y = data.yrel } }); } case .mouse_button_down: (data) { btn :MouseButton = if data.button == { case 1: .left; case 2: .middle; case 3: .right; else: .none; }; return .mouse_down(.{ position = .{ x = data.x, y = data.y }, button = btn }); } case .mouse_button_up: (data) { btn :MouseButton = if data.button == { case 1: .left; case 2: .middle; case 3: .right; else: .none; }; return .mouse_up(.{ position = .{ x = data.x, y = data.y }, button = btn }); } case .mouse_wheel: (data) { return .mouse_wheel(.{ position = .{ x = data.mouse_x, y = data.mouse_y }, delta = .{ x = data.x, y = data.y } }); } case .window_resized: (data) { return .window_resize(.{ size = .{ width = xx data.data1, height = xx data.data2 } }); } } .none }