dos_like/
input.rs

1//! Module for keyboard and mouse input functions.
2
3use dos_like_sys::{keycode_t, KEY_MODIFIER_RELEASED};
4use smallvec::SmallVec;
5
6/// A key code object.
7///
8/// See the various associated constants for specific keys.
9#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
10#[repr(transparent)]
11pub struct KeyCode(keycode_t);
12
13impl From<KeyCode> for u32 {
14    // ignore false positive from clippy,
15    // as we c_uint might not always be u32
16    #[allow(clippy::unnecessary_cast)]
17    fn from(key: KeyCode) -> u32 {
18        key.0 as u32
19    }
20}
21
22/// Checks whether a key is currently pushed (down).
23pub fn key_state(key: KeyCode) -> bool {
24    unsafe { dos_like_sys::keystate(key.0) != 0 }
25}
26
27/// A key press/release event.
28///
29/// This new type exists so as to make a distinction
30/// between an event that is either a key press or a key release,
31/// and a plain key code which identifies a key on a keyboard ([`KeyCode`]).
32///
33/// See the various associated constants for specific keys.
34#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
35#[repr(transparent)]
36pub struct KeyEvent(keycode_t);
37
38impl KeyEvent {
39    /// Returns the key code of this event,
40    /// without the release modifier.
41    #[inline]
42    pub fn key_code(self) -> KeyCode {
43        KeyCode(self.0 & 0x7FFF_FFFF)
44    }
45
46    /// Checks whether this event is a key press.
47    #[inline]
48    pub fn is_pressed(self) -> bool {
49        !self.is_released()
50    }
51
52    /// Checks whether this event is a key release.
53    #[inline]
54    pub fn is_released(self) -> bool {
55        (self.0 & KEY_MODIFIER_RELEASED) != 0
56    }
57}
58
59/// Reads the key press events available
60/// and saves them in an array.
61///
62/// This creates an independent copy of the keys,
63/// consuming the underlying buffer in the process.
64pub fn read_keys() -> SmallVec<[KeyEvent; 2]> {
65    let mut keys = SmallVec::new();
66
67    // Safety: readkeys is a valid pointer
68    // to a null terminated sequence of keycode_t
69    unsafe {
70        let p = dos_like_sys::readkeys();
71        for i in 0..=255 {
72            let c = *p.offset(i);
73            if c == 0 {
74                break;
75            }
76            keys.push(KeyEvent(c));
77        }
78    }
79
80    keys
81}
82
83/// Reads the character input events available
84/// and saves them in an array.
85///
86/// This creates an independent copy of the characters,
87/// consuming the underlying buffer in the process.
88pub fn read_chars() -> SmallVec<[u8; 4]> {
89    let mut keys = SmallVec::new();
90
91    // Safety: readchars is a valid pointer
92    // to a null terminated sequence of bytes
93    unsafe {
94        let p = dos_like_sys::readchars();
95        for i in 0..=255 {
96            let c = *p.offset(i);
97            if c == 0 {
98                break;
99            }
100            keys.push(c as u8);
101        }
102    }
103
104    keys
105}
106
107/// Gets the absolute mouse position on the X axis.
108pub fn mouse_x() -> i32 {
109    unsafe { dos_like_sys::mousex() }
110}
111
112/// Gets the absolute mouse position on the Y axis.
113pub fn mouse_y() -> i32 {
114    unsafe { dos_like_sys::mousey() }
115}
116
117/// Gets the mouse relative position
118/// since the last internal application loop
119/// on the X axis.
120pub fn mouse_rel_x() -> i32 {
121    unsafe { dos_like_sys::mouserelx() }
122}
123
124/// Gets the mouse relative position
125/// since the last internal application loop
126/// on the Y axis.
127pub fn mouse_rel_y() -> i32 {
128    unsafe { dos_like_sys::mouserely() }
129}
130
131impl KeyCode {
132    pub const KEY_INVALID: Self = KeyCode(dos_like_sys::keycode_t_KEY_INVALID);
133    pub const KEY_LBUTTON: Self = KeyCode(dos_like_sys::keycode_t_KEY_LBUTTON);
134    pub const KEY_RBUTTON: Self = KeyCode(dos_like_sys::keycode_t_KEY_RBUTTON);
135    pub const KEY_CANCEL: Self = KeyCode(dos_like_sys::keycode_t_KEY_CANCEL);
136    pub const KEY_MBUTTON: Self = KeyCode(dos_like_sys::keycode_t_KEY_MBUTTON);
137    pub const KEY_XBUTTON1: Self = KeyCode(dos_like_sys::keycode_t_KEY_XBUTTON1);
138    pub const KEY_XBUTTON2: Self = KeyCode(dos_like_sys::keycode_t_KEY_XBUTTON2);
139    pub const KEY_BACK: Self = KeyCode(dos_like_sys::keycode_t_KEY_BACK);
140    pub const KEY_TAB: Self = KeyCode(dos_like_sys::keycode_t_KEY_TAB);
141    pub const KEY_CLEAR: Self = KeyCode(dos_like_sys::keycode_t_KEY_CLEAR);
142    pub const KEY_RETURN: Self = KeyCode(dos_like_sys::keycode_t_KEY_RETURN);
143    pub const KEY_SHIFT: Self = KeyCode(dos_like_sys::keycode_t_KEY_SHIFT);
144    pub const KEY_CONTROL: Self = KeyCode(dos_like_sys::keycode_t_KEY_CONTROL);
145    pub const KEY_MENU: Self = KeyCode(dos_like_sys::keycode_t_KEY_MENU);
146    pub const KEY_PAUSE: Self = KeyCode(dos_like_sys::keycode_t_KEY_PAUSE);
147    pub const KEY_CAPITAL: Self = KeyCode(dos_like_sys::keycode_t_KEY_CAPITAL);
148    pub const KEY_KANA: Self = KeyCode(dos_like_sys::keycode_t_KEY_KANA);
149    pub const KEY_HANGUL: Self = KeyCode(dos_like_sys::keycode_t_KEY_HANGUL);
150    pub const KEY_JUNJA: Self = KeyCode(dos_like_sys::keycode_t_KEY_JUNJA);
151    pub const KEY_FINAL: Self = KeyCode(dos_like_sys::keycode_t_KEY_FINAL);
152    pub const KEY_HANJA: Self = KeyCode(dos_like_sys::keycode_t_KEY_HANJA);
153    pub const KEY_KANJI: Self = KeyCode(dos_like_sys::keycode_t_KEY_KANJI);
154    pub const KEY_ESCAPE: Self = KeyCode(dos_like_sys::keycode_t_KEY_ESCAPE);
155    pub const KEY_CONVERT: Self = KeyCode(dos_like_sys::keycode_t_KEY_CONVERT);
156    pub const KEY_NONCONVERT: Self = KeyCode(dos_like_sys::keycode_t_KEY_NONCONVERT);
157    pub const KEY_ACCEPT: Self = KeyCode(dos_like_sys::keycode_t_KEY_ACCEPT);
158    pub const KEY_MODECHANGE: Self = KeyCode(dos_like_sys::keycode_t_KEY_MODECHANGE);
159    pub const KEY_SPACE: Self = KeyCode(dos_like_sys::keycode_t_KEY_SPACE);
160    pub const KEY_PRIOR: Self = KeyCode(dos_like_sys::keycode_t_KEY_PRIOR);
161    pub const KEY_NEXT: Self = KeyCode(dos_like_sys::keycode_t_KEY_NEXT);
162    pub const KEY_END: Self = KeyCode(dos_like_sys::keycode_t_KEY_END);
163    pub const KEY_HOME: Self = KeyCode(dos_like_sys::keycode_t_KEY_HOME);
164    pub const KEY_LEFT: Self = KeyCode(dos_like_sys::keycode_t_KEY_LEFT);
165    pub const KEY_UP: Self = KeyCode(dos_like_sys::keycode_t_KEY_UP);
166    pub const KEY_RIGHT: Self = KeyCode(dos_like_sys::keycode_t_KEY_RIGHT);
167    pub const KEY_DOWN: Self = KeyCode(dos_like_sys::keycode_t_KEY_DOWN);
168    pub const KEY_SELECT: Self = KeyCode(dos_like_sys::keycode_t_KEY_SELECT);
169    pub const KEY_PRINT: Self = KeyCode(dos_like_sys::keycode_t_KEY_PRINT);
170    pub const KEY_EXEC: Self = KeyCode(dos_like_sys::keycode_t_KEY_EXEC);
171    pub const KEY_SNAPSHOT: Self = KeyCode(dos_like_sys::keycode_t_KEY_SNAPSHOT);
172    pub const KEY_INSERT: Self = KeyCode(dos_like_sys::keycode_t_KEY_INSERT);
173    pub const KEY_DELETE: Self = KeyCode(dos_like_sys::keycode_t_KEY_DELETE);
174    pub const KEY_HELP: Self = KeyCode(dos_like_sys::keycode_t_KEY_HELP);
175    pub const KEY_0: Self = KeyCode(dos_like_sys::keycode_t_KEY_0);
176    pub const KEY_1: Self = KeyCode(dos_like_sys::keycode_t_KEY_1);
177    pub const KEY_2: Self = KeyCode(dos_like_sys::keycode_t_KEY_2);
178    pub const KEY_3: Self = KeyCode(dos_like_sys::keycode_t_KEY_3);
179    pub const KEY_4: Self = KeyCode(dos_like_sys::keycode_t_KEY_4);
180    pub const KEY_5: Self = KeyCode(dos_like_sys::keycode_t_KEY_5);
181    pub const KEY_6: Self = KeyCode(dos_like_sys::keycode_t_KEY_6);
182    pub const KEY_7: Self = KeyCode(dos_like_sys::keycode_t_KEY_7);
183    pub const KEY_8: Self = KeyCode(dos_like_sys::keycode_t_KEY_8);
184    pub const KEY_9: Self = KeyCode(dos_like_sys::keycode_t_KEY_9);
185    pub const KEY_A: Self = KeyCode(dos_like_sys::keycode_t_KEY_A);
186    pub const KEY_B: Self = KeyCode(dos_like_sys::keycode_t_KEY_B);
187    pub const KEY_C: Self = KeyCode(dos_like_sys::keycode_t_KEY_C);
188    pub const KEY_D: Self = KeyCode(dos_like_sys::keycode_t_KEY_D);
189    pub const KEY_E: Self = KeyCode(dos_like_sys::keycode_t_KEY_E);
190    pub const KEY_F: Self = KeyCode(dos_like_sys::keycode_t_KEY_F);
191    pub const KEY_G: Self = KeyCode(dos_like_sys::keycode_t_KEY_G);
192    pub const KEY_H: Self = KeyCode(dos_like_sys::keycode_t_KEY_H);
193    pub const KEY_I: Self = KeyCode(dos_like_sys::keycode_t_KEY_I);
194    pub const KEY_J: Self = KeyCode(dos_like_sys::keycode_t_KEY_J);
195    pub const KEY_K: Self = KeyCode(dos_like_sys::keycode_t_KEY_K);
196    pub const KEY_L: Self = KeyCode(dos_like_sys::keycode_t_KEY_L);
197    pub const KEY_M: Self = KeyCode(dos_like_sys::keycode_t_KEY_M);
198    pub const KEY_N: Self = KeyCode(dos_like_sys::keycode_t_KEY_N);
199    pub const KEY_O: Self = KeyCode(dos_like_sys::keycode_t_KEY_O);
200    pub const KEY_P: Self = KeyCode(dos_like_sys::keycode_t_KEY_P);
201    pub const KEY_Q: Self = KeyCode(dos_like_sys::keycode_t_KEY_Q);
202    pub const KEY_R: Self = KeyCode(dos_like_sys::keycode_t_KEY_R);
203    pub const KEY_S: Self = KeyCode(dos_like_sys::keycode_t_KEY_S);
204    pub const KEY_T: Self = KeyCode(dos_like_sys::keycode_t_KEY_T);
205    pub const KEY_U: Self = KeyCode(dos_like_sys::keycode_t_KEY_U);
206    pub const KEY_V: Self = KeyCode(dos_like_sys::keycode_t_KEY_V);
207    pub const KEY_W: Self = KeyCode(dos_like_sys::keycode_t_KEY_W);
208    pub const KEY_X: Self = KeyCode(dos_like_sys::keycode_t_KEY_X);
209    pub const KEY_Y: Self = KeyCode(dos_like_sys::keycode_t_KEY_Y);
210    pub const KEY_Z: Self = KeyCode(dos_like_sys::keycode_t_KEY_Z);
211    pub const KEY_LWIN: Self = KeyCode(dos_like_sys::keycode_t_KEY_LWIN);
212    pub const KEY_RWIN: Self = KeyCode(dos_like_sys::keycode_t_KEY_RWIN);
213    pub const KEY_APPS: Self = KeyCode(dos_like_sys::keycode_t_KEY_APPS);
214    pub const KEY_SLEEP: Self = KeyCode(dos_like_sys::keycode_t_KEY_SLEEP);
215    pub const KEY_NUMPAD0: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD0);
216    pub const KEY_NUMPAD1: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD1);
217    pub const KEY_NUMPAD2: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD2);
218    pub const KEY_NUMPAD3: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD3);
219    pub const KEY_NUMPAD4: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD4);
220    pub const KEY_NUMPAD5: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD5);
221    pub const KEY_NUMPAD6: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD6);
222    pub const KEY_NUMPAD7: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD7);
223    pub const KEY_NUMPAD8: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD8);
224    pub const KEY_NUMPAD9: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMPAD9);
225    pub const KEY_MULTIPLY: Self = KeyCode(dos_like_sys::keycode_t_KEY_MULTIPLY);
226    pub const KEY_ADD: Self = KeyCode(dos_like_sys::keycode_t_KEY_ADD);
227    pub const KEY_SEPARATOR: Self = KeyCode(dos_like_sys::keycode_t_KEY_SEPARATOR);
228    pub const KEY_SUBTRACT: Self = KeyCode(dos_like_sys::keycode_t_KEY_SUBTRACT);
229    pub const KEY_DECIMAL: Self = KeyCode(dos_like_sys::keycode_t_KEY_DECIMAL);
230    pub const KEY_DIVIDE: Self = KeyCode(dos_like_sys::keycode_t_KEY_DIVIDE);
231    pub const KEY_F1: Self = KeyCode(dos_like_sys::keycode_t_KEY_F1);
232    pub const KEY_F2: Self = KeyCode(dos_like_sys::keycode_t_KEY_F2);
233    pub const KEY_F3: Self = KeyCode(dos_like_sys::keycode_t_KEY_F3);
234    pub const KEY_F4: Self = KeyCode(dos_like_sys::keycode_t_KEY_F4);
235    pub const KEY_F5: Self = KeyCode(dos_like_sys::keycode_t_KEY_F5);
236    pub const KEY_F6: Self = KeyCode(dos_like_sys::keycode_t_KEY_F6);
237    pub const KEY_F7: Self = KeyCode(dos_like_sys::keycode_t_KEY_F7);
238    pub const KEY_F8: Self = KeyCode(dos_like_sys::keycode_t_KEY_F8);
239    pub const KEY_F9: Self = KeyCode(dos_like_sys::keycode_t_KEY_F9);
240    pub const KEY_F10: Self = KeyCode(dos_like_sys::keycode_t_KEY_F10);
241    pub const KEY_F11: Self = KeyCode(dos_like_sys::keycode_t_KEY_F11);
242    pub const KEY_F12: Self = KeyCode(dos_like_sys::keycode_t_KEY_F12);
243    pub const KEY_F13: Self = KeyCode(dos_like_sys::keycode_t_KEY_F13);
244    pub const KEY_F14: Self = KeyCode(dos_like_sys::keycode_t_KEY_F14);
245    pub const KEY_F15: Self = KeyCode(dos_like_sys::keycode_t_KEY_F15);
246    pub const KEY_F16: Self = KeyCode(dos_like_sys::keycode_t_KEY_F16);
247    pub const KEY_F17: Self = KeyCode(dos_like_sys::keycode_t_KEY_F17);
248    pub const KEY_F18: Self = KeyCode(dos_like_sys::keycode_t_KEY_F18);
249    pub const KEY_F19: Self = KeyCode(dos_like_sys::keycode_t_KEY_F19);
250    pub const KEY_F20: Self = KeyCode(dos_like_sys::keycode_t_KEY_F20);
251    pub const KEY_F21: Self = KeyCode(dos_like_sys::keycode_t_KEY_F21);
252    pub const KEY_F22: Self = KeyCode(dos_like_sys::keycode_t_KEY_F22);
253    pub const KEY_F23: Self = KeyCode(dos_like_sys::keycode_t_KEY_F23);
254    pub const KEY_F24: Self = KeyCode(dos_like_sys::keycode_t_KEY_F24);
255    pub const KEY_NUMLOCK: Self = KeyCode(dos_like_sys::keycode_t_KEY_NUMLOCK);
256    pub const KEY_SCROLL: Self = KeyCode(dos_like_sys::keycode_t_KEY_SCROLL);
257    pub const KEY_LSHIFT: Self = KeyCode(dos_like_sys::keycode_t_KEY_LSHIFT);
258    pub const KEY_RSHIFT: Self = KeyCode(dos_like_sys::keycode_t_KEY_RSHIFT);
259    pub const KEY_LCONTROL: Self = KeyCode(dos_like_sys::keycode_t_KEY_LCONTROL);
260    pub const KEY_RCONTROL: Self = KeyCode(dos_like_sys::keycode_t_KEY_RCONTROL);
261    pub const KEY_LMENU: Self = KeyCode(dos_like_sys::keycode_t_KEY_LMENU);
262    pub const KEY_RMENU: Self = KeyCode(dos_like_sys::keycode_t_KEY_RMENU);
263    pub const KEY_BROWSER_BACK: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_BACK);
264    pub const KEY_BROWSER_FORWARD: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_FORWARD);
265    pub const KEY_BROWSER_REFRESH: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_REFRESH);
266    pub const KEY_BROWSER_STOP: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_STOP);
267    pub const KEY_BROWSER_SEARCH: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_SEARCH);
268    pub const KEY_BROWSER_FAVORITES: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_FAVORITES);
269    pub const KEY_BROWSER_HOME: Self = KeyCode(dos_like_sys::keycode_t_KEY_BROWSER_HOME);
270    pub const KEY_VOLUME_MUTE: Self = KeyCode(dos_like_sys::keycode_t_KEY_VOLUME_MUTE);
271    pub const KEY_VOLUME_DOWN: Self = KeyCode(dos_like_sys::keycode_t_KEY_VOLUME_DOWN);
272    pub const KEY_VOLUME_UP: Self = KeyCode(dos_like_sys::keycode_t_KEY_VOLUME_UP);
273    pub const KEY_MEDIA_NEXT_TRACK: Self = KeyCode(dos_like_sys::keycode_t_KEY_MEDIA_NEXT_TRACK);
274    pub const KEY_MEDIA_PREV_TRACK: Self = KeyCode(dos_like_sys::keycode_t_KEY_MEDIA_PREV_TRACK);
275    pub const KEY_MEDIA_STOP: Self = KeyCode(dos_like_sys::keycode_t_KEY_MEDIA_STOP);
276    pub const KEY_MEDIA_PLAY_PAUSE: Self = KeyCode(dos_like_sys::keycode_t_KEY_MEDIA_PLAY_PAUSE);
277    pub const KEY_LAUNCH_MAIL: Self = KeyCode(dos_like_sys::keycode_t_KEY_LAUNCH_MAIL);
278    pub const KEY_LAUNCH_MEDIA_SELECT: Self =
279        KeyCode(dos_like_sys::keycode_t_KEY_LAUNCH_MEDIA_SELECT);
280    pub const KEY_LAUNCH_APP1: Self = KeyCode(dos_like_sys::keycode_t_KEY_LAUNCH_APP1);
281    pub const KEY_LAUNCH_APP2: Self = KeyCode(dos_like_sys::keycode_t_KEY_LAUNCH_APP2);
282    pub const KEY_OEM_1: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_1);
283    pub const KEY_OEM_PLUS: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_PLUS);
284    pub const KEY_OEM_COMMA: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_COMMA);
285    pub const KEY_OEM_MINUS: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_MINUS);
286    pub const KEY_OEM_PERIOD: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_PERIOD);
287    pub const KEY_OEM_2: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_2);
288    pub const KEY_OEM_3: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_3);
289    pub const KEY_OEM_4: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_4);
290    pub const KEY_OEM_5: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_5);
291    pub const KEY_OEM_6: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_6);
292    pub const KEY_OEM_7: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_7);
293    pub const KEY_OEM_8: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_8);
294    pub const KEY_OEM_102: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_102);
295    pub const KEY_PROCESSKEY: Self = KeyCode(dos_like_sys::keycode_t_KEY_PROCESSKEY);
296    pub const KEY_ATTN: Self = KeyCode(dos_like_sys::keycode_t_KEY_ATTN);
297    pub const KEY_CRSEL: Self = KeyCode(dos_like_sys::keycode_t_KEY_CRSEL);
298    pub const KEY_EXSEL: Self = KeyCode(dos_like_sys::keycode_t_KEY_EXSEL);
299    pub const KEY_EREOF: Self = KeyCode(dos_like_sys::keycode_t_KEY_EREOF);
300    pub const KEY_PLAY: Self = KeyCode(dos_like_sys::keycode_t_KEY_PLAY);
301    pub const KEY_ZOOM: Self = KeyCode(dos_like_sys::keycode_t_KEY_ZOOM);
302    pub const KEY_NONAME: Self = KeyCode(dos_like_sys::keycode_t_KEY_NONAME);
303    pub const KEY_PA1: Self = KeyCode(dos_like_sys::keycode_t_KEY_PA1);
304    pub const KEY_OEM_CLEAR: Self = KeyCode(dos_like_sys::keycode_t_KEY_OEM_CLEAR);
305    pub const KEYCOUNT: Self = KeyCode(dos_like_sys::keycode_t_KEYCOUNT);
306}