1#![allow(clippy::bad_bit_mask)]
3
4use crate::rect::Rect;
5use crate::video::Window;
6use crate::EventPump;
7
8use std::fmt;
9use std::iter::FilterMap;
10use std::mem::transmute;
11
12use crate::sys;
13
14mod keycode;
15mod scancode;
16pub use self::keycode::Keycode;
17pub use self::scancode::Scancode;
18
19bitflags! {
20 pub struct Mod: u16 {
21 const NOMOD = 0x0000;
22 const LSHIFTMOD = 0x0001;
23 const RSHIFTMOD = 0x0002;
24 const LCTRLMOD = 0x0040;
25 const RCTRLMOD = 0x0080;
26 const LALTMOD = 0x0100;
27 const RALTMOD = 0x0200;
28 const LGUIMOD = 0x0400;
29 const RGUIMOD = 0x0800;
30 const NUMMOD = 0x1000;
31 const CAPSMOD = 0x2000;
32 const MODEMOD = 0x4000;
33 const RESERVEDMOD = 0x8000;
34 }
35}
36
37impl fmt::Display for Mod {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 write!(f, "{:04x}", *self)
40 }
41}
42
43pub struct KeyboardState<'a> {
44 keyboard_state: &'a [u8],
45}
46
47impl<'a> KeyboardState<'a> {
48 #[doc(alias = "SDL_GetKeyboardState")]
49 pub fn new(_e: &'a EventPump) -> KeyboardState<'a> {
50 let keyboard_state = unsafe {
51 let mut count = 0;
52 let state_ptr = sys::SDL_GetKeyboardState(&mut count);
53
54 ::std::slice::from_raw_parts(state_ptr, count as usize)
55 };
56
57 KeyboardState { keyboard_state }
58 }
59
60 pub fn is_scancode_pressed(&self, scancode: Scancode) -> bool {
71 self.keyboard_state[scancode as i32 as usize] != 0
72 }
73
74 pub fn scancodes(&self) -> ScancodeIterator {
76 ScancodeIterator {
77 index: 0,
78 keyboard_state: self.keyboard_state,
79 }
80 }
81
82 pub fn pressed_scancodes(&self) -> PressedScancodeIterator {
106 self.scancodes().into_pressed_scancode_iter()
107 }
108}
109
110pub struct ScancodeIterator<'a> {
111 index: i32,
112 keyboard_state: &'a [u8],
113}
114
115impl<'a> Iterator for ScancodeIterator<'a> {
116 type Item = (Scancode, bool);
117
118 fn next(&mut self) -> Option<(Scancode, bool)> {
119 if self.index < self.keyboard_state.len() as i32 {
120 let index = self.index;
121 self.index += 1;
122
123 if let Some(scancode) = Scancode::from_i32(index) {
124 let pressed = self.keyboard_state[index as usize] != 0;
125
126 Some((scancode, pressed))
127 } else {
128 self.next()
129 }
130 } else {
131 None
132 }
133 }
134}
135
136impl<'a> ScancodeIterator<'a> {
137 fn into_pressed_scancode_iter(self) -> PressedScancodeIterator<'a> {
138 self.filter_map(|(scancode, pressed)| pressed.then_some(scancode))
139 }
140}
141
142pub type PressedScancodeIterator<'a> =
143 FilterMap<ScancodeIterator<'a>, fn((Scancode, bool)) -> Option<Scancode>>;
144
145impl crate::Sdl {
146 #[inline]
147 pub fn keyboard(&self) -> KeyboardUtil {
148 KeyboardUtil {
149 _sdldrop: self.sdldrop(),
150 }
151 }
152}
153
154impl crate::VideoSubsystem {
155 #[inline]
156 pub fn text_input(&self) -> TextInputUtil {
157 TextInputUtil {
158 _subsystem: self.clone(),
159 }
160 }
161}
162
163pub struct KeyboardUtil {
171 _sdldrop: crate::SdlDrop,
172}
173
174impl KeyboardUtil {
175 #[doc(alias = "SDL_GetKeyboardFocus")]
177 pub fn focused_window_id(&self) -> Option<u32> {
178 let raw = unsafe { sys::SDL_GetKeyboardFocus() };
179 if raw.is_null() {
180 None
181 } else {
182 let id = unsafe { sys::SDL_GetWindowID(raw) };
183 Some(id)
184 }
185 }
186
187 #[doc(alias = "SDL_GetModState")]
188 pub fn mod_state(&self) -> Mod {
189 unsafe { Mod::from_bits(sys::SDL_GetModState() as u16).unwrap() }
190 }
191
192 #[doc(alias = "SDL_SetModState")]
193 pub fn set_mod_state(&self, flags: Mod) {
194 unsafe {
195 sys::SDL_SetModState(transmute::<u32, sys::SDL_Keymod>(flags.bits() as u32));
196 }
197 }
198}
199
200pub struct TextInputUtil {
212 _subsystem: crate::VideoSubsystem,
213}
214
215impl TextInputUtil {
216 #[doc(alias = "SDL_StartTextInput")]
217 pub fn start(&self) {
218 unsafe {
219 sys::SDL_StartTextInput();
220 }
221 }
222
223 #[doc(alias = "SDL_IsTextInputActive")]
224 pub fn is_active(&self) -> bool {
225 unsafe { sys::SDL_IsTextInputActive() == sys::SDL_bool::SDL_TRUE }
226 }
227
228 #[doc(alias = "SDL_StopTextInput")]
229 pub fn stop(&self) {
230 unsafe {
231 sys::SDL_StopTextInput();
232 }
233 }
234
235 #[doc(alias = "SDL_SetTextInputRect")]
236 pub fn set_rect(&self, rect: Rect) {
237 unsafe {
238 sys::SDL_SetTextInputRect(rect.raw() as *mut sys::SDL_Rect);
239 }
240 }
241
242 #[doc(alias = "SDL_HasScreenKeyboardSupport")]
243 pub fn has_screen_keyboard_support(&self) -> bool {
244 unsafe { sys::SDL_HasScreenKeyboardSupport() == sys::SDL_bool::SDL_TRUE }
245 }
246
247 #[doc(alias = "SDL_IsScreenKeyboardShown")]
248 pub fn is_screen_keyboard_shown(&self, window: &Window) -> bool {
249 unsafe { sys::SDL_IsScreenKeyboardShown(window.raw()) == sys::SDL_bool::SDL_TRUE }
250 }
251}