app_input 0.1.2

Cross-platform mouse and keyboard input
Documentation
// SPDX-License-Identifier: MPL-2.0
use crate::keyboard::Shared;
use crate::keyboard::key::KeyboardKey;
use std::ffi::c_void;
use std::sync::Arc;
use std::sync::Weak;

#[derive(Debug)]
pub(super) struct PlatformCoalescedKeyboard {
    imp: *mut c_void,
}

#[unsafe(no_mangle)]
unsafe extern "C" fn raw_input_key_notify_func(
    ctx: *mut c_void,
    window: *mut c_void,
    key_code: u16,
    down: bool,
) {
    let shared = unsafe { Weak::from_raw(ctx as *const Shared) };
    if let Some(shared) = shared.upgrade() {
        let key_code = KeyboardKey::from_code(key_code).expect("Unknown key code {key_code}");
        shared.set_key_state(key_code, down, window);
    }
    std::mem::forget(shared); //keep weak reference alive as it is still owned by the target function
}

#[unsafe(no_mangle)]
unsafe extern "C" fn raw_input_finish_event_context(ctx: *mut c_void) {
    unsafe { Weak::from_raw(ctx as *const Shared) };
}

unsafe extern "C" {
    fn PlatformCoalescedKeyboardNew(context: *const c_void) -> *mut c_void;
    fn PlatformCoalescedKeyboardFree(imp: *mut c_void);

    fn SwiftRawInputDebugWindowShow();
    fn SwiftRawInputDebugWindowHide();
}

pub fn debug_window_show() {
    unsafe { SwiftRawInputDebugWindowShow() }
}

pub fn debug_window_hide() {
    unsafe { SwiftRawInputDebugWindowHide() }
}

//Swift type implements Sendable
unsafe impl Send for PlatformCoalescedKeyboard {}
unsafe impl Sync for PlatformCoalescedKeyboard {}

impl PlatformCoalescedKeyboard {
    pub fn new(shared: &Arc<Shared>) -> Self {
        let weak = Arc::downgrade(shared);
        let weak_raw = Weak::into_raw(weak) as *const c_void;
        PlatformCoalescedKeyboard {
            imp: unsafe { PlatformCoalescedKeyboardNew(weak_raw) },
        }
    }
}

impl Drop for PlatformCoalescedKeyboard {
    fn drop(&mut self) {
        unsafe { PlatformCoalescedKeyboardFree(self.imp) }
    }
}

//keyboard codes, HIToolbox/Events.h
impl KeyboardKey {
    pub fn from_code(code: u16) -> Option<KeyboardKey> {
        match code {
            0x00 => Some(KeyboardKey::A),
            0x01 => Some(KeyboardKey::S),
            0x02 => Some(KeyboardKey::D),
            0x03 => Some(KeyboardKey::F),
            0x04 => Some(KeyboardKey::H),
            0x05 => Some(KeyboardKey::G),
            0x06 => Some(KeyboardKey::Z),
            0x07 => Some(KeyboardKey::X),
            0x08 => Some(KeyboardKey::C),
            0x09 => Some(KeyboardKey::V),
            0x0A => Some(KeyboardKey::InternationalBackslash),
            0x0B => Some(KeyboardKey::B),
            0x0C => Some(KeyboardKey::Q),
            0x0D => Some(KeyboardKey::W),
            0x0E => Some(KeyboardKey::E),
            0x0F => Some(KeyboardKey::R),
            0x10 => Some(KeyboardKey::Y),
            0x11 => Some(KeyboardKey::T),
            0x12 => Some(KeyboardKey::Num1),
            0x13 => Some(KeyboardKey::Num2),
            0x14 => Some(KeyboardKey::Num3),
            0x15 => Some(KeyboardKey::Num4),
            0x16 => Some(KeyboardKey::Num6),
            0x17 => Some(KeyboardKey::Num5),
            0x18 => Some(KeyboardKey::Equal),
            0x19 => Some(KeyboardKey::Num9),
            0x1A => Some(KeyboardKey::Num7),
            0x1B => Some(KeyboardKey::Minus),
            0x1C => Some(KeyboardKey::Num8),
            0x1D => Some(KeyboardKey::Num0),
            0x1E => Some(KeyboardKey::RightBracket),
            0x1F => Some(KeyboardKey::O),
            0x20 => Some(KeyboardKey::U),
            0x21 => Some(KeyboardKey::LeftBracket),
            0x22 => Some(KeyboardKey::I),
            0x23 => Some(KeyboardKey::P),
            0x24 => Some(KeyboardKey::Return),
            0x25 => Some(KeyboardKey::L),
            0x26 => Some(KeyboardKey::J),
            0x27 => Some(KeyboardKey::Quote),
            0x28 => Some(KeyboardKey::K),
            0x29 => Some(KeyboardKey::Semicolon),
            0x2A => Some(KeyboardKey::Backslash),
            0x2B => Some(KeyboardKey::Comma),
            0x2C => Some(KeyboardKey::Slash),
            0x2D => Some(KeyboardKey::N),
            0x2E => Some(KeyboardKey::M),
            0x2F => Some(KeyboardKey::Period),
            0x30 => Some(KeyboardKey::Tab),
            0x31 => Some(KeyboardKey::Space),
            0x32 => Some(KeyboardKey::Grave),
            0x33 => Some(KeyboardKey::Delete),
            0x34 => Some(KeyboardKey::KeypadEnter),
            0x35 => Some(KeyboardKey::Escape),
            0x36 => Some(KeyboardKey::RightCommand),
            0x37 => Some(KeyboardKey::Command),
            0x38 => Some(KeyboardKey::Shift),
            0x39 => Some(KeyboardKey::CapsLock),
            0x3A => Some(KeyboardKey::Option),
            0x3B => Some(KeyboardKey::Control),
            0x3C => Some(KeyboardKey::RightShift),
            0x3D => Some(KeyboardKey::RightOption),
            0x3E => Some(KeyboardKey::RightControl),
            0x3F => Some(KeyboardKey::Function),
            0x40 => Some(KeyboardKey::F17),
            0x41 => Some(KeyboardKey::KeypadDecimal),
            //nobody seems to know what 42 is!
            0x43 => Some(KeyboardKey::KeypadMultiply),
            //0x44  ??
            0x45 => Some(KeyboardKey::KeypadPlus),
            //0x46 ??
            0x47 => Some(KeyboardKey::NumLock),

            0x48 => Some(KeyboardKey::VolumeUp),
            0x49 => Some(KeyboardKey::VolumeDown),
            0x4A => Some(KeyboardKey::Mute),
            0x4B => Some(KeyboardKey::KeypadDivide),
            0x4C => Some(KeyboardKey::KeypadEnter),
            //0x4d ??
            0x4E => Some(KeyboardKey::KeypadMinus),
            0x4F => Some(KeyboardKey::F18),
            0x50 => Some(KeyboardKey::F19),
            0x51 => Some(KeyboardKey::KeypadEquals),
            0x52 => Some(KeyboardKey::Keypad0),
            0x53 => Some(KeyboardKey::Keypad1),
            0x54 => Some(KeyboardKey::Keypad2),
            0x55 => Some(KeyboardKey::Keypad3),
            0x56 => Some(KeyboardKey::Keypad4),
            0x57 => Some(KeyboardKey::Keypad5),
            0x58 => Some(KeyboardKey::Keypad6),
            0x59 => Some(KeyboardKey::Keypad7),
            0x5A => Some(KeyboardKey::F20),
            0x5B => Some(KeyboardKey::Keypad8),
            0x5C => Some(KeyboardKey::Keypad9),
            0x5D => Some(KeyboardKey::JISYen),
            0x5E => Some(KeyboardKey::JISUnderscore),
            0x5F => Some(KeyboardKey::JISKeypadComma),
            0x60 => Some(KeyboardKey::F5),
            0x61 => Some(KeyboardKey::F6),
            0x62 => Some(KeyboardKey::F7),
            0x63 => Some(KeyboardKey::F3),
            0x64 => Some(KeyboardKey::F8),
            0x65 => Some(KeyboardKey::F9),
            0x66 => Some(KeyboardKey::JISEisu),
            0x67 => Some(KeyboardKey::F11),
            0x68 => Some(KeyboardKey::JISKana),
            0x69 => Some(KeyboardKey::F13),
            0x6A => Some(KeyboardKey::F16),
            0x6B => Some(KeyboardKey::F14),
            //0x6c ??
            0x6D => Some(KeyboardKey::F10),
            0x6E => Some(KeyboardKey::ContextualMenu),
            0x6F => Some(KeyboardKey::F12),
            //0x70 ??
            0x71 => Some(KeyboardKey::F15),
            0x72 => Some(KeyboardKey::Help),
            0x73 => Some(KeyboardKey::Home),
            0x74 => Some(KeyboardKey::PageUp),
            0x75 => Some(KeyboardKey::ForwardDelete),
            0x76 => Some(KeyboardKey::F4),
            0x77 => Some(KeyboardKey::End),
            0x78 => Some(KeyboardKey::F2),
            0x79 => Some(KeyboardKey::PageDown),
            0x7A => Some(KeyboardKey::F1),
            0x7B => Some(KeyboardKey::LeftArrow),
            0x7C => Some(KeyboardKey::RightArrow),
            0x7D => Some(KeyboardKey::DownArrow),
            0x7E => Some(KeyboardKey::UpArrow),
            _ => None, // Return None if the code doesn't match any key
        }
    }
}