Skip to main content

openloaf_rdev/
codes_conv.rs

1#[cfg(target_os = "linux")]
2use crate::keycodes::linux::key_from_code as linux_key_from_code;
3#[cfg(target_os = "macos")]
4use crate::keycodes::macos::key_from_code as macos_key_from_code;
5use crate::keycodes::macos::virtual_keycodes::*;
6#[cfg(target_os = "windows")]
7use crate::keycodes::windows::key_from_scancode as win_key_from_scancode;
8#[cfg(target_os = "macos")]
9use crate::macos::map_keycode;
10use crate::{
11    keycodes::{
12        android::code_from_key as android_code_from_key,
13        linux::code_from_key as linux_code_from_key, macos::code_from_key as macos_code_from_key,
14        usb_hid::key_from_code as usb_hid_key_from_code,
15        windows::scancode_from_key as win_scancode_from_key,
16    },
17    Key, KeyCode,
18};
19
20macro_rules! conv_keycodes {
21    ($fnname:ident, $key_from_code:ident, $code_from_key:ident) => {
22        pub fn $fnname(code: u32) -> Option<KeyCode> {
23            let key = $key_from_code(code as _);
24            match key {
25                Key::Unknown(..) => None,
26                Key::RawKey(..) => None,
27                _ => $code_from_key(key).map(|c| c as KeyCode),
28            }
29        }
30    };
31}
32
33#[allow(non_upper_case_globals)]
34fn macos_iso_code_from_key(key: Key) -> Option<KeyCode> {
35    match macos_code_from_key(key)? {
36        kVK_ISO_Section => Some(kVK_ANSI_Grave),
37        kVK_ANSI_Grave => Some(kVK_ISO_Section),
38        code => Some(code as _),
39    }
40}
41
42#[cfg(target_os = "macos")]
43#[allow(non_upper_case_globals)]
44fn macos_keycode_from_code_(code: KeyCode) -> Key {
45    macos_key_from_code(map_keycode(code))
46}
47
48#[cfg(target_os = "windows")]
49conv_keycodes!(
50    win_scancode_to_linux_code,
51    win_key_from_scancode,
52    linux_code_from_key
53);
54#[cfg(target_os = "windows")]
55conv_keycodes!(
56    win_scancode_to_macos_code,
57    win_key_from_scancode,
58    macos_code_from_key
59);
60#[cfg(target_os = "windows")]
61// From Win scancode to MacOS keycode(ISO Layout)
62conv_keycodes!(
63    win_scancode_to_macos_iso_code,
64    win_key_from_scancode,
65    macos_iso_code_from_key
66);
67#[cfg(target_os = "windows")]
68// From Win scancode to android keycode
69conv_keycodes!(
70    win_scancode_to_android_key_code,
71    win_key_from_scancode,
72    android_code_from_key
73);
74#[cfg(target_os = "linux")]
75conv_keycodes!(
76    linux_code_to_win_scancode,
77    linux_key_from_code,
78    win_scancode_from_key
79);
80#[cfg(target_os = "linux")]
81conv_keycodes!(
82    linux_code_to_macos_code,
83    linux_key_from_code,
84    macos_code_from_key
85);
86#[cfg(target_os = "linux")]
87// From Linux scancode to MacOS keycode(ISO Layout)
88conv_keycodes!(
89    linux_code_to_macos_iso_code,
90    linux_key_from_code,
91    macos_iso_code_from_key
92);
93#[cfg(target_os = "linux")]
94conv_keycodes!(
95    linux_code_to_android_key_code,
96    linux_key_from_code,
97    android_code_from_key
98);
99#[cfg(target_os = "macos")]
100conv_keycodes!(
101    macos_code_to_win_scancode,
102    macos_keycode_from_code_,
103    win_scancode_from_key
104);
105#[cfg(target_os = "macos")]
106conv_keycodes!(
107    macos_code_to_linux_code,
108    macos_keycode_from_code_,
109    linux_code_from_key
110);
111#[cfg(target_os = "macos")]
112conv_keycodes!(
113    macos_code_to_android_key_code,
114    macos_keycode_from_code_,
115    android_code_from_key
116);
117conv_keycodes!(
118    usb_hid_code_to_win_scancode,
119    usb_hid_key_from_code,
120    win_scancode_from_key
121);
122conv_keycodes!(
123    usb_hid_code_to_linux_code,
124    usb_hid_key_from_code,
125    linux_code_from_key
126);
127conv_keycodes!(
128    usb_hid_code_to_macos_code,
129    usb_hid_key_from_code,
130    macos_code_from_key
131);
132conv_keycodes!(
133    usb_hid_code_to_macos_iso_code,
134    usb_hid_key_from_code,
135    macos_iso_code_from_key
136);
137conv_keycodes!(
138    usb_hid_code_to_android_key_code,
139    usb_hid_key_from_code,
140    android_code_from_key
141);
142
143#[cfg(test)]
144mod test {
145    #[test]
146    fn test_usb_hid_code_to_macos_code() {
147        for code in 0..=65535 {
148            let key = crate::keycodes::macos::key_from_code(code);
149            if matches!(key, crate::Key::Unknown(..) | crate::Key::RawKey(..)) {
150                continue;
151            }
152            let usb_hid = crate::keycodes::usb_hid::code_from_key(key);
153            if let Some(usb_hid) = usb_hid {
154                if usb_hid == 0 {
155                    continue;
156                }
157                if let Some(code2) = super::usb_hid_code_to_macos_code(usb_hid) {
158                    assert_eq!(code, code2 as u32)
159                } else {
160                    assert!(false, "We could not convert back code: {:?}", code);
161                }
162            }
163        }
164    }
165
166    #[test]
167    fn test_usb_hid_code_to_windows_scan_code() {
168        for code in 1..=65535 {
169            let key = crate::keycodes::windows::key_from_scancode(code);
170            if matches!(key, crate::Key::Unknown(..) | crate::Key::RawKey(..)) {
171                continue;
172            }
173            let usb_hid = crate::keycodes::usb_hid::code_from_key(key);
174            if let Some(usb_hid) = usb_hid {
175                if usb_hid == 0 {
176                    continue;
177                }
178                if let Some(code2) = super::usb_hid_code_to_win_scancode(usb_hid) {
179                    assert_eq!(code, code2 as u32)
180                } else {
181                    assert!(false, "We could not convert back code: {:?}", code);
182                }
183            }
184        }
185    }
186
187    #[test]
188    fn test_usb_hid_code_to_linux_key_code() {
189        for code in 0..=65535 {
190            let key = crate::keycodes::linux::key_from_code(code);
191            if matches!(key, crate::Key::Unknown(..) | crate::Key::RawKey(..)) {
192                continue;
193            }
194            let usb_hid = crate::keycodes::usb_hid::code_from_key(key);
195            if let Some(usb_hid) = usb_hid {
196                if usb_hid == 0 {
197                    continue;
198                }
199                if let Some(code2) = super::usb_hid_code_to_linux_code(usb_hid) {
200                    assert_eq!(code, code2 as u32)
201                } else {
202                    assert!(false, "We could not convert back code: {:?}", code);
203                }
204            }
205        }
206    }
207}