]> git.nega.tv - josh/narcissus/commitdiff
Add basic input events
authorJoshua Simmons <josh@nega.tv>
Sun, 13 Nov 2022 11:04:52 +0000 (12:04 +0100)
committerJoshua Simmons <josh@nega.tv>
Sun, 13 Nov 2022 11:06:01 +0000 (12:06 +0100)
ffi/sdl2-sys/src/lib.rs
narcissus-app/src/button.rs [new file with mode: 0644]
narcissus-app/src/key.rs [new file with mode: 0644]
narcissus-app/src/lib.rs
narcissus-app/src/sdl.rs
narcissus/src/main.rs

index 2e46a1564b31e8760e9d11db78df5b0014d3f3ca..dddb7e8ccbfae7163113725dc25bf70019257343 100644 (file)
@@ -10,9 +10,25 @@ pub type JoystickID = i32;
 pub type TouchID = i64;
 pub type FingerID = i64;
 pub type GestureID = i64;
-pub type Keycode = i32;
 
-#[repr(C)]
+#[repr(u8)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum PressedState {
+    Released = 0,
+    Pressed = 1,
+}
+
+#[repr(u8)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum MouseButton {
+    Left = 1,
+    Middle = 2,
+    Right = 3,
+    X1 = 4,
+    X2 = 5,
+}
+
+#[repr(i32)]
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub enum Scancode {
     UNKNOWN = 0,
@@ -398,12 +414,303 @@ pub enum Scancode {
     NUM_SCANCODES = 512,
 }
 
+const fn keycode_from_scancode(scancode: Scancode) -> i32 {
+    scancode as i32 | 1 << 30
+}
+
+#[repr(i32)]
+#[derive(Clone, Copy)]
+pub enum Keycode {
+    UNKNOWN = 0,
+
+    RETURN = '\r' as i32,
+    ESCAPE = '\x1B' as i32,
+    BACKSPACE = '\x08' as i32,
+    TAB = '\t' as i32,
+    SPACE = ' ' as i32,
+    EXCLAIM = '!' as i32,
+    QUOTEDBL = '"' as i32,
+    HASH = '#' as i32,
+    PERCENT = '%' as i32,
+    DOLLAR = '$' as i32,
+    AMPERSAND = '&' as i32,
+    QUOTE = '\'' as i32,
+    LEFTPAREN = '(' as i32,
+    RIGHTPAREN = ')' as i32,
+    ASTERISK = '*' as i32,
+    PLUS = '+' as i32,
+    COMMA = ',' as i32,
+    MINUS = '-' as i32,
+    PERIOD = '.' as i32,
+    SLASH = '/' as i32,
+    KEY_0 = '0' as i32,
+    KEY_1 = '1' as i32,
+    KEY_2 = '2' as i32,
+    KEY_3 = '3' as i32,
+    KEY_4 = '4' as i32,
+    KEY_5 = '5' as i32,
+    KEY_6 = '6' as i32,
+    KEY_7 = '7' as i32,
+    KEY_8 = '8' as i32,
+    KEY_9 = '9' as i32,
+    COLON = ':' as i32,
+    SEMICOLON = ';' as i32,
+    LESS = '<' as i32,
+    EQUALS = '=' as i32,
+    GREATER = '>' as i32,
+    QUESTION = '?' as i32,
+    AT = '@' as i32,
+
+    /*
+      Skip uppercase letters
+    */
+    LEFTBRACKET = '[' as i32,
+    BACKSLASH = '\\' as i32,
+    RIGHTBRACKET = ']' as i32,
+    CARET = '^' as i32,
+    UNDERSCORE = '_' as i32,
+    BACKQUOTE = '`' as i32,
+    a = 'a' as i32,
+    b = 'b' as i32,
+    c = 'c' as i32,
+    d = 'd' as i32,
+    e = 'e' as i32,
+    f = 'f' as i32,
+    g = 'g' as i32,
+    h = 'h' as i32,
+    i = 'i' as i32,
+    j = 'j' as i32,
+    k = 'k' as i32,
+    l = 'l' as i32,
+    m = 'm' as i32,
+    n = 'n' as i32,
+    o = 'o' as i32,
+    p = 'p' as i32,
+    q = 'q' as i32,
+    r = 'r' as i32,
+    s = 's' as i32,
+    t = 't' as i32,
+    u = 'u' as i32,
+    v = 'v' as i32,
+    w = 'w' as i32,
+    x = 'x' as i32,
+    y = 'y' as i32,
+    z = 'z' as i32,
+
+    CAPSLOCK = keycode_from_scancode(Scancode::CAPSLOCK),
+
+    F1 = keycode_from_scancode(Scancode::F1),
+    F2 = keycode_from_scancode(Scancode::F2),
+    F3 = keycode_from_scancode(Scancode::F3),
+    F4 = keycode_from_scancode(Scancode::F4),
+    F5 = keycode_from_scancode(Scancode::F5),
+    F6 = keycode_from_scancode(Scancode::F6),
+    F7 = keycode_from_scancode(Scancode::F7),
+    F8 = keycode_from_scancode(Scancode::F8),
+    F9 = keycode_from_scancode(Scancode::F9),
+    F10 = keycode_from_scancode(Scancode::F10),
+    F11 = keycode_from_scancode(Scancode::F11),
+    F12 = keycode_from_scancode(Scancode::F12),
+
+    PRINTSCREEN = keycode_from_scancode(Scancode::PRINTSCREEN),
+    SCROLLLOCK = keycode_from_scancode(Scancode::SCROLLLOCK),
+    PAUSE = keycode_from_scancode(Scancode::PAUSE),
+    INSERT = keycode_from_scancode(Scancode::INSERT),
+    HOME = keycode_from_scancode(Scancode::HOME),
+    PAGEUP = keycode_from_scancode(Scancode::PAGEUP),
+    DELETE = '\x7F' as i32,
+    END = keycode_from_scancode(Scancode::END),
+    PAGEDOWN = keycode_from_scancode(Scancode::PAGEDOWN),
+    RIGHT = keycode_from_scancode(Scancode::RIGHT),
+    LEFT = keycode_from_scancode(Scancode::LEFT),
+    DOWN = keycode_from_scancode(Scancode::DOWN),
+    UP = keycode_from_scancode(Scancode::UP),
+
+    NUMLOCKCLEAR = keycode_from_scancode(Scancode::NUMLOCKCLEAR),
+    KP_DIVIDE = keycode_from_scancode(Scancode::KP_DIVIDE),
+    KP_MULTIPLY = keycode_from_scancode(Scancode::KP_MULTIPLY),
+    KP_MINUS = keycode_from_scancode(Scancode::KP_MINUS),
+    KP_PLUS = keycode_from_scancode(Scancode::KP_PLUS),
+    KP_ENTER = keycode_from_scancode(Scancode::KP_ENTER),
+    KP_1 = keycode_from_scancode(Scancode::KP_1),
+    KP_2 = keycode_from_scancode(Scancode::KP_2),
+    KP_3 = keycode_from_scancode(Scancode::KP_3),
+    KP_4 = keycode_from_scancode(Scancode::KP_4),
+    KP_5 = keycode_from_scancode(Scancode::KP_5),
+    KP_6 = keycode_from_scancode(Scancode::KP_6),
+    KP_7 = keycode_from_scancode(Scancode::KP_7),
+    KP_8 = keycode_from_scancode(Scancode::KP_8),
+    KP_9 = keycode_from_scancode(Scancode::KP_9),
+    KP_0 = keycode_from_scancode(Scancode::KP_0),
+    KP_PERIOD = keycode_from_scancode(Scancode::KP_PERIOD),
+
+    APPLICATION = keycode_from_scancode(Scancode::APPLICATION),
+    POWER = keycode_from_scancode(Scancode::POWER),
+    KP_EQUALS = keycode_from_scancode(Scancode::KP_EQUALS),
+    F13 = keycode_from_scancode(Scancode::F13),
+    F14 = keycode_from_scancode(Scancode::F14),
+    F15 = keycode_from_scancode(Scancode::F15),
+    F16 = keycode_from_scancode(Scancode::F16),
+    F17 = keycode_from_scancode(Scancode::F17),
+    F18 = keycode_from_scancode(Scancode::F18),
+    F19 = keycode_from_scancode(Scancode::F19),
+    F20 = keycode_from_scancode(Scancode::F20),
+    F21 = keycode_from_scancode(Scancode::F21),
+    F22 = keycode_from_scancode(Scancode::F22),
+    F23 = keycode_from_scancode(Scancode::F23),
+    F24 = keycode_from_scancode(Scancode::F24),
+    EXECUTE = keycode_from_scancode(Scancode::EXECUTE),
+    HELP = keycode_from_scancode(Scancode::HELP),
+    MENU = keycode_from_scancode(Scancode::MENU),
+    SELECT = keycode_from_scancode(Scancode::SELECT),
+    STOP = keycode_from_scancode(Scancode::STOP),
+    AGAIN = keycode_from_scancode(Scancode::AGAIN),
+    UNDO = keycode_from_scancode(Scancode::UNDO),
+    CUT = keycode_from_scancode(Scancode::CUT),
+    COPY = keycode_from_scancode(Scancode::COPY),
+    PASTE = keycode_from_scancode(Scancode::PASTE),
+    FIND = keycode_from_scancode(Scancode::FIND),
+    MUTE = keycode_from_scancode(Scancode::MUTE),
+    VOLUMEUP = keycode_from_scancode(Scancode::VOLUMEUP),
+    VOLUMEDOWN = keycode_from_scancode(Scancode::VOLUMEDOWN),
+    KP_COMMA = keycode_from_scancode(Scancode::KP_COMMA),
+    KP_EQUALSAS400 = keycode_from_scancode(Scancode::KP_EQUALSAS400),
+
+    ALTERASE = keycode_from_scancode(Scancode::ALTERASE),
+    SYSREQ = keycode_from_scancode(Scancode::SYSREQ),
+    CANCEL = keycode_from_scancode(Scancode::CANCEL),
+    CLEAR = keycode_from_scancode(Scancode::CLEAR),
+    PRIOR = keycode_from_scancode(Scancode::PRIOR),
+    RETURN2 = keycode_from_scancode(Scancode::RETURN2),
+    SEPARATOR = keycode_from_scancode(Scancode::SEPARATOR),
+    OUT = keycode_from_scancode(Scancode::OUT),
+    OPER = keycode_from_scancode(Scancode::OPER),
+    CLEARAGAIN = keycode_from_scancode(Scancode::CLEARAGAIN),
+    CRSEL = keycode_from_scancode(Scancode::CRSEL),
+    EXSEL = keycode_from_scancode(Scancode::EXSEL),
+
+    KP_00 = keycode_from_scancode(Scancode::KP_00),
+    KP_000 = keycode_from_scancode(Scancode::KP_000),
+    THOUSANDSSEPARATOR = keycode_from_scancode(Scancode::THOUSANDSSEPARATOR),
+    DECIMALSEPARATOR = keycode_from_scancode(Scancode::DECIMALSEPARATOR),
+    CURRENCYUNIT = keycode_from_scancode(Scancode::CURRENCYUNIT),
+    CURRENCYSUBUNIT = keycode_from_scancode(Scancode::CURRENCYSUBUNIT),
+    KP_LEFTPAREN = keycode_from_scancode(Scancode::KP_LEFTPAREN),
+    KP_RIGHTPAREN = keycode_from_scancode(Scancode::KP_RIGHTPAREN),
+    KP_LEFTBRACE = keycode_from_scancode(Scancode::KP_LEFTBRACE),
+    KP_RIGHTBRACE = keycode_from_scancode(Scancode::KP_RIGHTBRACE),
+    KP_TAB = keycode_from_scancode(Scancode::KP_TAB),
+    KP_BACKSPACE = keycode_from_scancode(Scancode::KP_BACKSPACE),
+    KP_A = keycode_from_scancode(Scancode::KP_A),
+    KP_B = keycode_from_scancode(Scancode::KP_B),
+    KP_C = keycode_from_scancode(Scancode::KP_C),
+    KP_D = keycode_from_scancode(Scancode::KP_D),
+    KP_E = keycode_from_scancode(Scancode::KP_E),
+    KP_F = keycode_from_scancode(Scancode::KP_F),
+    KP_XOR = keycode_from_scancode(Scancode::KP_XOR),
+    KP_POWER = keycode_from_scancode(Scancode::KP_POWER),
+    KP_PERCENT = keycode_from_scancode(Scancode::KP_PERCENT),
+    KP_LESS = keycode_from_scancode(Scancode::KP_LESS),
+    KP_GREATER = keycode_from_scancode(Scancode::KP_GREATER),
+    KP_AMPERSAND = keycode_from_scancode(Scancode::KP_AMPERSAND),
+    KP_DBLAMPERSAND = keycode_from_scancode(Scancode::KP_DBLAMPERSAND),
+    KP_VERTICALBAR = keycode_from_scancode(Scancode::KP_VERTICALBAR),
+    KP_DBLVERTICALBAR = keycode_from_scancode(Scancode::KP_DBLVERTICALBAR),
+    KP_COLON = keycode_from_scancode(Scancode::KP_COLON),
+    KP_HASH = keycode_from_scancode(Scancode::KP_HASH),
+    KP_SPACE = keycode_from_scancode(Scancode::KP_SPACE),
+    KP_AT = keycode_from_scancode(Scancode::KP_AT),
+    KP_EXCLAM = keycode_from_scancode(Scancode::KP_EXCLAM),
+    KP_MEMSTORE = keycode_from_scancode(Scancode::KP_MEMSTORE),
+    KP_MEMRECALL = keycode_from_scancode(Scancode::KP_MEMRECALL),
+    KP_MEMCLEAR = keycode_from_scancode(Scancode::KP_MEMCLEAR),
+    KP_MEMADD = keycode_from_scancode(Scancode::KP_MEMADD),
+    KP_MEMSUBTRACT = keycode_from_scancode(Scancode::KP_MEMSUBTRACT),
+    KP_MEMMULTIPLY = keycode_from_scancode(Scancode::KP_MEMMULTIPLY),
+    KP_MEMDIVIDE = keycode_from_scancode(Scancode::KP_MEMDIVIDE),
+    KP_PLUSMINUS = keycode_from_scancode(Scancode::KP_PLUSMINUS),
+    KP_CLEAR = keycode_from_scancode(Scancode::KP_CLEAR),
+    KP_CLEARENTRY = keycode_from_scancode(Scancode::KP_CLEARENTRY),
+    KP_BINARY = keycode_from_scancode(Scancode::KP_BINARY),
+    KP_OCTAL = keycode_from_scancode(Scancode::KP_OCTAL),
+    KP_DECIMAL = keycode_from_scancode(Scancode::KP_DECIMAL),
+    KP_HEXADECIMAL = keycode_from_scancode(Scancode::KP_HEXADECIMAL),
+
+    LCTRL = keycode_from_scancode(Scancode::LCTRL),
+    LSHIFT = keycode_from_scancode(Scancode::LSHIFT),
+    LALT = keycode_from_scancode(Scancode::LALT),
+    LGUI = keycode_from_scancode(Scancode::LGUI),
+    RCTRL = keycode_from_scancode(Scancode::RCTRL),
+    RSHIFT = keycode_from_scancode(Scancode::RSHIFT),
+    RALT = keycode_from_scancode(Scancode::RALT),
+    RGUI = keycode_from_scancode(Scancode::RGUI),
+
+    MODE = keycode_from_scancode(Scancode::MODE),
+
+    AUDIONEXT = keycode_from_scancode(Scancode::AUDIONEXT),
+    AUDIOPREV = keycode_from_scancode(Scancode::AUDIOPREV),
+    AUDIOSTOP = keycode_from_scancode(Scancode::AUDIOSTOP),
+    AUDIOPLAY = keycode_from_scancode(Scancode::AUDIOPLAY),
+    AUDIOMUTE = keycode_from_scancode(Scancode::AUDIOMUTE),
+    MEDIASELECT = keycode_from_scancode(Scancode::MEDIASELECT),
+    WWW = keycode_from_scancode(Scancode::WWW),
+    MAIL = keycode_from_scancode(Scancode::MAIL),
+    CALCULATOR = keycode_from_scancode(Scancode::CALCULATOR),
+    COMPUTER = keycode_from_scancode(Scancode::COMPUTER),
+    AC_SEARCH = keycode_from_scancode(Scancode::AC_SEARCH),
+    AC_HOME = keycode_from_scancode(Scancode::AC_HOME),
+    AC_BACK = keycode_from_scancode(Scancode::AC_BACK),
+    AC_FORWARD = keycode_from_scancode(Scancode::AC_FORWARD),
+    AC_STOP = keycode_from_scancode(Scancode::AC_STOP),
+    AC_REFRESH = keycode_from_scancode(Scancode::AC_REFRESH),
+    AC_BOOKMARKS = keycode_from_scancode(Scancode::AC_BOOKMARKS),
+
+    BRIGHTNESSDOWN = keycode_from_scancode(Scancode::BRIGHTNESSDOWN),
+    BRIGHTNESSUP = keycode_from_scancode(Scancode::BRIGHTNESSUP),
+    DISPLAYSWITCH = keycode_from_scancode(Scancode::DISPLAYSWITCH),
+    KBDILLUMTOGGLE = keycode_from_scancode(Scancode::KBDILLUMTOGGLE),
+    KBDILLUMDOWN = keycode_from_scancode(Scancode::KBDILLUMDOWN),
+    KBDILLUMUP = keycode_from_scancode(Scancode::KBDILLUMUP),
+    EJECT = keycode_from_scancode(Scancode::EJECT),
+    SLEEP = keycode_from_scancode(Scancode::SLEEP),
+    APP1 = keycode_from_scancode(Scancode::APP1),
+    APP2 = keycode_from_scancode(Scancode::APP2),
+
+    AUDIOREWIND = keycode_from_scancode(Scancode::AUDIOREWIND),
+    AUDIOFASTFORWARD = keycode_from_scancode(Scancode::AUDIOFASTFORWARD),
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct Keymod(pub u16);
+
+impl Keymod {
+    pub const NONE: Self = Self(0x0000);
+    pub const LSHIFT: Self = Self(0x0001);
+    pub const RSHIFT: Self = Self(0x0002);
+    pub const LCTRL: Self = Self(0x0040);
+    pub const RCTRL: Self = Self(0x0080);
+    pub const LALT: Self = Self(0x0100);
+    pub const RALT: Self = Self(0x0200);
+    pub const LGUI: Self = Self(0x0400);
+    pub const RGUI: Self = Self(0x0800);
+    pub const NUM: Self = Self(0x1000);
+    pub const CAPS: Self = Self(0x2000);
+    pub const MODE: Self = Self(0x4000);
+    pub const SCROLL: Self = Self(0x8000);
+
+    pub const CTRL: Self = Self(Self::LCTRL.0 | Self::RCTRL.0);
+    pub const SHIFT: Self = Self(Self::LSHIFT.0 | Self::RSHIFT.0);
+    pub const ALT: Self = Self(Self::LALT.0 | Self::RALT.0);
+    pub const GUI: Self = Self(Self::LGUI.0 | Self::RGUI.0);
+}
+
 #[repr(C)]
 #[derive(Clone, Copy)]
 pub struct Keysym {
     pub scancode: Scancode,
     pub sym: Keycode,
-    pub modifiers: u16,
+    pub modifiers: Keymod,
     pub _unused: u32,
 }
 
@@ -568,7 +875,7 @@ pub struct KeyboardEvent {
     pub r#type: EventType,
     pub timestamp: u32,
     pub window_id: u32,
-    pub state: u8,
+    pub state: PressedState,
     pub repeat: u8,
     pub _padding2: u8,
     pub _padding3: u8,
@@ -620,8 +927,8 @@ pub struct MouseButtonEvent {
     pub timestamp: u32,
     pub window_id: u32,
     pub which: u32,
-    pub button: u8,
-    pub state: u8,
+    pub button: MouseButton,
+    pub state: PressedState,
     pub clicks: u8,
     pub padding1: u8,
     pub x: i32,
@@ -918,6 +1225,8 @@ extern "C" {
     pub fn SDL_GetWindowID(window: *mut Window) -> u32;
     pub fn SDL_GetWindowFromID(id: u32) -> *mut Window;
 
+    pub fn SDL_GetKeyFromScancode(scancode: Scancode) -> Keycode;
+
     pub fn SDL_PollEvent(event: *mut Event) -> i32;
 
     pub fn SDL_Vulkan_LoadLibrary(path: *const c_char) -> i32;
diff --git a/narcissus-app/src/button.rs b/narcissus-app/src/button.rs
new file mode 100644 (file)
index 0000000..b5e5151
--- /dev/null
@@ -0,0 +1,8 @@
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum Button {
+    Left,
+    Middle,
+    Right,
+    X1,
+    X2,
+}
diff --git a/narcissus-app/src/key.rs b/narcissus-app/src/key.rs
new file mode 100644 (file)
index 0000000..9f01915
--- /dev/null
@@ -0,0 +1,197 @@
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum Key {
+    Unknown,
+
+    A,
+    B,
+    C,
+    D,
+    E,
+    F,
+    G,
+    H,
+    I,
+    J,
+    K,
+    L,
+    M,
+    N,
+    O,
+    P,
+    Q,
+    R,
+    S,
+    T,
+    U,
+    V,
+    W,
+    X,
+    Y,
+    Z,
+
+    Key1,
+    Key2,
+    Key3,
+    Key4,
+    Key5,
+    Key6,
+    Key7,
+    Key8,
+    Key9,
+    Key0,
+
+    Return,
+    Escape,
+    Backspace,
+    Delete,
+    Tab,
+    Space,
+    Minus,
+    Equal,
+    LeftBrace,
+    RightBrace,
+    Backslash,
+    Semicolon,
+    Apostrophe,
+    Grave,
+    Comma,
+    Period,
+    Slash,
+    CapsLock,
+
+    F1,
+    F2,
+    F3,
+    F4,
+    F5,
+    F6,
+    F7,
+    F8,
+    F9,
+    F10,
+    F11,
+    F12,
+    F13,
+    F14,
+    F15,
+    F16,
+    F17,
+    F18,
+    F19,
+    F20,
+    F21,
+    F22,
+    F23,
+    F24,
+
+    ScrollLock,
+    Insert,
+    Home,
+    End,
+    PageUp,
+    PageDown,
+
+    Left,
+    Right,
+    Up,
+    Down,
+
+    NumLock,
+    NumpadDivide,
+    NumpadMultiply,
+    NumpadSubtract,
+    NumpadAdd,
+    NumpadEnter,
+    Numpad1,
+    Numpad2,
+    Numpad3,
+    Numpad4,
+    Numpad5,
+    Numpad6,
+    Numpad7,
+    Numpad8,
+    Numpad9,
+    Numpad0,
+    NumpadPeriod,
+    NumpadEquals,
+    NumpadLeftParen,
+    NumpadRightParen,
+    NumpadPlusMinus,
+    NumpadComma,
+
+    Eject,
+    Stop,
+    Mute,
+    VolumeUp,
+    VolumeDown,
+    Power,
+
+    Compose,
+    Sleep,
+
+    LeftShift,
+    RightShift,
+    LeftControl,
+    RightControl,
+    LeftAlt,
+    RightAlt,
+    LeftMeta,
+    RightMeta,
+
+    Menu,
+    Pause,
+
+    NonUSBackslash,
+    SysReq,
+    Again,
+    Undo,
+    Copy,
+    Paste,
+    Find,
+    Cut,
+    Help,
+    Calculator,
+    AltErase,
+    Cancel,
+
+    BrightnessUp,
+    BrightnessDown,
+
+    SwitchVideoMode,
+
+    KeyboardIlluminationToggle,
+    KeyboardIlluminationDown,
+    KeyboardIlluminationUp,
+
+    App1,
+    App2,
+    WWW,
+    Mail,
+    Computer,
+
+    ACBookmarks,
+    ACBack,
+    ACForward,
+    ACHome,
+    ACRefresh,
+    ACSearch,
+
+    AudioNext,
+    AudioPlay,
+    AudioPrev,
+    AudioStop,
+    AudioRewind,
+    AudioFastForward,
+
+    Language1,
+    Language2,
+    Language3,
+    Language4,
+    Language5,
+
+    International1,
+    International2,
+    International3,
+    International4,
+    International5,
+}
index 1810c050340881ca02458caa832fd941a40f36ad..3f971e5aa36d4e039cc499786620c3a01f1f5775 100644 (file)
@@ -1,8 +1,27 @@
+mod button;
+mod key;
 mod sdl;
 
 use std::ffi::{c_void, CStr};
 
-use narcissus_core::Handle;
+use narcissus_core::{flags_def, Handle};
+
+pub use button::Button;
+pub use key::Key;
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum PressedState {
+    Released,
+    Pressed,
+}
+
+flags_def!(ModifierFlags);
+impl ModifierFlags {
+    pub const ALT: Self = Self(1 << 0);
+    pub const CTRL: Self = Self(1 << 1);
+    pub const SHIFT: Self = Self(1 << 2);
+    pub const META: Self = Self(1 << 3);
+}
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Default, Debug)]
 pub struct Window(Handle);
@@ -23,7 +42,66 @@ pub struct WindowDesc<'a> {
 pub enum Event {
     Unknown,
     Quit,
-    WindowClose(Window),
+
+    KeyPress {
+        window: Window,
+        key: Key,
+        pressed: PressedState,
+        modifiers: ModifierFlags,
+    },
+
+    ButtonPress {
+        window: Window,
+        button: Button,
+        pressed: PressedState,
+    },
+
+    MouseMotion {
+        window: Window,
+        x: i32,
+        y: i32,
+    },
+
+    /// A window has gained mouse focus.
+    MouseEnter {
+        window: Window,
+        x: i32,
+        y: i32,
+    },
+
+    /// A window has lost moust focus.
+    MouseLeave {
+        window: Window,
+        x: i32,
+        y: i32,
+    },
+
+    /// A window has gained keyboard focus.
+    FocusIn {
+        window: Window,
+    },
+
+    /// A window has lost keyboard focus.
+    FocusOut {
+        window: Window,
+    },
+
+    /// The window has been resized.
+    Resize {
+        window: Window,
+        width: u32,
+        height: u32,
+    },
+
+    // The close button has been pressed on the window.
+    Close {
+        window: Window,
+    },
+
+    // The window has been destroyed.
+    Destroy {
+        window: Window,
+    },
 }
 
 pub trait App {
index 385d6d2ec374cdce959de0016ffdcb27976ec66c..c35a1dcc81d41adfdc40098fb1f352858a5a471c 100644 (file)
@@ -5,7 +5,7 @@ use std::{
     os::raw::c_char,
 };
 
-use crate::{App, Event, Window};
+use crate::{App, Button, Event, Key, ModifierFlags, PressedState, Window};
 
 use narcissus_core::{Handle, Mutex, Pool};
 use sdl2_sys as sdl;
@@ -25,6 +25,14 @@ impl SdlApp {
             window_id_to_handle: Mutex::new(HashMap::new()),
         })
     }
+
+    fn window_from_window_id(&self, window_id: u32) -> Window {
+        self.window_id_to_handle
+            .lock()
+            .get(&window_id)
+            .copied()
+            .unwrap_or_else(|| Window(Handle::null()))
+    }
 }
 
 impl Drop for SdlApp {
@@ -131,39 +139,329 @@ impl App for SdlApp {
 
         let event = unsafe { event.assume_init() };
         let e = match unsafe { event.r#type } {
-            sdl2_sys::EventType::QUIT => Event::Quit,
-            sdl2_sys::EventType::WINDOWEVENT => match unsafe { event.window.event } {
+            sdl::EventType::QUIT => Event::Quit,
+            sdl::EventType::WINDOWEVENT => match unsafe { event.window.event } {
                 sdl::WindowEventId::None => Event::Unknown,
                 sdl::WindowEventId::Shown => Event::Unknown,
                 sdl::WindowEventId::Hidden => Event::Unknown,
                 sdl::WindowEventId::Exposed => Event::Unknown,
                 sdl::WindowEventId::Moved => Event::Unknown,
-                sdl::WindowEventId::Resized => Event::Unknown,
+                sdl::WindowEventId::Resized => {
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::Resize {
+                        window: handle,
+                        width: unsafe { event.window.data1 } as u32,
+                        height: unsafe { event.window.data2 } as u32,
+                    }
+                }
                 sdl::WindowEventId::SizeChanged => Event::Unknown,
                 sdl::WindowEventId::Minimized => Event::Unknown,
                 sdl::WindowEventId::Maximized => Event::Unknown,
                 sdl::WindowEventId::Restored => Event::Unknown,
-                sdl::WindowEventId::Enter => Event::Unknown,
-                sdl::WindowEventId::Leave => Event::Unknown,
-                sdl::WindowEventId::FocusGained => Event::Unknown,
-                sdl::WindowEventId::FocusLost => Event::Unknown,
+                sdl::WindowEventId::Enter => {
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::MouseEnter {
+                        window: handle,
+                        x: unsafe { event.window.data1 },
+                        y: unsafe { event.window.data2 },
+                    }
+                }
+                sdl::WindowEventId::Leave => {
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::MouseLeave {
+                        window: handle,
+                        x: unsafe { event.window.data1 },
+                        y: unsafe { event.window.data2 },
+                    }
+                }
+                sdl::WindowEventId::FocusGained => {
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::FocusIn { window: handle }
+                }
+                sdl::WindowEventId::FocusLost => {
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::FocusOut { window: handle }
+                }
                 sdl::WindowEventId::Close => {
-                    let handle = self
-                        .window_id_to_handle
-                        .lock()
-                        .get(&unsafe { event.window.window_id })
-                        .copied()
-                        .unwrap_or_else(|| Window(Handle::null()));
-                    Event::WindowClose(handle)
+                    let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                    Event::Close { window: handle }
                 }
                 sdl::WindowEventId::TakeFocus => Event::Unknown,
                 sdl::WindowEventId::HitTest => Event::Unknown,
                 sdl::WindowEventId::IccprofChanged => Event::Unknown,
                 sdl::WindowEventId::DisplayChanged => Event::Unknown,
             },
+            sdl::EventType::KEYUP | sdl::EventType::KEYDOWN => {
+                let handle = self.window_from_window_id(unsafe { event.key.window_id });
+                let scancode = unsafe { event.key.keysym.scancode };
+                let modifiers = unsafe { event.key.keysym.modifiers };
+                let state = unsafe { event.key.state };
+                let key = map_sdl_scancode(scancode);
+                let modifiers = map_sdl_modifiers(modifiers);
+                let pressed = map_sdl_pressed_state(state);
+                Event::KeyPress {
+                    window: handle,
+                    key,
+                    pressed,
+                    modifiers,
+                }
+            }
+            sdl::EventType::MOUSEBUTTONUP | sdl::EventType::MOUSEBUTTONDOWN => {
+                let handle = self.window_from_window_id(unsafe { event.button.window_id });
+                let button = unsafe { event.button.button };
+                let state = unsafe { event.button.state };
+                let button = map_sdl_button(button);
+                let pressed = map_sdl_pressed_state(state);
+                Event::ButtonPress {
+                    window: handle,
+                    button,
+                    pressed,
+                }
+            }
+            sdl::EventType::MOUSEMOTION => {
+                let handle = self.window_from_window_id(unsafe { event.window.window_id });
+                Event::MouseMotion {
+                    window: handle,
+                    x: unsafe { event.window.data1 },
+                    y: unsafe { event.window.data2 },
+                }
+            }
             _ => Event::Unknown,
         };
 
         Some(e)
     }
 }
+
+fn map_sdl_button(button: sdl::MouseButton) -> Button {
+    match button {
+        sdl::MouseButton::Left => Button::Left,
+        sdl::MouseButton::Middle => Button::Middle,
+        sdl::MouseButton::Right => Button::Right,
+        sdl::MouseButton::X1 => Button::X1,
+        sdl::MouseButton::X2 => Button::X2,
+    }
+}
+
+fn map_sdl_pressed_state(pressed_state: sdl::PressedState) -> PressedState {
+    match pressed_state {
+        sdl::PressedState::Released => PressedState::Released,
+        sdl::PressedState::Pressed => PressedState::Pressed,
+    }
+}
+
+fn map_sdl_modifiers(modifiers: sdl::Keymod) -> ModifierFlags {
+    let mut flags = ModifierFlags::default();
+    if modifiers.0 & sdl::Keymod::ALT.0 != 0 {
+        flags &= ModifierFlags::ALT
+    }
+    if modifiers.0 & sdl::Keymod::SHIFT.0 != 0 {
+        flags &= ModifierFlags::SHIFT
+    }
+    if modifiers.0 & sdl::Keymod::CTRL.0 != 0 {
+        flags &= ModifierFlags::CTRL
+    }
+    if modifiers.0 & sdl::Keymod::GUI.0 != 0 {
+        flags &= ModifierFlags::META
+    }
+    flags
+}
+
+fn map_sdl_scancode(scancode: sdl::Scancode) -> Key {
+    match scancode {
+        sdl::Scancode::A => Key::A,
+        sdl::Scancode::B => Key::B,
+        sdl::Scancode::C => Key::C,
+        sdl::Scancode::D => Key::D,
+        sdl::Scancode::E => Key::E,
+        sdl::Scancode::F => Key::F,
+        sdl::Scancode::G => Key::G,
+        sdl::Scancode::H => Key::H,
+        sdl::Scancode::I => Key::I,
+        sdl::Scancode::J => Key::J,
+        sdl::Scancode::K => Key::K,
+        sdl::Scancode::L => Key::L,
+        sdl::Scancode::M => Key::M,
+        sdl::Scancode::N => Key::N,
+        sdl::Scancode::O => Key::O,
+        sdl::Scancode::P => Key::P,
+        sdl::Scancode::Q => Key::Q,
+        sdl::Scancode::R => Key::R,
+        sdl::Scancode::S => Key::S,
+        sdl::Scancode::T => Key::T,
+        sdl::Scancode::U => Key::U,
+        sdl::Scancode::V => Key::V,
+        sdl::Scancode::W => Key::W,
+        sdl::Scancode::X => Key::X,
+        sdl::Scancode::Y => Key::Y,
+        sdl::Scancode::Z => Key::Z,
+
+        sdl::Scancode::SCANCODE_1 => Key::Key1,
+        sdl::Scancode::SCANCODE_2 => Key::Key2,
+        sdl::Scancode::SCANCODE_3 => Key::Key3,
+        sdl::Scancode::SCANCODE_4 => Key::Key4,
+        sdl::Scancode::SCANCODE_5 => Key::Key5,
+        sdl::Scancode::SCANCODE_6 => Key::Key6,
+        sdl::Scancode::SCANCODE_7 => Key::Key7,
+        sdl::Scancode::SCANCODE_8 => Key::Key8,
+        sdl::Scancode::SCANCODE_9 => Key::Key9,
+        sdl::Scancode::SCANCODE_0 => Key::Key0,
+
+        sdl::Scancode::RETURN => Key::Return,
+        sdl::Scancode::ESCAPE => Key::Escape,
+        sdl::Scancode::BACKSPACE => Key::Backspace,
+        sdl::Scancode::DELETE => Key::Delete,
+        sdl::Scancode::TAB => Key::Tab,
+        sdl::Scancode::SPACE => Key::Space,
+        sdl::Scancode::MINUS => Key::Minus,
+        sdl::Scancode::EQUALS => Key::Equal,
+        sdl::Scancode::LEFTBRACKET => Key::LeftBrace,
+        sdl::Scancode::RIGHTBRACKET => Key::RightBrace,
+        sdl::Scancode::BACKSLASH => Key::Backslash,
+        sdl::Scancode::SEMICOLON => Key::Semicolon,
+        sdl::Scancode::APOSTROPHE => Key::Apostrophe,
+        sdl::Scancode::GRAVE => Key::Grave,
+        sdl::Scancode::COMMA => Key::Comma,
+        sdl::Scancode::PERIOD => Key::Period,
+        sdl::Scancode::SLASH => Key::Slash,
+        sdl::Scancode::CAPSLOCK => Key::CapsLock,
+
+        sdl::Scancode::F1 => Key::F1,
+        sdl::Scancode::F2 => Key::F2,
+        sdl::Scancode::F3 => Key::F3,
+        sdl::Scancode::F4 => Key::F4,
+        sdl::Scancode::F5 => Key::F5,
+        sdl::Scancode::F6 => Key::F6,
+        sdl::Scancode::F7 => Key::F7,
+        sdl::Scancode::F8 => Key::F8,
+        sdl::Scancode::F9 => Key::F9,
+        sdl::Scancode::F10 => Key::F10,
+        sdl::Scancode::F11 => Key::F11,
+        sdl::Scancode::F12 => Key::F12,
+        sdl::Scancode::F13 => Key::F13,
+        sdl::Scancode::F14 => Key::F14,
+        sdl::Scancode::F15 => Key::F15,
+        sdl::Scancode::F16 => Key::F16,
+        sdl::Scancode::F17 => Key::F17,
+        sdl::Scancode::F18 => Key::F18,
+        sdl::Scancode::F19 => Key::F19,
+        sdl::Scancode::F20 => Key::F20,
+        sdl::Scancode::F21 => Key::F21,
+        sdl::Scancode::F22 => Key::F22,
+        sdl::Scancode::F23 => Key::F23,
+        sdl::Scancode::F24 => Key::F24,
+
+        sdl::Scancode::SCROLLLOCK => Key::ScrollLock,
+        sdl::Scancode::INSERT => Key::Insert,
+        sdl::Scancode::HOME => Key::Home,
+        sdl::Scancode::END => Key::End,
+        sdl::Scancode::PAGEUP => Key::PageUp,
+        sdl::Scancode::PAGEDOWN => Key::PageDown,
+
+        sdl::Scancode::LEFT => Key::Left,
+        sdl::Scancode::RIGHT => Key::Right,
+        sdl::Scancode::UP => Key::Up,
+        sdl::Scancode::DOWN => Key::Down,
+
+        sdl::Scancode::NUMLOCKCLEAR => Key::NumLock,
+        sdl::Scancode::KP_DIVIDE => Key::NumpadDivide,
+        sdl::Scancode::KP_MULTIPLY => Key::NumpadMultiply,
+        sdl::Scancode::KP_MINUS => Key::NumpadSubtract,
+        sdl::Scancode::KP_PLUS => Key::NumpadAdd,
+        sdl::Scancode::KP_ENTER => Key::NumpadEnter,
+        sdl::Scancode::KP_1 => Key::Numpad1,
+        sdl::Scancode::KP_2 => Key::Numpad2,
+        sdl::Scancode::KP_3 => Key::Numpad3,
+        sdl::Scancode::KP_4 => Key::Numpad4,
+        sdl::Scancode::KP_5 => Key::Numpad5,
+        sdl::Scancode::KP_6 => Key::Numpad6,
+        sdl::Scancode::KP_7 => Key::Numpad7,
+        sdl::Scancode::KP_8 => Key::Numpad8,
+        sdl::Scancode::KP_9 => Key::Numpad9,
+        sdl::Scancode::KP_0 => Key::Numpad0,
+        sdl::Scancode::KP_PERIOD => Key::NumpadPeriod,
+        sdl::Scancode::KP_EQUALS => Key::NumpadEquals,
+        sdl::Scancode::KP_LEFTPAREN => Key::NumpadLeftParen,
+        sdl::Scancode::KP_RIGHTPAREN => Key::NumpadRightParen,
+        sdl::Scancode::KP_PLUSMINUS => Key::NumpadPlusMinus,
+        sdl::Scancode::KP_COMMA => Key::NumpadComma,
+
+        sdl::Scancode::EJECT => Key::Eject,
+        sdl::Scancode::STOP => Key::Stop,
+        sdl::Scancode::MUTE => Key::Mute,
+        sdl::Scancode::VOLUMEUP => Key::VolumeUp,
+        sdl::Scancode::VOLUMEDOWN => Key::VolumeDown,
+        sdl::Scancode::POWER => Key::Power,
+
+        sdl::Scancode::APPLICATION => Key::Compose,
+        sdl::Scancode::SLEEP => Key::Sleep,
+
+        sdl::Scancode::LSHIFT => Key::LeftShift,
+        sdl::Scancode::RSHIFT => Key::RightShift,
+        sdl::Scancode::LCTRL => Key::LeftControl,
+        sdl::Scancode::RCTRL => Key::RightControl,
+        sdl::Scancode::LALT => Key::LeftAlt,
+        sdl::Scancode::RALT => Key::RightAlt,
+        sdl::Scancode::LGUI => Key::LeftMeta,
+        sdl::Scancode::RGUI => Key::RightMeta,
+
+        sdl::Scancode::MENU => Key::Menu,
+        sdl::Scancode::PAUSE => Key::Pause,
+
+        sdl::Scancode::NONUSBACKSLASH => Key::NonUSBackslash,
+        sdl::Scancode::SYSREQ => Key::SysReq,
+        sdl::Scancode::AGAIN => Key::Again,
+        sdl::Scancode::UNDO => Key::Undo,
+        sdl::Scancode::COPY => Key::Copy,
+        sdl::Scancode::PASTE => Key::Paste,
+        sdl::Scancode::FIND => Key::Find,
+        sdl::Scancode::CUT => Key::Cut,
+        sdl::Scancode::HELP => Key::Help,
+        sdl::Scancode::CALCULATOR => Key::Calculator,
+        sdl::Scancode::ALTERASE => Key::AltErase,
+        sdl::Scancode::CANCEL => Key::Cancel,
+
+        sdl::Scancode::BRIGHTNESSUP => Key::BrightnessUp,
+        sdl::Scancode::BRIGHTNESSDOWN => Key::BrightnessDown,
+
+        sdl::Scancode::DISPLAYSWITCH => Key::SwitchVideoMode,
+
+        sdl::Scancode::KBDILLUMTOGGLE => Key::KeyboardIlluminationToggle,
+        sdl::Scancode::KBDILLUMDOWN => Key::KeyboardIlluminationDown,
+        sdl::Scancode::KBDILLUMUP => Key::KeyboardIlluminationUp,
+
+        sdl::Scancode::APP1 => Key::App1,
+        sdl::Scancode::APP2 => Key::App2,
+        sdl::Scancode::WWW => Key::WWW,
+        sdl::Scancode::MAIL => Key::Mail,
+        sdl::Scancode::COMPUTER => Key::Computer,
+
+        sdl::Scancode::AC_BOOKMARKS => Key::ACBookmarks,
+        sdl::Scancode::AC_BACK => Key::ACBack,
+        sdl::Scancode::AC_FORWARD => Key::ACForward,
+        sdl::Scancode::AC_HOME => Key::ACHome,
+        sdl::Scancode::AC_REFRESH => Key::ACRefresh,
+        sdl::Scancode::AC_SEARCH => Key::ACSearch,
+
+        sdl::Scancode::AUDIONEXT => Key::AudioNext,
+        sdl::Scancode::AUDIOPLAY => Key::AudioPlay,
+        sdl::Scancode::AUDIOPREV => Key::AudioPrev,
+        sdl::Scancode::AUDIOSTOP => Key::AudioStop,
+        sdl::Scancode::AUDIOREWIND => Key::AudioRewind,
+        sdl::Scancode::AUDIOFASTFORWARD => Key::AudioFastForward,
+
+        sdl::Scancode::LANG1 => Key::Language1,
+        sdl::Scancode::LANG2 => Key::Language2,
+        sdl::Scancode::LANG3 => Key::Language3,
+        sdl::Scancode::LANG4 => Key::Language4,
+        sdl::Scancode::LANG5 => Key::Language5,
+
+        sdl::Scancode::INTERNATIONAL1 => Key::International1,
+        sdl::Scancode::INTERNATIONAL2 => Key::International2,
+        sdl::Scancode::INTERNATIONAL3 => Key::International3,
+        sdl::Scancode::INTERNATIONAL4 => Key::International4,
+        sdl::Scancode::INTERNATIONAL5 => Key::International5,
+
+        _ => Key::Unknown,
+    }
+}
index 839ada88c16e4ff496b4cd7e0b57789389c68482..a538a331e59faf0c92543d2853924c5e48bd73fd 100644 (file)
@@ -1,6 +1,6 @@
 use std::{path::Path, time::Instant};
 
-use narcissus_app::{create_app, Event, WindowDesc};
+use narcissus_app::{create_app, Event, Key, WindowDesc};
 use narcissus_core::{cstr, default, obj, Image};
 use narcissus_gpu::{
     create_vulkan_device, Bind, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType, Buffer,
@@ -193,7 +193,7 @@ pub fn main() {
     let (blåhaj_vertices, blåhaj_indices) = load_obj("narcissus/data/blåhaj.obj");
 
     let app = create_app();
-    let window = app.create_window(&WindowDesc {
+    let main_window = app.create_window(&WindowDesc {
         title: "narcissus",
         width: 800,
         height: 600,
@@ -279,11 +279,21 @@ pub fn main() {
         while let Some(event) = app.poll_event() {
             use Event::*;
             match event {
+                KeyPress {
+                    window: _,
+                    key,
+                    pressed: _,
+                    modifiers: _,
+                } => {
+                    if key == Key::Escape {
+                        break 'main;
+                    }
+                }
                 Quit => {
                     break 'main;
                 }
-                WindowClose(w) => {
-                    assert_eq!(window, w);
+                Close { window } => {
+                    assert_eq!(window, main_window);
                     device.destroy_window(window);
                     break 'main;
                 }
@@ -292,7 +302,7 @@ pub fn main() {
         }
 
         let (width, height, swapchain_image) =
-            device.acquire_swapchain(&frame_token, window, TextureFormat::BGRA8_SRGB);
+            device.acquire_swapchain(&frame_token, main_window, TextureFormat::BGRA8_SRGB);
 
         let frame_start = Instant::now() - start_time;
         let frame_start = frame_start.as_secs_f32() * 0.5;