1use crate::rect::Rect;
2use crate::video::Window;
3use crate::EventPump;
4
5use crate::sys;
6use std::fmt;
7use sys::video::SDL_GetWindowID;
8
9mod keycode;
10mod scancode;
11pub use self::keycode::Keycode;
12pub use self::scancode::Scancode;
13
14bitflags! {
15 #[derive(Debug, Copy, Clone, PartialEq)]
16 pub struct Mod: u16 {
17 const NOMOD = 0x0000;
18 const LSHIFTMOD = 0x0001;
19 const RSHIFTMOD = 0x0002;
20 const LCTRLMOD = 0x0040;
21 const RCTRLMOD = 0x0080;
22 const LALTMOD = 0x0100;
23 const RALTMOD = 0x0200;
24 const LGUIMOD = 0x0400;
25 const RGUIMOD = 0x0800;
26 const NUMMOD = 0x1000;
27 const CAPSMOD = 0x2000;
28 const MODEMOD = 0x4000;
29 const RESERVEDMOD = 0x8000;
30 }
31}
32
33impl fmt::Display for Mod {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 write!(f, "{:04x}", *self)
36 }
37}
38
39pub struct KeyboardState<'a> {
40 keyboard_state: &'a [bool],
41}
42
43impl<'a> KeyboardState<'a> {
44 #[doc(alias = "SDL_GetKeyboardState")]
45 pub fn new(_e: &'a EventPump) -> KeyboardState<'a> {
46 let keyboard_state = unsafe {
47 let mut count = 0;
48 let state_ptr = sys::keyboard::SDL_GetKeyboardState(&mut count);
49
50 ::std::slice::from_raw_parts(state_ptr, count as usize)
51 };
52
53 KeyboardState { keyboard_state }
54 }
55
56 pub fn is_scancode_pressed(&self, scancode: Scancode) -> bool {
67 self.keyboard_state[scancode as i32 as usize]
68 }
69
70 pub fn scancodes(&self) -> ScancodeIterator {
72 ScancodeIterator {
73 index: 0,
74 keyboard_state: self.keyboard_state,
75 }
76 }
77
78 pub fn pressed_scancodes(&self) -> PressedScancodeIterator {
102 PressedScancodeIterator {
103 iter: self.scancodes(),
104 }
105 }
106}
107
108pub struct ScancodeIterator<'a> {
109 index: i32,
110 keyboard_state: &'a [bool],
111}
112
113impl Iterator for ScancodeIterator<'_> {
114 type Item = (Scancode, bool);
115
116 fn next(&mut self) -> Option<(Scancode, bool)> {
117 if self.index < self.keyboard_state.len() as i32 {
118 let index = self.index;
119 self.index += 1;
120
121 if let Some(scancode) = Scancode::from_i32(index) {
122 let pressed = self.keyboard_state[index as usize];
123
124 Some((scancode, pressed))
125 } else {
126 self.next()
127 }
128 } else {
129 None
130 }
131 }
132}
133
134pub struct PressedScancodeIterator<'a> {
135 iter: ScancodeIterator<'a>,
136}
137
138impl Iterator for PressedScancodeIterator<'_> {
139 type Item = Scancode;
140
141 fn next(&mut self) -> Option<Scancode> {
142 for (scancode, pressed) in self.iter.by_ref() {
143 if pressed {
144 return Some(scancode);
145 }
146 }
147
148 None
149 }
150}
151
152impl crate::Sdl {
153 #[inline]
154 pub fn keyboard(&self) -> KeyboardUtil {
155 KeyboardUtil {
156 _sdldrop: self.sdldrop(),
157 }
158 }
159}
160
161impl crate::VideoSubsystem {
162 #[inline]
163 pub fn text_input(&self) -> TextInputUtil {
164 TextInputUtil {
165 _subsystem: self.clone(),
166 }
167 }
168}
169
170pub struct KeyboardUtil {
178 _sdldrop: crate::SdlDrop,
179}
180
181impl KeyboardUtil {
182 #[doc(alias = "SDL_GetKeyboardFocus")]
184 pub fn focused_window_id(&self) -> Option<u32> {
185 let raw = unsafe { sys::keyboard::SDL_GetKeyboardFocus() };
186 if raw.is_null() {
187 None
188 } else {
189 let id = unsafe { SDL_GetWindowID(raw) };
190 Some(id)
191 }
192 }
193
194 #[doc(alias = "SDL_GetModState")]
195 pub fn mod_state(&self) -> Mod {
196 unsafe { Mod::from_bits(sys::keyboard::SDL_GetModState() as u16).unwrap() }
197 }
198
199 #[doc(alias = "SDL_SetModState")]
200 pub fn set_mod_state(&self, flags: Mod) {
201 unsafe {
202 sys::keyboard::SDL_SetModState(flags.bits());
203 }
204 }
205}
206
207pub struct TextInputUtil {
220 _subsystem: crate::VideoSubsystem,
221}
222
223impl TextInputUtil {
224 #[doc(alias = "SDL_StartTextInput")]
225 pub fn start(&self, window: &Window) {
226 unsafe {
227 sys::keyboard::SDL_StartTextInput(window.raw());
228 }
229 }
230
231 #[doc(alias = "SDL_TextInputActive")]
232 pub fn is_active(&self, window: &Window) -> bool {
233 unsafe { sys::keyboard::SDL_TextInputActive(window.raw()) }
234 }
235
236 #[doc(alias = "SDL_StopTextInput")]
237 pub fn stop(&self, window: &Window) {
238 unsafe {
239 sys::keyboard::SDL_StopTextInput(window.raw());
240 }
241 }
242
243 #[doc(alias = "SDL_SetTextInputArea")]
244 pub fn set_rect(&self, window: &Window, rect: Rect, cursor: i32) {
245 unsafe {
246 sys::keyboard::SDL_SetTextInputArea(
247 window.raw(),
248 rect.raw() as *mut sys::rect::SDL_Rect,
249 cursor,
250 );
251 }
252 }
253
254 #[doc(alias = "SDL_HasScreenKeyboardSupport")]
255 pub fn has_screen_keyboard_support(&self) -> bool {
256 unsafe { sys::keyboard::SDL_HasScreenKeyboardSupport() }
257 }
258
259 #[doc(alias = "SDL_ScreenKeyboardShown")]
260 pub fn is_screen_keyboard_shown(&self, window: &Window) -> bool {
261 unsafe { sys::keyboard::SDL_ScreenKeyboardShown(window.raw()) }
262 }
263}