/// ## keyboard example
/// ```rust
/// cargo add doe -F kcm
///use doe::keyboard::key_click;
///use doe::keyboard::key_press;
///use doe::keyboard::key_release;
///use doe::keyboard::KeyCode;
///use doe::mouse::mouse_drag;
///use doe::mouse::move_to_paste;
///use doe::mouse::move_to_press_left;
///use doe::*;
///use keyboard::exit_if_click_esc;
///let list = vec!["iphone","ipad","macbook"];
///
///// crete new baogao
///move_to_press_left(857, 588).sleep(1.0); //#000000
///
///// create fengmian
///move_to_paste(1540, 853, "Apple").sleep(1.0); //#000000
///move_to_paste(1360, 882, "ID").sleep(1.0); //#000000
///
///// add shuoming
///move_to_paste(772, 464, "Discription").sleep(1.0); //#ffffff
///mouse_drag((894, 719).into(), (821, 716).into()).sleep(1.0); //#f0f0f0
///key_click("2024-01-23").sleep(1.0);
///move_to_press_left(740, 305).sleep(1.0); //#f0f0f0
///
///for name in list {
///    // add baobao
///    move_to_press_left(476, 253).sleep(1.0); //#ffffff
///
///    // name
///    move_to_press_left(796, 331).sleep(1.0); //#ffffff
///    key_click("end");
///    key_click("shift+home");
///    set_clipboard(name).unwrap().sleep(0.5);
///    key_click("ctrl+v");
///
///    // add fujian
///    move_to_press_left(870, 587).sleep(1.0); //#000000
///    mouse_drag((893, 818).into(), (814, 816).into()).sleep(1.0); //#f0f0f0
///    key_click("2024-01-23").sleep(1.0);
///    move_to_press_left(723, 206).sleep(1.0); //#000000
///}
///
///// set taoshu
///move_to_paste(1341, 910, "New_name").sleep(1.0); //#000000
/// ```
#[allow(warnings)]
#[cfg(feature = "keyboard")]
pub mod keyboard {
    pub mod common {
        #[allow(warnings)]
        /// key_modifiers: 'SHIFT' 'CONTROL' 'ALT' 'SUPER' 'HYPER' 'META' 'NONE'
        /// ```ignore
        /// use doe::keyboard::listen_keyboard_in_terminal;
        /// listen_keyboard_in_terminal(std::sync::Arc::new(|key|{
        ///    if key == "1,0x0,Press"{
        ///        b1::b1();
        ///    }
        /// }));
        /// ```
        pub fn listen_keyboard_in_terminal<F>(press_callback: std::sync::Arc<F>)
        where
            F: Fn(String) + std::marker::Sync + std::marker::Send + 'static,
        {
            use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
            use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
            use std::sync::mpsc;
            use std::thread;
            use std::time::Duration;

            // 启用原始模式，以便可以捕捉按键事件
            enable_raw_mode().expect("Failed to enable raw mode");

            // 创建一个通道，用于从键盘监听线程发送事件到主线程
            let (tx, rx) = mpsc::channel();

            // 复制通道的发送端，用于在键盘监听线程中发送事件
            let tx_clone = tx.clone();

            // 启动键盘监听线程
            thread::spawn(move || {
                // 每隔一段时间检查键盘事件并发送到通道
                loop {
                    if crossterm::event::poll(Duration::from_millis(100)).unwrap() {
                        if let crossterm::event::Event::Key(KeyEvent {
                            code,
                            modifiers,
                            state,
                            kind,
                        }) = crossterm::event::read().unwrap()
                        {
                            // 发送键盘事件到通道
                            tx_clone.send((code, modifiers, state, kind)).unwrap();
                        }
                    }
                }
            });

            // 主线程处理从通道接收到的键盘事件
            loop {
                if let Ok((code, modifiers, state, kind)) = rx.recv() {
                    // 在这里处理接收到的键盘事件
                    // println!(
                    //     "Key event received: {:?} with modifiers {:?}, state: {:?}, kind: {:?}",
                    //     code, modifiers, state,kind
                    // );
                    let code = format!("{:?}", code)
                        .replace("Char", "")
                        .replace(")", "")
                        .replace("'", "")
                        .replace("(", "");
                    let modifiers = format!("{:?}", modifiers)
                        .replace("KeyModifiers(", "")
                        .replace(" | ", ",")
                        .replace(")", "");
                    let _kind = format!("{:?}", kind);
                    press_callback(vec![code, modifiers, _kind].join(",").to_string());
                    // 如果需要退出循环，可以添加一个条件并调用disable_raw_mode来还原终端状态
                    disable_raw_mode().expect("Failed to disable raw mode");
                    // break;
                }
            }
        }
    }

    #[cfg(target_os = "linux")]
    pub mod linux {
        use std::ffi::c_void;
        use std::ptr;
        use std::sync::Arc;
        use std::time::Duration;

        // X11 FFI types
        type Display = c_void;
        type Window = u64;
        type KeySym = u64;
        type KeyCode = u8;
        type Atom = u64;
        type Bool = i32;
        type Status = i32;

        const CURRENT_TIME: u64 = 0;
        const TRUE: Bool = 1;
        const FALSE: Bool = 0;

        #[link(name = "X11")]
        extern "C" {
            fn XOpenDisplay(name: *const i8) -> *mut Display;
            fn XCloseDisplay(dpy: *mut Display);
            fn XDefaultRootWindow(dpy: *mut Display) -> Window;
            fn XStringToKeysym(s: *const i8) -> KeySym;
            fn XKeysymToKeycode(dpy: *mut Display, ks: KeySym) -> KeyCode;
            fn XKeycodeToKeysym(dpy: *mut Display, kc: KeyCode, index: i32) -> KeySym;
            fn XFlush(dpy: *mut Display) -> i32;
            fn XSync(dpy: *mut Display, discard: i32) -> i32;
            fn XGetInputFocus(dpy: *mut Display, win: *mut Window, revert_to: *mut i32) -> i32;
            fn XSelectInput(dpy: *mut Display, win: Window, mask: i64) -> i32;
            fn XNextEvent(dpy: *mut Display, event: *mut XEvent) -> i32;
            fn XInternAtom(dpy: *mut Display, name: *const i8, only_if_exists: Bool) -> Atom;
            fn XGetWindowProperty(
                dpy: *mut Display, win: Window, atom: Atom, offset: i64,
                length: i64, delete: Bool, req_type: Atom,
                actual_type: *mut Atom, actual_format: *mut i32,
                nitems: *mut u64, bytes_after: *mut u64, data: *mut *mut u8,
            ) -> i32;
            fn XFree(data: *mut c_void) -> i32;
            fn XQueryTree(
                dpy: *mut Display, win: Window, root: *mut Window,
                parent: *mut Window, children: *mut *mut Window, nchildren: *mut u32,
            ) -> Status;
        }

        #[link(name = "Xtst")]
        extern "C" {
            fn XTestFakeKeyEvent(dpy: *mut Display, kc: KeyCode, is_press: Bool, delay: u64);
        }

        // XRecord FFI for global keyboard listening
        #[link(name = "Xtst")]
        extern "C" {
            fn XRecordQueryVersion(dpy: *mut Display, major: *mut u8, minor: *mut u8) -> Status;
            fn XRecordCreateContext(
                dpy: *mut Display, datum_flags: i32,
                clients: *mut u64, nclients: i32,
                ranges: *mut *mut XRecordRange, nranges: i32,
            ) -> u64;
            fn XRecordEnableContext(dpy: *mut Display, ctx: u64, callback: Option<unsafe extern "C" fn(*mut c_void, *mut XRecordInterceptData)>, closure: *mut c_void) -> i32;
            fn XRecordDisableContext(dpy: *mut Display, ctx: u64) -> Status;
            fn XRecordFreeContext(dpy: *mut Display, ctx: u64) -> Status;
            fn XRecordAllocRange() -> *mut XRecordRange;
            fn XRecordFreeRange(range: *mut XRecordRange);
        }

        // XRecordRange has pairs of first/last for each event type category
        #[repr(C)]
        struct XRecordRange {
            first_requests: u8,
            last_requests: u8,
            first_replies: u8,
            last_replies: u8,
            first_device_events: u8,
            last_device_events: u8,
            first_errors: u8,
            last_errors: u8,
            first_client_started: u8,
            last_client_started: u8,
            first_client_died: u8,
            last_client_died: u8,
        }

        #[repr(C)]
        struct XRecordInterceptData {
            category: i32,
            client_swapped: Bool,
            id_base: u8,
            server_time: u64,
            client_seq: u64,
            data: *mut u8,
            data_len: i32,
        }

        // XEvent union (simplified, we only care about key events)
        #[repr(C)]
        union XEvent {
            type_: i32,
            xkey: XKeyEventData,
            padding: [u8; 96],
        }

        #[repr(C)]
        #[derive(Copy, Clone)]
        struct XKeyEventData {
            type_: i32,
            serial: u64,
            send_event: Bool,
            display: *mut Display,
            window: Window,
            root: Window,
            subwindow: Window,
            time: u64,
            x: i32,
            y: i32,
            x_root: i32,
            y_root: i32,
            state: u32,
            keycode: KeyCode,
            same_screen: Bool,
        }

        // Wrapper to make Display pointer Send-able for thread spawning
        // Store as usize which is Send
        struct DisplayPtr(usize);

        impl DisplayPtr {
            fn new(ptr: *mut Display) -> Self {
                DisplayPtr(ptr as usize)
            }
            fn get(&self) -> *mut Display {
                self.0 as *mut Display
            }
        }

        unsafe impl Send for DisplayPtr {}

        /// Open X11 display, returns None if display cannot be opened
        fn open_display() -> Option<*mut Display> {
            unsafe {
                let dpy = XOpenDisplay(ptr::null());
                if dpy.is_null() {
                    None
                } else {
                    Some(dpy)
                }
            }
        }

        /// Convert a key string like "a", "ctrl", "return", "f1" to an X11 keycode.
        /// Supports modifier names: ctrl, shift, alt, super, caps_lock, etc.
        fn str_to_keycode(dpy: *mut Display, key: &str) -> Option<KeyCode> {
            let lower = key.to_lowercase();
            let keysym_str = match lower.as_str() {
                // Modifiers
                "ctrl" | "control" => "Control_L",
                "ctrl_r" | "control_r" => "Control_R",
                "shift" => "Shift_L",
                "shift_r" => "Shift_R",
                "alt" => "Alt_L",
                "alt_r" => "Alt_R",
                "super" | "win" | "windows" | "meta" => "Super_L",
                "super_r" | "win_r" | "meta_r" => "Super_R",
                "caps_lock" => "Caps_Lock",
                "num_lock" => "Num_Lock",
                "scroll_lock" => "Scroll_Lock",
                // Special keys
                "return" | "enter" => "Return",
                "escape" | "esc" => "Escape",
                "backspace" => "BackSpace",
                "tab" => "Tab",
                "space" | "spacebar" => "space",
                "delete" => "Delete",
                "home" => "Home",
                "end" => "End",
                "page_up" | "pageup" => "Page_Up",
                "page_down" | "pagedown" => "Page_Down",
                "insert" => "Insert",
                "print" | "printscreen" | "sysrq" => "Print",
                "pause" => "Pause",
                "menu" | "apps" => "Menu",
                // Arrow keys
                "left" | "left_arrow" => "Left",
                "right" | "right_arrow" => "Right",
                "up" | "up_arrow" => "Up",
                "down" | "down_arrow" => "Down",
                // Function keys
                "f1" => "F1",
                "f2" => "F2",
                "f3" => "F3",
                "f4" => "F4",
                "f5" => "F5",
                "f6" => "F6",
                "f7" => "F7",
                "f8" => "F8",
                "f9" => "F9",
                "f10" => "F10",
                "f11" => "F11",
                "f12" => "F12",
                "f13" => "F13",
                "f14" => "F14",
                "f15" => "F15",
                // Keypad
                "kp_0" => "KP_0",
                "kp_1" => "KP_1",
                "kp_2" => "KP_2",
                "kp_3" => "KP_3",
                "kp_4" => "KP_4",
                "kp_5" => "KP_5",
                "kp_6" => "KP_6",
                "kp_7" => "KP_7",
                "kp_8" => "KP_8",
                "kp_9" => "KP_9",
                "kp_enter" => "KP_Enter",
                "kp_add" | "kp_plus" => "KP_Add",
                "kp_subtract" | "kp_minus" => "KP_Subtract",
                "kp_multiply" => "KP_Multiply",
                "kp_divide" => "KP_Divide",
                "kp_decimal" | "kp_dot" => "KP_Decimal",
                // Media keys
                "volume_up" | "vol_up" => "XF86AudioRaiseVolume",
                "volume_down" | "vol_down" => "XF86AudioLowerVolume",
                "mute" => "XF86AudioMute",
                "play" | "media_play" => "XF86AudioPlay",
                "pause_media" | "media_pause" => "XF86AudioPause",
                "stop" | "media_stop" => "XF86AudioStop",
                "next" | "media_next" => "XF86AudioNext",
                "prev" | "media_prev" => "XF86AudioPrev",
                // Single characters
                s if s.len() == 1 => s,
                _ => return None,
            };

            let c_str = std::ffi::CString::new(keysym_str).ok()?;
            unsafe {
                let keysym = XStringToKeysym(c_str.as_ptr());
                if keysym == 0 {
                    return None;
                }
                let keycode = XKeysymToKeycode(dpy, keysym);
                if keycode == 0 {
                    None
                } else {
                    Some(keycode)
                }
            }
        }

        /// Convert a single character to X11 keycode using XStringToKeysym
        fn char_to_keycode(dpy: *mut Display, ch: char) -> Option<KeyCode> {
            let s = ch.to_string();
            let c_str = std::ffi::CString::new(s).ok()?;
            unsafe {
                let keysym = XStringToKeysym(c_str.as_ptr());
                if keysym == 0 {
                    return None;
                }
                let keycode = XKeysymToKeycode(dpy, keysym);
                if keycode == 0 {
                    None
                } else {
                    Some(keycode)
                }
            }
        }

        /// Parse a key string that may contain modifiers joined by "+", e.g. "ctrl+shift+a"
        /// Returns a list of keycodes in order (modifiers first, then the main key)
        fn parse_key_combo(dpy: *mut Display, keys: &str) -> Vec<KeyCode> {
            let mut result = Vec::new();
            for part in keys.split('+') {
                let part = part.trim();
                if let Some(kc) = str_to_keycode(dpy, part) {
                    result.push(kc);
                } else {
                    // Try each character
                    for ch in part.chars() {
                        if let Some(kc) = char_to_keycode(dpy, ch) {
                            result.push(kc);
                        }
                    }
                }
            }
            result
        }

        /// Simulate a key press event.
        /// Supports key combos like "ctrl+a", "ctrl+shift+s", "f1", "return", etc.
        ///
        /// ```rust
        /// use doe::keyboard::key_press;
        /// key_press("ctrl+a");
        /// key_press("f1");
        /// key_press("return");
        /// ```
        pub fn key_press(keys: &str) {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };
            let keycodes = parse_key_combo(dpy, keys);
            unsafe {
                for &kc in &keycodes {
                    XTestFakeKeyEvent(dpy, kc, TRUE, CURRENT_TIME);
                }
                XFlush(dpy);
                XCloseDisplay(dpy);
            }
        }

        /// Simulate a key release event.
        /// Supports key combos like "ctrl+a", "ctrl+shift+s", "f1", "return", etc.
        ///
        /// ```rust
        /// use doe::keyboard::key_release;
        /// key_release("ctrl+a");
        /// ```
        pub fn key_release(keys: &str) {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };
            let keycodes = parse_key_combo(dpy, keys);
            unsafe {
                for &kc in &keycodes {
                    XTestFakeKeyEvent(dpy, kc, FALSE, CURRENT_TIME);
                }
                XFlush(dpy);
                XCloseDisplay(dpy);
            }
        }

        /// Simulate a key click (press then release) with optional delay between them.
        /// Supports key combos: modifiers are pressed first, then the main key is clicked,
        /// then modifiers are released.
        /// Also supports space-separated sequences: "ctrl+a ctrl+c" will execute two combos.
        ///
        /// ```rust
        /// use doe::keyboard::key_click;
        /// key_click("ctrl+a");        // Select all
        /// key_click("ctrl+shift+s");  // Save as
        /// key_click("return");        // Press Enter
        /// key_click("ctrl+a ctrl+c"); // Select all then copy
        /// ```
        pub fn key_click(keys: &str) {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };

            let combos: Vec<&str> = keys.split_whitespace().collect();
            unsafe {
                for combo in combos {
                    let keycodes = parse_key_combo(dpy, combo);
                    if keycodes.is_empty() {
                        continue;
                    }

                    // Press all keys (modifiers first, then main key)
                    for &kc in &keycodes {
                        XTestFakeKeyEvent(dpy, kc, TRUE, CURRENT_TIME);
                    }
                    XFlush(dpy);

                    // Small delay between press and release for stability
                    std::thread::sleep(Duration::from_millis(12));

                    // Release in reverse order (main key first, then modifiers)
                    for &kc in keycodes.iter().rev() {
                        XTestFakeKeyEvent(dpy, kc, FALSE, CURRENT_TIME);
                    }
                    XFlush(dpy);

                    // Small delay between combos
                    std::thread::sleep(Duration::from_millis(12));
                }
                XCloseDisplay(dpy);
            }
        }

        /// Type a text string by simulating individual key presses for each character.
        /// Supports Unicode characters by using XStringToKeysym.
        /// For characters that cannot be mapped directly, falls back to clipboard paste.
        ///
        /// ```rust
        /// use doe::keyboard::key_paste;
        /// key_paste("Hello, World!");
        /// key_paste("你好");  // Unicode characters
        /// ```
        pub fn key_paste(text: &str) {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };

            unsafe {
                for ch in text.chars() {
                    if let Some(kc) = char_to_keycode(dpy, ch) {
                        // Type the character directly via keycode
                        let needs_shift = ch.is_ascii_uppercase()
                            || matches!(ch, '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | '_' | '+' | '{' | '}' | '|' | ':' | '"' | '<' | '>' | '?' | '~');

                        if needs_shift {
                            if let Some(shift_kc) = str_to_keycode(dpy, "shift") {
                                XTestFakeKeyEvent(dpy, shift_kc, TRUE, CURRENT_TIME);
                            }
                        }

                        XTestFakeKeyEvent(dpy, kc, TRUE, CURRENT_TIME);
                        XFlush(dpy);
                        std::thread::sleep(Duration::from_micros(500));
                        XTestFakeKeyEvent(dpy, kc, FALSE, CURRENT_TIME);
                        XFlush(dpy);

                        if needs_shift {
                            if let Some(shift_kc) = str_to_keycode(dpy, "shift") {
                                XTestFakeKeyEvent(dpy, shift_kc, FALSE, CURRENT_TIME);
                            }
                        }

                        XFlush(dpy);
                        std::thread::sleep(Duration::from_millis(5));
                    } else {
                        // For characters that can't be typed directly (e.g. Chinese),
                        // use xdotool command as fallback via clipboard
                        if let Ok(output) = std::process::Command::new("xdotool")
                            .args(["type", "--delay", "12", &ch.to_string()])
                            .output()
                        {
                            let _ = output;
                        }
                    }
                }
                XCloseDisplay(dpy);
            }
        }

        /// Type a text string using only X11 keycodes (no external commands).
        /// Characters that cannot be mapped to X11 keycodes will be silently skipped.
        /// For full Unicode support, use `key_paste` instead.
        pub fn key_paste_native(text: &str) {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };

            unsafe {
                for ch in text.chars() {
                    if let Some(kc) = char_to_keycode(dpy, ch) {
                        let needs_shift = ch.is_ascii_uppercase()
                            || matches!(ch, '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | '_' | '+' | '{' | '}' | '|' | ':' | '"' | '<' | '>' | '?' | '~');

                        if needs_shift {
                            if let Some(shift_kc) = str_to_keycode(dpy, "shift") {
                                XTestFakeKeyEvent(dpy, shift_kc, TRUE, CURRENT_TIME);
                            }
                        }

                        XTestFakeKeyEvent(dpy, kc, TRUE, CURRENT_TIME);
                        XFlush(dpy);
                        std::thread::sleep(Duration::from_micros(500));
                        XTestFakeKeyEvent(dpy, kc, FALSE, CURRENT_TIME);
                        XFlush(dpy);

                        if needs_shift {
                            if let Some(shift_kc) = str_to_keycode(dpy, "shift") {
                                XTestFakeKeyEvent(dpy, shift_kc, FALSE, CURRENT_TIME);
                            }
                        }

                        XFlush(dpy);
                        std::thread::sleep(Duration::from_millis(5));
                    }
                }
                XCloseDisplay(dpy);
            }
        }

        /// Listen to global keyboard events using /dev/input devices.
        /// This requires root/sudo privileges or membership in the `input` group.
        /// The callback receives a string in the format "keycode,press" or "keycode,release".
        ///
        /// ```rust
        /// use std::sync::Arc;
        /// use doe::keyboard::listen_keyboard_callback;
        /// listen_keyboard_callback(Arc::new(|key| {
        ///     println!("Key event: {}", key);
        /// }));
        /// ```
        pub fn listen_keyboard_callback<F>(callback: Arc<F>)
        where
            F: Fn(String) + Send + Sync + 'static,
        {
            // Try XRecord extension first (no root needed)
            if try_listen_with_xrecord(callback.clone()) {
                return;
            }

            // Fallback to /dev/input
            listen_with_dev_input(callback);
        }

        /// Try to listen using XRecord extension (works without root)
        fn try_listen_with_xrecord<F>(callback: Arc<F>) -> bool
        where
            F: Fn(String) + Send + Sync + 'static,
        {
            let dpy = match open_display() {
                Some(d) => d,
                None => return false,
            };

            unsafe {
                // Check if XRecord is available
                let mut major: u8 = 0;
                let mut minor: u8 = 0;
                if XRecordQueryVersion(dpy, &mut major, &mut minor) == 0 {
                    XCloseDisplay(dpy);
                    return false;
                }

                let range = XRecordAllocRange();
                if range.is_null() {
                    XCloseDisplay(dpy);
                    return false;
                }

                // Set range to capture key events (device events)
                (*range).first_device_events = 0;
                (*range).last_device_events = 255;

                let client = 0u64; // all clients
                let ctx = XRecordCreateContext(
                    dpy,
                    0,
                    &client as *const u64 as *mut u64,
                    1,
                    &range as *const *mut XRecordRange as *mut *mut XRecordRange,
                    1,
                );

                XRecordFreeRange(range);

                if ctx == 0 {
                    XCloseDisplay(dpy);
                    return false;
                }

                // We need a separate connection for XRecordEnableContext
                let dpy_data = XOpenDisplay(ptr::null());
                if dpy_data.is_null() {
                    XRecordFreeContext(dpy, ctx);
                    XCloseDisplay(dpy);
                    return false;
                }

                let callback_ptr = Arc::into_raw(callback) as *mut c_void;

                extern "C" fn record_callback<F>(
                    closure: *mut c_void,
                    intercept_data: *mut XRecordInterceptData,
                ) where
                    F: Fn(String) + Send + Sync + 'static,
                {
                    unsafe {
                        let data = &*intercept_data;
                        if data.category == 0 && data.data_len >= 32 {
                            // XRecord data starts at offset 0 for key events
                            let raw = std::slice::from_raw_parts(data.data, data.data_len as usize);
                            let event_type = raw[0];
                            let keycode = raw[1];

                            let callback_ref = &*(closure as *const F);
                            match event_type as i32 {
                                2 => {
                                    // KeyPress
                                    callback_ref(format!("{},press", keycode));
                                }
                                3 => {
                                    // KeyRelease
                                    callback_ref(format!("{},release", keycode));
                                }
                                _ => {}
                            }
                        }
                    }
                }

                let result = XRecordEnableContext(
                    dpy_data,
                    ctx,
                    Some(record_callback::<F>),
                    callback_ptr,
                );

                // Cleanup (only reached if XRecordEnableContext returns)
                let _ = result;
                let _ = Arc::from_raw(callback_ptr as *const F);
                XRecordFreeContext(dpy, ctx);
                XCloseDisplay(dpy_data);
                XCloseDisplay(dpy);
            }
            true
        }

        /// Listen using /dev/input/event* devices (requires root or input group)
        fn listen_with_dev_input<F>(callback: Arc<F>)
        where
            F: Fn(String) + Send + Sync + 'static,
        {
            use std::fs;
            use std::io::Read;

            // Find all /dev/input/event* devices
            let mut devices: Vec<String> = Vec::new();
            if let Ok(entries) = fs::read_dir("/dev/input") {
                for entry in entries.flatten() {
                    let name = entry.file_name();
                    let name = name.to_string_lossy();
                    if name.starts_with("event") {
                        devices.push(format!("/dev/input/{}", name));
                    }
                }
            }

            if devices.is_empty() {
                eprintln!("No /dev/input/event* devices found. Try running with sudo or add user to 'input' group.");
                return;
            }

            // Spawn a thread for each device
            let handles: Vec<_> = devices
                .into_iter()
                .map(|dev_path| {
                    let cb = callback.clone();
                    std::thread::spawn(move || {
                        let mut file = match fs::File::open(&dev_path) {
                            Ok(f) => f,
                            Err(_) => return,
                        };

                        // input_event struct: struct timeval (16 bytes) + type (2) + code (2) + value (4)
                        let mut buf = [0u8; 24];
                        loop {
                            match file.read_exact(&mut buf) {
                                Ok(_) => {
                                    // Parse event
                                    let event_type = u16::from_ne_bytes([buf[16], buf[17]]);
                                    let code = u16::from_ne_bytes([buf[18], buf[19]]);
                                    let value = i32::from_ne_bytes([buf[20], buf[21], buf[22], buf[23]]);

                                    // EV_KEY = 0x01
                                    if event_type == 0x01 {
                                        match value {
                                            1 => cb(format!("{},press", code)),
                                            0 => cb(format!("{},release", code)),
                                            2 => {} // key repeat, ignore
                                            _ => {}
                                        }
                                    }
                                }
                                Err(_) => break,
                            }
                        }
                    })
                })
                .collect();

            for h in handles {
                let _ = h.join();
            }
        }

        /// Listen to keyboard events in a specific window.
        /// Uses XInput2 extension to capture key events on the target window.
        /// If `window_name` is None, listens on the currently focused window.
        ///
        /// ```rust
        /// use std::sync::Arc;
        /// use doe::keyboard::listen_keyboard_in_window;
        /// // Listen in the currently focused window
        /// listen_keyboard_in_window(None, Arc::new(|key| {
        ///     println!("Key: {}", key);
        /// }));
        /// // Listen in a specific window by name
        /// listen_keyboard_in_window(Some("Firefox"), Arc::new(|key| {
        ///     println!("Key: {}", key);
        /// }));
        /// ```
        pub fn listen_keyboard_in_window<F>(window_name: Option<&str>, callback: Arc<F>)
        where
            F: Fn(String) + Send + Sync + 'static,
        {
            let dpy = match open_display() {
                Some(d) => d,
                None => return,
            };

            let target_window = if let Some(name) = window_name {
                match find_window_by_name(dpy, name) {
                    Some(w) => w,
                    None => {
                        eprintln!("Window '{}' not found", name);
                        unsafe { XCloseDisplay(dpy) };
                        return;
                    }
                }
            } else {
                let mut win: Window = 0;
                let mut revert: i32 = 0;
                unsafe { XGetInputFocus(dpy, &mut win, &mut revert) };
                win
            };

            // Use XSelectInput to listen for KeyPressMask | KeyReleaseMask on the target window
            const KEY_PRESS_MASK: i64 = 1 << 0;   // KeyPressMask
            const KEY_RELEASE_MASK: i64 = 1 << 1; // KeyReleaseMask

            unsafe {
                XSelectInput(dpy, target_window, KEY_PRESS_MASK | KEY_RELEASE_MASK);
            }

            let callback_ref = callback;
            let dpy_wrapped = DisplayPtr::new(dpy);
            std::thread::spawn(move || {
                let dpy = dpy_wrapped.get();
                // Use Vec<u8> as XEvent buffer to avoid moving !Send *mut c_void across threads
                let mut event_buf: Vec<u8> = vec![0u8; 96];

                loop {
                    unsafe {
                        XNextEvent(dpy, event_buf.as_mut_ptr() as *mut XEvent);
                        let event_type = i32::from_ne_bytes(event_buf[0..4].try_into().unwrap_or([0; 4]));
                        if event_type == 2 || event_type == 3 {
                            // Read keycode from XKeyEvent at the known offset
                            // XKeyEvent layout on x86_64:
                            //   type(4) + serial(8) + send_event(4) + pad(4) + display(8) + window(8) +
                            //   root(8) + subwindow(8) + time(8) + x(4) + y(4) + x_root(4) + y_root(4) +
                            //   state(4) + keycode(1) = offset 80
                            let keycode = event_buf[80];
                            let action = if event_type == 2 { "press" } else { "release" };
                            callback_ref(format!("{},{}", keycode, action));
                        }
                    }
                }
            });
        }

        /// Find a window by its name (title) using recursive search
        fn find_window_by_name(dpy: *mut Display, name: &str) -> Option<Window> {
            let root = unsafe { XDefaultRootWindow(dpy) };
            let wm_name = unsafe { XInternAtom(dpy, b"WM_NAME\0".as_ptr() as *const i8, 0) };
            let utf8_name = unsafe { XInternAtom(dpy, b"_NET_WM_NAME\0".as_ptr() as *const i8, 0) };
            let string_type = unsafe { XInternAtom(dpy, b"STRING\0".as_ptr() as *const i8, 0) };
            let utf8_string = unsafe { XInternAtom(dpy, b"UTF8_STRING\0".as_ptr() as *const i8, 0) };

            fn search(
                dpy: *mut Display,
                win: Window,
                name: &str,
                wm_name: Atom,
                utf8_name: Atom,
                string_type: Atom,
                utf8_string: Atom,
            ) -> Option<Window> {
                // Check this window's name
                let mut actual_type: Atom = 0;
                let mut actual_format: i32 = 0;
                let mut nitems: u64 = 0;
                let mut bytes_after: u64 = 0;
                let mut data: *mut u8 = ptr::null_mut();

                unsafe {
                    // Try _NET_WM_NAME first (UTF8)
                    if XGetWindowProperty(
                        dpy, win, utf8_name, 0, 1024, FALSE, utf8_string,
                        &mut actual_type, &mut actual_format, &mut nitems,
                        &mut bytes_after, &mut data,
                    ) == 0 && !data.is_null() && nitems > 0
                    {
                        let slice = std::slice::from_raw_parts(data, nitems as usize);
                        if let Ok(s) = std::str::from_utf8(slice) {
                            if s.contains(name) {
                                XFree(data as *mut c_void);
                                return Some(win);
                            }
                        }
                        XFree(data as *mut c_void);
                    }

                    // Try WM_NAME
                    data = ptr::null_mut();
                    if XGetWindowProperty(
                        dpy, win, wm_name, 0, 1024, FALSE, string_type,
                        &mut actual_type, &mut actual_format, &mut nitems,
                        &mut bytes_after, &mut data,
                    ) == 0 && !data.is_null() && nitems > 0
                    {
                        let slice = std::slice::from_raw_parts(data, nitems as usize);
                        if let Ok(s) = std::str::from_utf8(slice) {
                            if s.contains(name) {
                                XFree(data as *mut c_void);
                                return Some(win);
                            }
                        }
                        XFree(data as *mut c_void);
                    }

                    // Recurse into children
                    let mut root_ret: Window = 0;
                    let mut parent: Window = 0;
                    let mut children: *mut Window = ptr::null_mut();
                    let mut nchildren: u32 = 0;

                    if XQueryTree(dpy, win, &mut root_ret, &mut parent, &mut children, &mut nchildren) != 0
                        && !children.is_null()
                    {
                        let child_slice = std::slice::from_raw_parts(children, nchildren as usize);
                        for &child in child_slice {
                            if let Some(found) = search(dpy, child, name, wm_name, utf8_name, string_type, utf8_string) {
                                XFree(children as *mut c_void);
                                return Some(found);
                            }
                        }
                        XFree(children as *mut c_void);
                    }
                }
                None
            }

            search(dpy, root, name, wm_name, utf8_name, string_type, utf8_string)
        }

        /// Exit the program when Escape key is pressed (global listener).
        pub fn exit_if_click_esc() {
            listen_keyboard_callback(Arc::new(|key| {
                if key == "9,press" || key == "1,press" {
                    // keycode 9 = Escape in X11
                    std::process::exit(0);
                }
            }));
        }

        /// Get the X11 keycode for a key name string.
        /// Returns None if the key cannot be mapped.
        ///
        /// ```rust
        /// use doe::keyboard::get_keycode;
        /// if let Some(kc) = get_keycode("a") {
        ///     println!("Keycode for 'a': {}", kc);
        /// }
        /// ```
        pub fn get_keycode(key: &str) -> Option<u8> {
            let dpy = open_display()?;
            let kc = str_to_keycode(dpy, key);
            unsafe { XCloseDisplay(dpy) };
            kc
        }

        /// Get the key name for an X11 keycode.
        /// Returns None if the keycode cannot be mapped.
        pub fn get_keyname(keycode: u8) -> Option<String> {
            let dpy = open_display()?;
            unsafe {
                let keysym = XKeycodeToKeysym(dpy, keycode, 0);
                if keysym == 0 {
                    XCloseDisplay(dpy);
                    return None;
                }
                // Convert keysym to name by checking known mappings
                let name = keysym_to_name(keysym);
                XCloseDisplay(dpy);
                name
            }
        }

        fn keysym_to_name(keysym: KeySym) -> Option<String> {
            // Common X11 keysym mappings
            let name = match keysym {
                0x0020 => "space",
                0x0021 => "!",
                0x0022 => "\"",
                0x0023 => "#",
                0x0024 => "$",
                0x0025 => "%",
                0x0026 => "&",
                0x0027 => "'",
                0x0028 => "(",
                0x0029 => ")",
                0x002a => "*",
                0x002b => "+",
                0x002c => ",",
                0x002d => "-",
                0x002e => ".",
                0x002f => "/",
                0x0030..=0x0039 => return Some((((keysym - 0x0030) as u8 + b'0') as char).to_string()),
                0x003a => ":",
                0x003b => ";",
                0x003c => "<",
                0x003d => "=",
                0x003e => ">",
                0x003f => "?",
                0x0040 => "@",
                0x0041..=0x005a => return Some((((keysym - 0x0040) as u8 + b'@') as char).to_string()),
                0x005b => "[",
                0x005c => "\\",
                0x005d => "]",
                0x005e => "^",
                0x005f => "_",
                0x0060 => "`",
                0x0061..=0x007a => return Some((((keysym - 0x0060) as u8 + b'`') as char).to_string()),
                0x007b => "{",
                0x007c => "|",
                0x007d => "}",
                0x007e => "~",
                0xff08 => "backspace",
                0xff09 => "tab",
                0xff0a => "linefeed",
                0xff0d => "return",
                0xff1b => "escape",
                0xff50 => "home",
                0xff51 => "left",
                0xff52 => "up",
                0xff53 => "right",
                0xff54 => "down",
                0xff55 => "page_up",
                0xff56 => "page_down",
                0xff57 => "end",
                0xff60 => "select",
                0xff61 => "print",
                0xff63 => "insert",
                0xff65 => "undo",
                0xff6a => "help",
                0xff7f => "num_lock",
                0xff80 => "kp_space",
                0xff8d => "kp_enter",
                0xff95 => "kp_home",
                0xff96 => "kp_left",
                0xff97 => "kp_up",
                0xff98 => "kp_right",
                0xff99 => "kp_down",
                0xff9a => "kp_page_up",
                0xff9b => "kp_page_down",
                0xff9c => "kp_end",
                0xff9e => "kp_insert",
                0xff9f => "kp_delete",
                0xffaa => "kp_multiply",
                0xffab => "kp_add",
                0xffad => "kp_subtract",
                0xffae => "kp_decimal",
                0xffaf => "kp_divide",
                0xffb0..=0xffb9 => return Some(format!("kp_{}", keysym - 0xffb0)),
                0xffbe..=0xffd1 => return Some(format!("f{}", keysym - 0xffbe + 1)),
                0xffe1 => "shift_l",
                0xffe2 => "shift_r",
                0xffe3 => "control_l",
                0xffe4 => "control_r",
                0xffe5 => "caps_lock",
                0xffe7 => "meta_l",
                0xffe8 => "meta_r",
                0xffe9 => "alt_l",
                0xffea => "alt_r",
                0xffeb => "super_l",
                0xffec => "super_r",
                0xffed => "hyper_l",
                0xffee => "hyper_r",
                0xffff => "delete",
                _ => return None,
            };
            Some(name.to_string())
        }
    }

    #[cfg(target_os = "macos")]
    pub mod macos {
        use core_foundation::base::TCFTypeRef;

        /// ```ignore
        /// "a" => Self::A,
        /// "b" => Self::B,
        /// "c" => Self::C,
        /// "d" => Self::D,
        /// "e" => Self::E,
        /// "f" => Self::F,
        /// "g" => Self::G,
        /// "h" => Self::H,
        /// "i" => Self::I,
        /// "j" => Self::J,
        /// "k" => Self::K,
        /// "l" => Self::L,
        /// "m" => Self::M,
        /// "n" => Self::N,
        /// "o" => Self::O,
        /// "p" => Self::P,
        /// "q" => Self::Q,
        /// "r" => Self::R,
        /// "s" => Self::S,
        /// "t" => Self::T,
        /// "u" => Self::U,
        /// "v" => Self::V,
        /// "w" => Self::W,
        /// "x" => Self::X,
        /// "y" => Self::Y,
        /// "z" => Self::Z,
        /// "0" => Self::NUM_0,
        /// "1" => Self::NUM_1,
        /// "2" => Self::NUM_2,
        /// "3" => Self::NUM_3,
        /// "4" => Self::NUM_4,
        /// "5" => Self::NUM_5,
        /// "6" => Self::NUM_6,
        /// "7" => Self::NUM_7,
        /// "8" => Self::NUM_8,
        /// "9" => Self::NUM_9,
        /// "f1" => Self::F1,
        /// "f2" => Self::F2,
        /// "f3" => Self::F3,
        /// "f4" => Self::F4,
        /// "f5" => Self::F5,
        /// "f6" => Self::F6,
        /// "f7" => Self::F7,
        /// "f8" => Self::F8,
        /// "f9" => Self::F9,
        /// "f10" => Self::F10,
        /// "f11" => Self::F11,
        /// "f12" => Self::F12,
        /// "f13"=>Self::F13,
        /// "f14"=>Self::F14,
        /// "f15"=>Self::F15,
        /// "f16"=>Self::F16,
        /// "f17"=>Self::F17,
        /// "f18"=>Self::F18,
        /// "f19"=>Self::F19,
        /// "20"=>Self::F20,
        /// "help"=>Self::HELP,
        /// "home"=>Self::HOME,
        /// "page_up"=>Self::PAGE_UP,
        /// "forward_delete"=>Self::FORWARD_DELETE,
        /// "end"=>Self::END,
        /// "page_down"=>Self::PAGE_DOWN,
        /// "left_arrow"=>Self::LEFT_ARROW,
        /// "right_arrow"=>Self::RIGHT_ARROW,
        /// "down_arrow"=>Self::DOWN_ARROW,
        /// "up_arrow"=>Self::UP_ARROW,
        /// "*"=>Self::SIGN_MUL,
        /// "+"=>Self::SIGN_ADD,
        /// "-"=>Self::SIGN_SUB,
        /// "."=>Self::SIGN_DOT,
        /// "/"=>Self::SIGN_DIV,
        /// "{"=>Self::LeftBracket,
        /// "}"=>Self::LeftBracket,
        /// "enter"=>Self::RETURN,
        /// "tab"=>Self::TAB,
        /// "space"=>Self::SPACE,
        /// "delete"=>Self::DELETE,
        /// "esc"=>Self::ESC,
        /// "command"=>Self::COMMAND,
        /// "shift"=>Self::SHIFT,
        /// "caps_lock"=>Self::CAPS_LOCK,
        /// "option"=>Self::OPTION,
        /// "ctrl"=>Self::CONTROL,
        /// "right_command"=>Self::RIGHT_COMMAND,
        /// "right_shift"=>Self::RIGHT_SHIFT,
        /// "right_option"=>Self::RIGHT_OPTION,
        /// "right_control"=>Self::RIGHT_CONTROL,
        /// "function"=>Self::FUNCTION,
        /// "volume_up"=>Self::VOLUME_UP,
        /// "volume_down"=>Self::VOLUME_DOWN,
        /// "mute"=>Self::MUTE,
        ///```
        /// # key_click
        /// ```ignore
        /// use doe::keyboard::key_click;
        /// use doe::mouse::move_to_press_left;
        /// use doe::*;
        /// move_to_press_left(726, 348).sleep(0.1);
        /// key_click("command+a");
        /// key_click("command+c");
        /// key_click("2027 command+a");
        /// key_click("command+shift+p");
        /// ```
        pub fn key_click(key: &str) {
            use crate::keyboard::KeyCode;
            use crate::traits::traits::Str;
            let key_vec = key.split_to_vec(" ");
            let keycode = KeyCode::default();
            for key in key_vec.iter() {
                if key == "+" {
                    let keycode = keycode.string_to_keycode(key.to_string());
                    key_press(keycode);
                    key_release(keycode);
                } else if key.contains("+") {
                    for key in key.split_to_vec("+") {
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_press(keycode);
                    }
                    for key in key.split_to_vec("+") {
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_release(keycode);
                    }
                } else {
                    for key in key.chars() {
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_press(keycode);
                        key_release(keycode);
                    }
                }
            }
        }

        /// ## keyboard example
        /// ```rust
        ///    use doe::keyboard::key_press;
        ///    use doe::keyboard::key_release;
        ///    use doe::keyboard::listen_mouse_position;
        ///    use doe::keyboard::get_mouse_position;
        ///
        ///    use doe::keyboard::KeyCode;
        ///    key_press(KeyCode::COMMAND);
        ///    key_press(KeyCode::V);
        ///    key_release(KeyCode::V);
        /// ```
        #[cfg(target_os = "macos")]
        pub fn key_press(keycode: u16) {
            use core_graphics::event::CGKeyCode;
            use core_graphics::event::{CGEvent, CGEventFlags, CGEventTapLocation};
            use core_graphics::event_source::CGEventSource;
            use core_graphics::event_source::CGEventSourceStateID;
            let state_id: CGEventSourceStateID = CGEventSourceStateID::HIDSystemState;
            let source: CGEventSource = CGEventSource::new(state_id).unwrap();
            let new_keycode: CGKeyCode = keycode;
            let event = CGEvent::new_keyboard_event(source, new_keycode, true).unwrap();
            event.set_flags(CGEventFlags::CGEventFlagCommand);
            event.post(CGEventTapLocation::HID);
        }
        /// ## keyboard example
        /// ```rust
        ///fn main(){
        ///    use doe::keyboard::key_press;
        ///    use doe::keyboard::key_release;
        ///    use doe::keyboard::listen_mouse_position;
        ///    use doe::keyboard::get_mouse_position;
        ///
        ///    use doe::keyboard::KeyCode;
        ///    key_press(KeyCode::COMMAND);
        ///    key_press(KeyCode::V);
        ///    key_release(KeyCode::V);
        ///}
        /// ```

        #[cfg(target_os = "macos")]
        pub fn key_release(keycode: u16) {
            use core_graphics::event::CGKeyCode;
            use core_graphics::event::{CGEvent, CGEventFlags, CGEventTapLocation};
            use core_graphics::event_source::CGEventSource;
            use core_graphics::event_source::CGEventSourceStateID;
            let state_id: CGEventSourceStateID = CGEventSourceStateID::HIDSystemState;
            let source: CGEventSource = CGEventSource::new(state_id).unwrap();
            let new_keycode: CGKeyCode = keycode;
            let event = CGEvent::new_keyboard_event(source, new_keycode, false).unwrap();
            event.set_flags(CGEventFlags::CGEventFlagCommand);
            event.post(CGEventTapLocation::HID);
        }
        /// must use cocoa implement
        /// 使用 Cocoa 实现的退出函数
        pub fn exit_if_click_esc() {
            // 导入所需的 Cocoa 模块和类型
            use cocoa::appkit::{NSApp, NSApplication, NSEvent, NSEventType};
            use cocoa::base::id;
        }
    }

    #[cfg(target_os = "windows")]
    pub mod windows {
        use crate::{keyboard::KeyCode, DebugPrint, Print, Sleep, Str};
        use std::sync::{atomic::AtomicU32, Arc, Mutex};

        ///exit_if_click_esc
        /// ```rust
        /// use std::thread;
        /// use doe::keyboard::exit_if_click_esc;
        /// let t1 = std::thread::spawn(move || {
        ///     loop {
        ///         println!("rust");
        ///     }
        /// });
        /// let t2 = std::thread::spawn(move || {
        ///     exit_if_click_esc();
        /// });
        /// t1.join().unwrap();
        /// t2.join().unwrap();
        /// ```

        pub fn exit_if_click_esc() {
            use std::sync::mpsc::channel;
            use std::sync::Arc;
            use std::thread;

            let (tx, rx) = channel();
            let t1 = thread::spawn(move || loop {
                if let Ok(r) = rx.recv() {
                    if r == 1 {
                        let _ = std::fs::remove_file("./.press_release_callback");
                        std::process::exit(0);
                    }
                }
            });

            let t2 = thread::spawn(move || {
                use crate::keyboard::listen_keyboard_callback;
                let _ = std::fs::remove_file("./.press_release_callback");

                listen_keyboard_callback(Arc::new(move |a| {
                    if a == "27,press" {
                        tx.send(1).unwrap();
                    }
                }));
            });

            t1.join().unwrap();
            t2.join().unwrap();
        }

        pub fn exit_if_click_esc_with_callback<F>(callback: std::sync::Arc<F>)
        where
            F: Fn() + std::marker::Sync + std::marker::Send + 'static,
        {
            use std::sync::mpsc::channel;
            use std::sync::Arc;
            use std::thread;

            let (tx, rx) = channel();
            let t1 = thread::spawn(move || loop {
                if let Ok(r) = rx.recv() {
                    if r == 1 {
                        callback();
                        let _ = std::fs::remove_file("./.press_release_callback");
                        std::process::exit(0);
                    }
                }
            });

            let t2 = thread::spawn(move || {
                use crate::keyboard::listen_keyboard_callback;
                listen_keyboard_callback(Arc::new(move |a| {
                    if a == "27,press" {
                        tx.send(1).unwrap();
                    }
                }));
            });

            t1.join().unwrap();
            t2.join().unwrap();
        }

        ///```rust
        ///use doe::keyboard::listen_keyboard_callback;
        ///listen_keyboard_callback(Arc::new( |a|{
        ///    println!("{}",a);
        ///}));
        /// ```

        pub fn listen_keyboard_callback<F>(press_callback: std::sync::Arc<F>)
        where
            F: Fn(String) + std::marker::Sync + std::marker::Send + 'static,
        {
            let t1 = std::thread::spawn(move || {
                use std::ptr;
                use winapi::shared::minwindef::{DWORD, LPARAM, LPVOID, WPARAM};
                use winapi::um::libloaderapi::{
                    FreeLibrary, FreeLibraryAndExitThread, GetModuleHandleW,
                };
                use winapi::um::processthreadsapi::CreateThread;
                use winapi::um::winuser::WM_QUIT;
                use winapi::um::winuser::{
                    CallNextHookEx, DispatchMessageW, GetMessageW, SetWindowsHookExW,
                    TranslateMessage, UnhookWindowsHookEx, KBDLLHOOKSTRUCT, MSG, WH_KEYBOARD_LL,
                };
                let _ = std::fs::remove_file("./.press_release_callback");
                unsafe extern "system" fn keyboard_hook_callback(
                    code: i32,
                    wparam: WPARAM,
                    lparam: LPARAM,
                ) -> LPARAM {
                    if code < 0 {
                        return CallNextHookEx(ptr::null_mut(), code, wparam, lparam);
                    }
                    use std::sync::atomic::Ordering;
                    let kbd_event = *(lparam as *const KBDLLHOOKSTRUCT);
                    let key_code = kbd_event.vkCode;
                    use std::fs::{File, OpenOptions};
                    use std::io::BufWriter;
                    use std::io::Write;
                    let file = OpenOptions::new()
                        .create(true)
                        .append(true)
                        .open("./.press_release_callback")
                        .unwrap();
                    let mut writer = BufWriter::new(file);

                    if wparam == 0x100 || wparam == 0x104 {
                        let new = key_code.to_string().push_back(",press").push_back("\n");
                        writer.write_all(new.as_bytes()).unwrap();
                    } else if wparam == 0x101 || wparam == 0x105 {
                        let new = key_code.to_string().push_back(",release").push_back("\n");
                        writer.write_all(new.as_bytes()).unwrap();
                    }

                    CallNextHookEx(ptr::null_mut(), code, wparam, lparam)
                }

                unsafe extern "system" fn keyboard_hook_thread(_: LPVOID) -> DWORD {
                    let h_instance = GetModuleHandleW(ptr::null_mut());

                    let hook = SetWindowsHookExW(
                        WH_KEYBOARD_LL,
                        Some(keyboard_hook_callback),
                        h_instance,
                        0,
                    );

                    let mut msg: MSG = std::mem::zeroed();
                    loop {
                        let ret = GetMessageW(&mut msg, ptr::null_mut(), 0, 0);
                        if ret == -1 || ret == 0 {
                            break;
                        }
                        if msg.message == WM_QUIT {
                            break;
                        }

                        TranslateMessage(&msg);

                        DispatchMessageW(&msg);
                    }

                    UnhookWindowsHookEx(hook);

                    FreeLibrary(h_instance);

                    0
                }
                unsafe {
                    let h_instance = GetModuleHandleW(ptr::null());
                    let mut thread_id: u32 = 0;
                    let thread_handle = CreateThread(
                        ptr::null_mut(),
                        0,
                        Some(keyboard_hook_thread),
                        h_instance as LPVOID,
                        0,
                        &mut thread_id as *mut _,
                    );

                    if thread_handle.is_null() {
                        panic!("Failed to create thread");
                    }

                    let mut msg = std::mem::zeroed();
                    while GetMessageW(&mut msg, ptr::null_mut(), 0, 0) != 0 {
                        if msg.message == WM_QUIT {
                            break;
                        }
                        TranslateMessage(&msg);

                        DispatchMessageW(&msg);
                    }

                    FreeLibraryAndExitThread(h_instance, 0);
                }
            });

            let t2 = std::thread::spawn(move || -> ! {
                use std::io::BufRead;
                use std::io::BufReader;
                loop {
                    let buf = if let Ok(file) = std::fs::File::open("./.press_release_callback") {
                        let reader = BufReader::new(file);
                        let buf = reader.lines().map(|s| s.unwrap()).collect::<Vec<_>>();
                        buf
                    } else {
                        Vec::new()
                    };
                    ().sleep(0.1);
                    let new_buf = if let Ok(file) = std::fs::File::open("./.press_release_callback")
                    {
                        let reader = BufReader::new(file);
                        let buf = reader.lines().map(|s| s.unwrap()).collect::<Vec<_>>();
                        buf
                    } else {
                        Vec::new()
                    };
                    if new_buf != buf {
                        if let Some(last) = new_buf.last() {
                            press_callback(last.to_string());
                        }
                    }
                }
            });

            t1.join().unwrap();
            t2.join();
        }

        pub fn listen_keybord_append_to_file() {
            use std::ptr;
            use winapi::shared::minwindef::{DWORD, LPARAM, LPVOID, WPARAM};
            use winapi::um::libloaderapi::{
                FreeLibrary, FreeLibraryAndExitThread, GetModuleHandleW,
            };
            use winapi::um::processthreadsapi::CreateThread;
            use winapi::um::winuser::WM_QUIT;
            use winapi::um::winuser::{
                CallNextHookEx, DispatchMessageW, GetMessageW, SetWindowsHookExW, TranslateMessage,
                UnhookWindowsHookEx, KBDLLHOOKSTRUCT, MSG, WH_KEYBOARD_LL,
            };

            unsafe extern "system" fn keyboard_hook_callback(
                code: i32,
                wparam: WPARAM,
                lparam: LPARAM,
            ) -> LPARAM {
                if code < 0 {
                    return CallNextHookEx(ptr::null_mut(), code, wparam, lparam);
                }

                let kbd_event = *(lparam as *const KBDLLHOOKSTRUCT);
                if wparam == 0x100 || wparam == 0x104 {
                    let file_path = "listen_all.bin";
                    if let Ok(_) = crate::append_data_to_file(
                        file_path,
                        format!("key_press({});\n", kbd_event.vkCode),
                    ) {}
                } else if wparam == 0x101 || wparam == 0x105 {
                    let file_path = "listen_all.bin";
                    if let Ok(_) = crate::append_data_to_file(
                        file_path,
                        format!("key_release({});\n", kbd_event.vkCode),
                    ) {}
                }

                CallNextHookEx(ptr::null_mut(), code, wparam, lparam)
            }

            unsafe extern "system" fn keyboard_hook_thread(_: LPVOID) -> DWORD {
                let h_instance = GetModuleHandleW(ptr::null_mut());

                let hook =
                    SetWindowsHookExW(WH_KEYBOARD_LL, Some(keyboard_hook_callback), h_instance, 0);

                let mut msg: MSG = std::mem::zeroed();
                loop {
                    let ret = GetMessageW(&mut msg, ptr::null_mut(), 0, 0);
                    if ret == -1 || ret == 0 {
                        break;
                    }
                    if msg.message == WM_QUIT {
                        break;
                    }
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }

                UnhookWindowsHookEx(hook);

                FreeLibrary(h_instance);

                0
            }
            unsafe {
                let h_instance = GetModuleHandleW(ptr::null());
                let mut thread_id: u32 = 0;
                let thread_handle = CreateThread(
                    ptr::null_mut(),
                    0,
                    Some(keyboard_hook_thread),
                    h_instance as LPVOID,
                    0,
                    &mut thread_id as *mut _,
                );

                if thread_handle.is_null() {
                    panic!("Failed to create thread");
                }

                let mut msg = std::mem::zeroed();
                while GetMessageW(&mut msg, ptr::null_mut(), 0, 0) != 0 {
                    if msg.message == WM_QUIT {
                        break;
                    }
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }

                FreeLibraryAndExitThread(h_instance, 0);
            }
        }

        pub fn listen_keybord() {
            let call = || {};
            use std::ptr;
            use winapi::shared::minwindef::{DWORD, LPARAM, LPVOID, WPARAM};
            use winapi::um::libloaderapi::{
                FreeLibrary, FreeLibraryAndExitThread, GetModuleHandleW,
            };
            use winapi::um::processthreadsapi::CreateThread;
            use winapi::um::winuser::WM_QUIT;
            use winapi::um::winuser::{
                CallNextHookEx, DispatchMessageW, GetMessageW, SetWindowsHookExW, TranslateMessage,
                UnhookWindowsHookEx, KBDLLHOOKSTRUCT, MSG, WH_KEYBOARD_LL,
            };

            unsafe extern "system" fn keyboard_hook_callback(
                code: i32,
                wparam: WPARAM,
                lparam: LPARAM,
            ) -> LPARAM {
                if code < 0 {
                    return CallNextHookEx(ptr::null_mut(), code, wparam, lparam);
                }

                let kbd_event = *(lparam as *const KBDLLHOOKSTRUCT);

                if wparam == 0x100 || wparam == 0x104 {
                    println!("key_press({});", kbd_event.vkCode);
                } else if wparam == 0x101 || wparam == 0x105 {
                    println!("key_release({});", kbd_event.vkCode);
                }

                CallNextHookEx(ptr::null_mut(), code, wparam, lparam)
            }

            unsafe extern "system" fn keyboard_hook_thread(_: LPVOID) -> DWORD {
                let h_instance = GetModuleHandleW(ptr::null_mut());

                let hook =
                    SetWindowsHookExW(WH_KEYBOARD_LL, Some(keyboard_hook_callback), h_instance, 0);

                let mut msg: MSG = std::mem::zeroed();
                loop {
                    let ret = GetMessageW(&mut msg, ptr::null_mut(), 0, 0);
                    if ret == -1 || ret == 0 {
                        break;
                    }
                    if msg.message == WM_QUIT {
                        break;
                    }
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }

                UnhookWindowsHookEx(hook);

                FreeLibrary(h_instance);

                0
            }
            unsafe {
                let h_instance = GetModuleHandleW(ptr::null());
                let mut thread_id: u32 = 0;
                let thread_handle = CreateThread(
                    ptr::null_mut(),
                    0,
                    Some(keyboard_hook_thread),
                    h_instance as LPVOID,
                    0,
                    &mut thread_id as *mut _,
                );

                if thread_handle.is_null() {
                    panic!("Failed to create thread");
                }

                let mut msg = std::mem::zeroed();
                while GetMessageW(&mut msg, ptr::null_mut(), 0, 0) != 0 {
                    if msg.message == WM_QUIT {
                        break;
                    }
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }

                FreeLibraryAndExitThread(h_instance, 0);
            }
        }

        pub fn key_release_keybd_event(keycode: u16) {
            use winapi::um::winuser::keybd_event;

            unsafe {
                keybd_event(keycode as u8, 0, 0x2, 0);
            }
        }
        pub fn key_press_by_keybd_event(keycode: u16) {
            use winapi::um::winuser::keybd_event;
            use winapi::um::winuser::mouse_event;

            unsafe {
                keybd_event(keycode as u8, 0, 0, 0);
            }
        }
        pub fn key_release(keycode: u16) {
            use winapi::shared::minwindef::DWORD;
            use winapi::um::winuser::keybd_event;
            use winapi::um::winuser::{SendInput, INPUT, INPUT_KEYBOARD};
            pub const KEYEVENTF_KEYUP: DWORD = 0x0002;
            unsafe {
                let mut input = INPUT::default();
                input.type_ = INPUT_KEYBOARD;
                input.u.ki_mut().wVk = keycode as _;
                input.u.ki_mut().dwFlags = KEYEVENTF_KEYUP;
                // Simulate key press
                let usent = SendInput(
                    1,                    // Number of inputs
                    &mut input as *mut _, // Pointer to the input array
                    std::mem::size_of::<INPUT>() as i32,
                );
                if usent != 1 {
                    println!("send error");
                }
            }
        }
        ///```ignore
        /// "/"=>{Self::SIGN_DIV},
        /// "."=>{Self::SIGN_DOT},
        /// "-"=>{Self::SIGN_SUB},
        /// "+"=>{Self::SIGN_ADD},
        /// "*"=>{Self::SIGN_MUL},
        /// "a"=>{Self::A},
        /// "b"=>{Self::B},
        /// "c"=>{Self::C},
        /// "d"=>{Self::D},
        /// "e"=>{Self::E},
        /// "f"=>{Self::F},
        /// "g"=>{Self::G},
        /// "h"=>{Self::H},
        /// "i"=>{Self::I},
        /// "j"=>{Self::J},
        /// "k"=>{Self::K},
        /// "l"=>{Self::L},
        /// "m"=>{Self::M},
        /// "n"=>{Self::N},
        /// "o"=>{Self::O},
        /// "p"=>{Self::P},
        /// "q"=>{Self::Q},
        /// "r"=>{Self::R},
        /// "s"=>{Self::S},
        /// "t"=>{Self::T},
        /// "u"=>{Self::U},
        /// "v"=>{Self::V},
        /// "w"=>{Self::W},
        /// "x"=>{Self::X},
        /// "y"=>{Self::Y},
        /// "z"=>{Self::Z},
        /// "0"=>{Self::NUM_0},
        /// "1"=>{Self::NUM_1},
        /// "2"=>{Self::NUM_2},
        /// "3"=>{Self::NUM_3},
        /// "4"=>{Self::NUM_4},
        /// "5"=>{Self::NUM_5},
        /// "6"=>{Self::NUM_6},
        /// "7"=>{Self::NUM_7},
        /// "8"=>{Self::NUM_8},
        /// "9"=>{Self::NUM_9},
        /// "f1"=>{Self::F1},
        /// "f2"=>{Self::F2},
        /// "f3"=>{Self::F3},
        /// "f4"=>{Self::F4},
        /// "f5"=>{Self::F5},
        /// "f6"=>{Self::F6},
        /// "f7"=>{Self::F7},
        /// "f8"=>{Self::F8},
        /// "f9"=>{Self::F9},
        /// "f10"=>{Self::F10},
        /// "f11"=>{Self::F11},
        /// "f12"=>{Self::F12},
        /// "enter"=>{Self::ENTER},
        /// "end"=>{Self::END},
        /// "home"=>{Self::HOME},
        /// "left_arrow"=>{Self::LEFT_ARROW},
        /// "up_arrow"=>{Self::UP_ARROW},
        /// "right_arrow"=>{Self::RIGHT_ARROW},
        /// "down_arrow"=>{Self::DOWN_ARROW},
        /// "insert"=>{Self::INSERT},
        /// "detele"=>{Self::DELETE},
        /// "help"=>{Self::HELP},
        /// "num_lock"=>{Self::NUM_LOCK},
        /// "backspace"=>{Self::BACKSPACE},
        /// "tab"=>{Self::TAB},
        /// "clear"=>{Self::CLEAR},
        /// "shift"=>{Self::SHIFT},
        /// "ctrl"=>{Self::CONTROL},
        /// "alt"=>{Self::ALT},
        /// "caps_lock"=>{Self::CAPS_LOCK},
        /// "esc"=>{Self::ESC},
        /// "spacebar"=>{Self::SPACEBAR},
        /// "page_up"=>{Self::PAGE_UP},
        /// "page_down"=>{Self::PAGE_DOWN},
        /// "windows"=>Self::WINDOWS,
        ///```
        /// # key_click
        ///```ignore
        /// use doe::keyboard::key_click;
        /// use doe::mouse::move_to_press_left;
        /// use doe::*;
        /// move_to_press_left(726, 348).sleep(0.1);
        /// key_click("ctrl+a");
        /// key_click("ctrl+c");
        /// key_click("2027 ctrl+a");
        /// key_click("ctrl+shift+p");
        /// ```
        pub fn key_click(key: &str) {
            let key_vec = key.split_to_vec(" ");
            let keycode = KeyCode::default();
            for key in key_vec.iter() {
                if key == "+" {
                    let keycode = keycode.string_to_keycode(key.to_string());
                    key_press(keycode);
                    key_release(keycode);
                } else if key.contains("+") {
                    for key in key.split_to_vec("+") {
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_press(keycode);
                    }
                    for key in key.split_to_vec("+") {
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_release(keycode);
                    }
                } else {
                    // if key code is 0
                    if keycode.string_to_keycode(key.to_string()) == 0 {
                        for key in key.chars() {
                            let keycode = keycode.string_to_keycode(key.to_string());
                            key_press(keycode);
                            key_release(keycode);
                        }
                    } else {
                        // if key code is not 0
                        let keycode = keycode.string_to_keycode(key.to_string());
                        key_press(keycode);
                        key_release(keycode);
                    }
                }
            }
        }

        pub fn key_press(keycode: u16) {
            use winapi::shared::minwindef::DWORD;
            use winapi::um::winuser::keybd_event;
            use winapi::um::winuser::{SendInput, INPUT, INPUT_KEYBOARD};
            pub const KEYEVENTF_KEYUP: DWORD = 0x0002;
            unsafe {
                let mut input = INPUT::default();
                input.type_ = INPUT_KEYBOARD;
                input.u.ki_mut().wVk = keycode as _;
                input.u.ki_mut().dwFlags = 0; // Press the key

                // Simulate key press
                let usent = SendInput(
                    1,                    // Number of inputs
                    &mut input as *mut _, // Pointer to the input array
                    std::mem::size_of::<INPUT>() as i32,
                );
                if usent != 1 {
                    println!("send error");
                }
            }
        }
    }

    pub use common::*;

    #[cfg(target_os = "linux")]
    pub use linux::*;

    #[cfg(target_os = "macos")]
    pub use macos::*;

    #[cfg(target_os = "windows")]
    pub use windows::*;
}

#[cfg(feature = "keyboard")]
pub use keyboard::*;

///KeyCode struct is struct that contains a set of constants representing keyboard keys on a `Windows` operating system. Each constant is represented by a u16 value, which is the Unicode code point of the key.
#[allow(warnings)]
#[cfg(target_os = "windows")]
#[derive(Debug, Default)]
pub struct KeyCode;
#[cfg(target_os = "windows")]
impl KeyCode {
    /// a
    pub const A: u16 = 65;
    /// b
    pub const B: u16 = 66;
    /// c
    pub const C: u16 = 67;
    /// d
    pub const D: u16 = 68;
    /// e
    pub const E: u16 = 69;
    ///
    pub const F: u16 = 70;
    ///
    pub const G: u16 = 71;
    ///
    pub const H: u16 = 72;
    ///
    pub const I: u16 = 73;
    ///
    pub const J: u16 = 74;
    ///
    pub const K: u16 = 75;
    ///
    pub const L: u16 = 76;
    ///
    pub const M: u16 = 77;
    ///
    pub const N: u16 = 78;
    ///
    pub const O: u16 = 79;
    ///
    pub const P: u16 = 80;
    ///
    pub const Q: u16 = 81;
    ///
    pub const R: u16 = 82;
    ///
    pub const S: u16 = 83;
    ///
    pub const T: u16 = 84;
    ///
    pub const U: u16 = 85;
    ///
    pub const V: u16 = 86;
    ///
    pub const W: u16 = 87;
    ///
    pub const X: u16 = 88;
    ///
    pub const Y: u16 = 89;
    ///
    pub const Z: u16 = 90;
    ///
    pub const NUM_0: u16 = 48;
    ///
    pub const NUM_1: u16 = 49;
    ///
    pub const NUM_2: u16 = 50;
    ///
    pub const NUM_3: u16 = 51;
    ///
    pub const NUM_4: u16 = 52;
    ///
    pub const NUM_5: u16 = 53;
    ///
    pub const NUM_6: u16 = 54;
    ///
    pub const NUM_7: u16 = 55;
    ///
    pub const NUM_8: u16 = 56;
    ///
    pub const NUM_9: u16 = 57;
    ///
    pub const F1: u16 = 112;
    ///
    pub const F2: u16 = 113;
    ///
    pub const F3: u16 = 114;
    ///
    pub const F4: u16 = 115;
    ///
    pub const F5: u16 = 116;
    ///
    pub const F6: u16 = 117;
    ///
    pub const F7: u16 = 118;
    ///
    pub const F8: u16 = 119;
    ///
    pub const F9: u16 = 120;
    ///
    pub const F10: u16 = 121;
    ///
    pub const F11: u16 = 122;
    ///
    pub const F12: u16 = 123;
    ///
    pub const ENTER: u16 = 10;
    ///
    pub const END: u16 = 35;
    ///
    pub const HOME: u16 = 36;
    ///
    pub const LEFT_ARROW: u16 = 37;
    ///
    pub const UP_ARROW: u16 = 38;
    ///
    pub const RIGHT_ARROW: u16 = 39;
    ///
    pub const DOWN_ARROW: u16 = 40;
    ///
    pub const INSERT: u16 = 45;
    ///
    pub const DELETE: u16 = 46;
    ///
    pub const HELP: u16 = 47;
    ///
    pub const NUM_LOCK: u16 = 14;
    ///
    pub const BACKSPACE: u16 = 8;
    ///
    pub const TAB: u16 = 9;
    ///
    pub const CLEAR: u16 = 12;
    ///
    pub const SHIFT: u16 = 16;
    ///
    pub const CONTROL: u16 = 17;
    ///
    pub const ALT: u16 = 18;
    ///
    pub const CAPS_LOCK: u16 = 20;
    ///
    pub const ESC: u16 = 27;
    ///
    pub const SPACEBAR: u16 = 32;
    ///
    pub const PAGE_UP: u16 = 33;
    ///
    pub const PAGE_DOWN: u16 = 3;
    /// *
    pub const SIGN_MUL: u16 = 106; //*
    /// +
    pub const SIGN_ADD: u16 = 107; //+
    /// -
    pub const SIGN_SUB: u16 = 109; //-
    /// .
    pub const SIGN_DOT: u16 = 110; //.
    /// /
    pub const SIGN_DIV: u16 = 111; // \/
    /// WINDOWS
    pub const WINDOWS: u16 = 0x5B;
    #[allow(warnings)]
    fn string_to_keycode(&self, s: String) -> u16 {
        match s.as_str().as_ref() {
            "/" => Self::SIGN_DIV,
            "." => Self::SIGN_DOT,
            "-" => Self::SIGN_SUB,
            "+" => Self::SIGN_ADD,
            "*" => Self::SIGN_MUL,
            "a" => Self::A,
            "b" => Self::B,
            "c" => Self::C,
            "d" => Self::D,
            "e" => Self::E,
            "f" => Self::F,
            "g" => Self::G,
            "h" => Self::H,
            "i" => Self::I,
            "j" => Self::J,
            "k" => Self::K,
            "l" => Self::L,
            "m" => Self::M,
            "n" => Self::N,
            "o" => Self::O,
            "p" => Self::P,
            "q" => Self::Q,
            "r" => Self::R,
            "s" => Self::S,
            "t" => Self::T,
            "u" => Self::U,
            "v" => Self::V,
            "w" => Self::W,
            "x" => Self::X,
            "y" => Self::Y,
            "z" => Self::Z,
            "0" => Self::NUM_0,
            "1" => Self::NUM_1,
            "2" => Self::NUM_2,
            "3" => Self::NUM_3,
            "4" => Self::NUM_4,
            "5" => Self::NUM_5,
            "6" => Self::NUM_6,
            "7" => Self::NUM_7,
            "8" => Self::NUM_8,
            "9" => Self::NUM_9,
            "f1" => Self::F1,
            "f2" => Self::F2,
            "f3" => Self::F3,
            "f4" => Self::F4,
            "f5" => Self::F5,
            "f6" => Self::F6,
            "f7" => Self::F7,
            "f8" => Self::F8,
            "f9" => Self::F9,
            "f10" => Self::F10,
            "f11" => Self::F11,
            "f12" => Self::F12,
            "enter" => Self::ENTER,
            "end" => Self::END,
            "home" => Self::HOME,
            "left_arrow" => Self::LEFT_ARROW,
            "up_arrow" => Self::UP_ARROW,
            "right_arrow" => Self::RIGHT_ARROW,
            "down_arrow" => Self::DOWN_ARROW,
            "insert" => Self::INSERT,
            "detele" => Self::DELETE,
            "help" => Self::HELP,
            "num_lock" => Self::NUM_LOCK,
            "backspace" => Self::BACKSPACE,
            "tab" => Self::TAB,
            "clear" => Self::CLEAR,
            "shift" => Self::SHIFT,
            "ctrl" => Self::CONTROL,
            "alt" => Self::ALT,
            "caps_lock" => Self::CAPS_LOCK,
            "esc" => Self::ESC,
            "spacebar" => Self::SPACEBAR,
            "page_up" => Self::PAGE_UP,
            "page_down" => Self::PAGE_DOWN,
            "windows" => Self::WINDOWS,
            _ => 0,
        }
    }
}

///KeyCode struct is struct that contains a set of constants representing keyboard keys on a `macos` operating system. Each constant is represented by a u16 value, which is the Unicode code point of the key.
#[allow(warnings)]
#[cfg(target_os = "macos")]
#[derive(Debug, Default)]
pub struct KeyCode;
#[allow(warnings)]
#[cfg(target_os = "macos")]
impl KeyCode {
    pub const SIGN_MUL: u16 = 0x6A; //*
    pub const SIGN_ADD: u16 = 0x6B; //+
    pub const SIGN_SUB: u16 = 0x2D; //+
    pub const SIGN_DOT: u16 = 0x2E; //.
    pub const SIGN_DIV: u16 = 0x2F; // \/
    pub const LeftBracket: u16 = 0x2B;
    pub const RightBracket: u16 = 0x30;
    pub const RETURN: u16 = 0x24;
    pub const TAB: u16 = 0x30;
    pub const SPACE: u16 = 0x31;
    pub const DELETE: u16 = 0x33;
    pub const ESC: u16 = 0x35;
    pub const COMMAND: u16 = 0x37;
    pub const SHIFT: u16 = 0x38;
    pub const CAPS_LOCK: u16 = 0x39;
    pub const OPTION: u16 = 0x3A;
    pub const CONTROL: u16 = 0x3B;
    pub const RIGHT_COMMAND: u16 = 0x36;
    pub const RIGHT_SHIFT: u16 = 0x3C;
    pub const RIGHT_OPTION: u16 = 0x3D;
    pub const RIGHT_CONTROL: u16 = 0x3E;
    pub const FUNCTION: u16 = 0x3F;
    pub const VOLUME_UP: u16 = 0x48;
    pub const VOLUME_DOWN: u16 = 0x49;
    pub const MUTE: u16 = 0x4A;
    pub const F1: u16 = 0x7A;
    pub const F2: u16 = 0x78;
    pub const F3: u16 = 0x63;
    pub const F4: u16 = 0x76;
    pub const F5: u16 = 0x60;
    pub const F6: u16 = 0x61;
    pub const F7: u16 = 0x62;
    pub const F8: u16 = 0x64;
    pub const F9: u16 = 0x65;
    pub const F10: u16 = 0x6D;
    pub const F11: u16 = 0x67;
    pub const F12: u16 = 0x6F;
    pub const F13: u16 = 0x69;
    pub const F14: u16 = 0x6B;
    pub const F15: u16 = 0x71;
    pub const F16: u16 = 0x6A;
    pub const F17: u16 = 0x40;
    pub const F18: u16 = 0x4F;
    pub const F19: u16 = 0x50;
    pub const F20: u16 = 0x5A;
    pub const HELP: u16 = 0x72;
    pub const HOME: u16 = 0x73;
    pub const PAGE_UP: u16 = 0x74;
    pub const FORWARD_DELETE: u16 = 0x75;
    pub const END: u16 = 0x77;
    pub const PAGE_DOWN: u16 = 0x79;
    pub const LEFT_ARROW: u16 = 0x7B;
    pub const RIGHT_ARROW: u16 = 0x7C;
    pub const DOWN_ARROW: u16 = 0x7D;
    pub const UP_ARROW: u16 = 0x7E;

    // 字母 A-Z
    pub const A: u16 = 0x00;
    pub const B: u16 = 0x0B;
    pub const C: u16 = 0x08;
    pub const D: u16 = 0x02;
    pub const E: u16 = 0x0E;
    pub const F: u16 = 0x03;
    pub const G: u16 = 0x05;
    pub const H: u16 = 0x04;
    pub const I: u16 = 0x22;
    pub const J: u16 = 0x26;
    pub const K: u16 = 0x28;
    pub const L: u16 = 0x25;
    pub const M: u16 = 0x2E;
    pub const N: u16 = 0x2D;
    pub const O: u16 = 0x1F;
    pub const P: u16 = 0x23;
    pub const Q: u16 = 0x0C;
    pub const R: u16 = 0x0F;
    pub const S: u16 = 0x01;
    pub const T: u16 = 0x11;
    pub const U: u16 = 0x20;
    pub const V: u16 = 0x09;
    pub const W: u16 = 0x0D;
    pub const X: u16 = 0x07;
    pub const Y: u16 = 0x10;
    pub const Z: u16 = 0x06;

    // 数字 0-9
    pub const NUM_0: u16 = 0x1D;
    pub const NUM_1: u16 = 0x12;
    pub const NUM_2: u16 = 0x13;
    pub const NUM_3: u16 = 0x14;
    pub const NUM_4: u16 = 0x15;
    pub const NUM_5: u16 = 0x17;
    pub const NUM_6: u16 = 0x16;
    pub const NUM_7: u16 = 0x1A;
    pub const NUM_8: u16 = 0x1C;
    pub const NUM_9: u16 = 0x19;

    #[allow(warnings)]
    fn string_to_keycode(&self, s: String) -> u16 {
        match s.as_str().as_ref() {
            "a" => Self::A,
            "b" => Self::B,
            "c" => Self::C,
            "d" => Self::D,
            "e" => Self::E,
            "f" => Self::F,
            "g" => Self::G,
            "h" => Self::H,
            "i" => Self::I,
            "j" => Self::J,
            "k" => Self::K,
            "l" => Self::L,
            "m" => Self::M,
            "n" => Self::N,
            "o" => Self::O,
            "p" => Self::P,
            "q" => Self::Q,
            "r" => Self::R,
            "s" => Self::S,
            "t" => Self::T,
            "u" => Self::U,
            "v" => Self::V,
            "w" => Self::W,
            "x" => Self::X,
            "y" => Self::Y,
            "z" => Self::Z,
            "0" => Self::NUM_0,
            "1" => Self::NUM_1,
            "2" => Self::NUM_2,
            "3" => Self::NUM_3,
            "4" => Self::NUM_4,
            "5" => Self::NUM_5,
            "6" => Self::NUM_6,
            "7" => Self::NUM_7,
            "8" => Self::NUM_8,
            "9" => Self::NUM_9,
            "f1" => Self::F1,
            "f2" => Self::F2,
            "f3" => Self::F3,
            "f4" => Self::F4,
            "f5" => Self::F5,
            "f6" => Self::F6,
            "f7" => Self::F7,
            "f8" => Self::F8,
            "f9" => Self::F9,
            "f10" => Self::F10,
            "f11" => Self::F11,
            "f12" => Self::F12,
            "f13" => Self::F13,
            "f14" => Self::F14,
            "f15" => Self::F15,
            "f16" => Self::F16,
            "f17" => Self::F17,
            "f18" => Self::F18,
            "f19" => Self::F19,
            "20" => Self::F20,
            "help" => Self::HELP,
            "home" => Self::HOME,
            "page_up" => Self::PAGE_UP,
            "forward_delete" => Self::FORWARD_DELETE,
            "end" => Self::END,
            "page_down" => Self::PAGE_DOWN,
            "left_arrow" => Self::LEFT_ARROW,
            "right_arrow" => Self::RIGHT_ARROW,
            "down_arrow" => Self::DOWN_ARROW,
            "up_arrow" => Self::UP_ARROW,
            "*" => Self::SIGN_MUL,
            "+" => Self::SIGN_ADD,
            "-" => Self::SIGN_SUB,
            "." => Self::SIGN_DOT,
            "/" => Self::SIGN_DIV,
            "{" => Self::LeftBracket,
            "}" => Self::LeftBracket,
            "enter" => Self::RETURN,
            "tab" => Self::TAB,
            "space" => Self::SPACE,
            "delete" => Self::DELETE,
            "esc" => Self::ESC,
            "command" => Self::COMMAND,
            "shift" => Self::SHIFT,
            "caps_lock" => Self::CAPS_LOCK,
            "option" => Self::OPTION,
            "ctrl" => Self::CONTROL,
            "right_command" => Self::RIGHT_COMMAND,
            "right_shift" => Self::RIGHT_SHIFT,
            "right_option" => Self::RIGHT_OPTION,
            "right_control" => Self::RIGHT_CONTROL,
            "function" => Self::FUNCTION,
            "volume_up" => Self::VOLUME_UP,
            "volume_down" => Self::VOLUME_DOWN,
            "mute" => Self::MUTE,
            _ => 0,
        }
    }
}

///KeyCode struct is struct that contains a set of constants representing keyboard keys on a `linux` operating system.
/// These are X11 keycodes (hardware scan codes mapped by X server). The actual keycode values
/// may vary depending on the keyboard layout, but these are the standard values for a typical
/// PC keyboard with US layout on X11.
#[allow(warnings)]
#[cfg(target_os = "linux")]
#[derive(Debug, Default)]
pub struct KeyCode;
#[allow(warnings)]
#[cfg(target_os = "linux")]
impl KeyCode {
    // Letters (X11 keycodes for standard US keyboard layout)
    pub const A: u16 = 38;
    pub const B: u16 = 56;
    pub const C: u16 = 54;
    pub const D: u16 = 40;
    pub const E: u16 = 26;
    pub const F: u16 = 41;
    pub const G: u16 = 42;
    pub const H: u16 = 43;
    pub const I: u16 = 31;
    pub const J: u16 = 44;
    pub const K: u16 = 45;
    pub const L: u16 = 46;
    pub const M: u16 = 58;
    pub const N: u16 = 57;
    pub const O: u16 = 32;
    pub const P: u16 = 33;
    pub const Q: u16 = 24;
    pub const R: u16 = 27;
    pub const S: u16 = 39;
    pub const T: u16 = 28;
    pub const U: u16 = 30;
    pub const V: u16 = 55;
    pub const W: u16 = 25;
    pub const X: u16 = 53;
    pub const Y: u16 = 29;
    pub const Z: u16 = 52;

    // Numbers
    pub const NUM_0: u16 = 19;
    pub const NUM_1: u16 = 10;
    pub const NUM_2: u16 = 11;
    pub const NUM_3: u16 = 12;
    pub const NUM_4: u16 = 13;
    pub const NUM_5: u16 = 14;
    pub const NUM_6: u16 = 15;
    pub const NUM_7: u16 = 16;
    pub const NUM_8: u16 = 17;
    pub const NUM_9: u16 = 18;

    // Function keys
    pub const F1: u16 = 67;
    pub const F2: u16 = 68;
    pub const F3: u16 = 69;
    pub const F4: u16 = 70;
    pub const F5: u16 = 71;
    pub const F6: u16 = 72;
    pub const F7: u16 = 73;
    pub const F8: u16 = 74;
    pub const F9: u16 = 75;
    pub const F10: u16 = 76;
    pub const F11: u16 = 95;
    pub const F12: u16 = 96;
    pub const F13: u16 = 191;
    pub const F14: u16 = 192;
    pub const F15: u16 = 193;
    pub const F16: u16 = 194;
    pub const F17: u16 = 195;
    pub const F18: u16 = 196;
    pub const F19: u16 = 197;
    pub const F20: u16 = 198;

    // Modifiers
    pub const SHIFT: u16 = 50;
    pub const SHIFT_L: u16 = 50;
    pub const SHIFT_R: u16 = 62;
    pub const CONTROL: u16 = 37;
    pub const CONTROL_L: u16 = 37;
    pub const CONTROL_R: u16 = 105;
    pub const ALT: u16 = 64;
    pub const ALT_L: u16 = 64;
    pub const ALT_R: u16 = 108;
    pub const SUPER: u16 = 133;
    pub const SUPER_L: u16 = 133;
    pub const SUPER_R: u16 = 134;
    pub const CAPS_LOCK: u16 = 66;
    pub const NUM_LOCK: u16 = 77;
    pub const SCROLL_LOCK: u16 = 78;

    // Navigation & editing
    pub const RETURN: u16 = 36;
    pub const ENTER: u16 = 36;
    pub const ESCAPE: u16 = 9;
    pub const ESC: u16 = 9;
    pub const BACKSPACE: u16 = 22;
    pub const TAB: u16 = 23;
    pub const SPACE: u16 = 65;
    pub const SPACEBAR: u16 = 65;
    pub const DELETE: u16 = 119;
    pub const FORWARD_DELETE: u16 = 119;
    pub const HOME: u16 = 110;
    pub const END: u16 = 115;
    pub const PAGE_UP: u16 = 112;
    pub const PAGE_DOWN: u16 = 117;
    pub const INSERT: u16 = 118;

    // Arrow keys
    pub const LEFT_ARROW: u16 = 113;
    pub const RIGHT_ARROW: u16 = 114;
    pub const UP_ARROW: u16 = 111;
    pub const DOWN_ARROW: u16 = 116;

    // Keypad
    pub const KP_0: u16 = 90;
    pub const KP_1: u16 = 87;
    pub const KP_2: u16 = 88;
    pub const KP_3: u16 = 89;
    pub const KP_4: u16 = 83;
    pub const KP_5: u16 = 84;
    pub const KP_6: u16 = 85;
    pub const KP_7: u16 = 79;
    pub const KP_8: u16 = 80;
    pub const KP_9: u16 = 81;
    pub const KP_ENTER: u16 = 104;
    pub const KP_ADD: u16 = 86;
    pub const KP_SUBTRACT: u16 = 82;
    pub const KP_MULTIPLY: u16 = 63;
    pub const KP_DIVIDE: u16 = 106;
    pub const KP_DECIMAL: u16 = 91;

    // Special keys
    pub const PRINT: u16 = 107;
    pub const PAUSE: u16 = 127;
    pub const MENU: u16 = 135;
    pub const HELP: u16 = 146;

    // Legacy aliases (for backwards compatibility with macOS-style names)
    pub const COMMAND: u16 = 133;
    pub const OPTION: u16 = 64;
    pub const RIGHT_COMMAND: u16 = 134;
    pub const RIGHT_SHIFT: u16 = 62;
    pub const RIGHT_OPTION: u16 = 108;
    pub const RIGHT_CONTROL: u16 = 105;
    pub const FUNCTION: u16 = 199;

    #[allow(warnings)]
    fn string_to_keycode(&self, s: String) -> u16 {
        match s.as_str() {
            "a" => Self::A,
            "b" => Self::B,
            "c" => Self::C,
            "d" => Self::D,
            "e" => Self::E,
            "f" => Self::F,
            "g" => Self::G,
            "h" => Self::H,
            "i" => Self::I,
            "j" => Self::J,
            "k" => Self::K,
            "l" => Self::L,
            "m" => Self::M,
            "n" => Self::N,
            "o" => Self::O,
            "p" => Self::P,
            "q" => Self::Q,
            "r" => Self::R,
            "s" => Self::S,
            "t" => Self::T,
            "u" => Self::U,
            "v" => Self::V,
            "w" => Self::W,
            "x" => Self::X,
            "y" => Self::Y,
            "z" => Self::Z,
            "0" => Self::NUM_0,
            "1" => Self::NUM_1,
            "2" => Self::NUM_2,
            "3" => Self::NUM_3,
            "4" => Self::NUM_4,
            "5" => Self::NUM_5,
            "6" => Self::NUM_6,
            "7" => Self::NUM_7,
            "8" => Self::NUM_8,
            "9" => Self::NUM_9,
            "f1" => Self::F1,
            "f2" => Self::F2,
            "f3" => Self::F3,
            "f4" => Self::F4,
            "f5" => Self::F5,
            "f6" => Self::F6,
            "f7" => Self::F7,
            "f8" => Self::F8,
            "f9" => Self::F9,
            "f10" => Self::F10,
            "f11" => Self::F11,
            "f12" => Self::F12,
            "enter" | "return" => Self::ENTER,
            "end" => Self::END,
            "home" => Self::HOME,
            "left_arrow" | "left" => Self::LEFT_ARROW,
            "up_arrow" | "up" => Self::UP_ARROW,
            "right_arrow" | "right" => Self::RIGHT_ARROW,
            "down_arrow" | "down" => Self::DOWN_ARROW,
            "insert" => Self::INSERT,
            "delete" => Self::DELETE,
            "help" => Self::HELP,
            "num_lock" => Self::NUM_LOCK,
            "backspace" => Self::BACKSPACE,
            "tab" => Self::TAB,
            "space" | "spacebar" => Self::SPACEBAR,
            "page_up" | "pageup" => Self::PAGE_UP,
            "page_down" | "pagedown" => Self::PAGE_DOWN,
            "shift" => Self::SHIFT,
            "ctrl" | "control" => Self::CONTROL,
            "alt" | "option" => Self::ALT,
            "super" | "win" | "windows" | "command" | "meta" => Self::SUPER,
            "caps_lock" => Self::CAPS_LOCK,
            "esc" | "escape" => Self::ESCAPE,
            "print" | "printscreen" => Self::PRINT,
            "pause" => Self::PAUSE,
            "menu" | "apps" => Self::MENU,
            "scroll_lock" => Self::SCROLL_LOCK,
            _ => 0,
        }
    }
}
