1use crate::Vec2;
2use std::cell::Cell;
3use std::rc::Rc;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6pub struct PointerId(pub u64);
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum PointerKind {
10 Mouse,
11 Touch,
12 Pen,
13}
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16pub enum PointerButton {
17 Primary, Secondary, Tertiary, }
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum PointerEventPass {
24 Initial,
27 Main,
31 Final,
34}
35
36#[derive(Clone, Copy, Debug)]
37pub enum PointerEventKind {
38 Down(PointerButton),
39 Up(PointerButton),
40 Move,
41 Cancel,
42 Enter,
43 Leave,
44}
45
46#[derive(Clone, Debug)]
47pub struct PointerEvent {
48 pub id: PointerId,
49 pub kind: PointerKind,
50 pub event: PointerEventKind,
51 pub position: Vec2,
53 pub origin: Vec2,
55 pub pressure: f32,
56 pub modifiers: Modifiers,
57 pub consumed: Rc<Cell<bool>>,
60}
61
62impl PointerEvent {
63 pub fn new(
64 id: PointerId,
65 kind: PointerKind,
66 event: PointerEventKind,
67 position: Vec2,
68 pressure: f32,
69 modifiers: Modifiers,
70 ) -> Self {
71 Self {
72 id,
73 kind,
74 event,
75 position,
76 origin: Vec2::ZERO,
77 pressure,
78 modifiers,
79 consumed: Rc::new(Cell::new(false)),
80 }
81 }
82
83 pub fn position_in_window(&self) -> Vec2 {
85 self.position + self.origin
86 }
87
88 pub fn consume(&self) {
92 self.consumed.set(true);
93 }
94
95 pub fn is_consumed(&self) -> bool {
97 self.consumed.get()
98 }
99}
100
101#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
102pub struct Modifiers {
103 pub shift: bool,
104 pub ctrl: bool,
105 pub alt: bool,
106 pub meta: bool, pub command: bool, }
109
110#[derive(Clone, Debug, PartialEq, Eq, Hash)]
111pub enum Key {
112 Character(char),
113 Enter,
114 Tab,
115 Backspace,
116 Delete,
117 Insert,
118 Escape,
119 ArrowLeft,
120 ArrowRight,
121 ArrowUp,
122 ArrowDown,
123 Home,
124 End,
125 PageUp,
126 PageDown,
127 Space,
128 F(u8), Unknown,
130}
131
132#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub enum KeyEventType {
134 Down,
136 Up,
138 Unknown,
140}
141
142#[derive(Clone, Debug)]
143pub struct KeyEvent {
144 pub key: Key,
145 pub modifiers: Modifiers,
146 pub is_repeat: bool,
147 pub event_type: KeyEventType,
149 pub utf16_code_point: u16,
152 pub physical: Option<String>,
159}
160
161#[derive(Clone, Debug)]
162pub struct TextInputEvent {
163 pub text: String,
164}
165
166#[derive(Clone, Debug)]
167pub enum ImeEvent {
168 Start,
170 Update {
172 text: String,
173 cursor: Option<(usize, usize)>, },
175 Commit(String),
177 Cancel,
179}
180
181#[derive(Clone, Debug)]
182pub enum InputEvent {
183 Pointer(PointerEvent),
184 Key(KeyEvent),
185 Text(TextInputEvent),
186 Ime(ImeEvent),
187 Gamepad(GamepadEvent),
188}
189
190#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
193pub struct GamepadId(pub u32);
194
195#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
198pub enum GamepadButton {
199 South,
201 East,
203 West,
205 North,
207 Start,
208 Select,
209 LeftShoulder,
210 RightShoulder,
211 LeftStick,
212 RightStick,
213 DPadUp,
214 DPadDown,
215 DPadLeft,
216 DPadRight,
217}
218
219#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
221pub enum GamepadAxis {
222 LeftStickX,
223 LeftStickY,
224 RightStickX,
225 RightStickY,
226 LeftTrigger,
227 RightTrigger,
228}
229
230#[derive(Clone, Debug)]
231pub enum GamepadEvent {
232 Connected {
233 id: GamepadId,
234 name: String,
235 },
236 Disconnected {
237 id: GamepadId,
238 },
239 Button {
240 id: GamepadId,
241 button: GamepadButton,
242 pressed: bool,
243 },
244 Axis {
245 id: GamepadId,
246 axis: GamepadAxis,
247 value: f32,
249 },
250}
251
252impl GamepadEvent {
253 pub fn id(&self) -> GamepadId {
254 match *self {
255 GamepadEvent::Connected { id, .. } => id,
256 GamepadEvent::Disconnected { id } => id,
257 GamepadEvent::Button { id, .. } => id,
258 GamepadEvent::Axis { id, .. } => id,
259 }
260 }
261}
262
263#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
264pub enum InputMode {
265 #[default]
266 Touch,
267 Keyboard,
269}
270
271thread_local! {
272 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
273}
274
275#[inline]
280pub fn input_mode() -> InputMode {
281 crate::locals::local_input_mode().unwrap_or_else(|| INPUT_MODE.get())
282}
283
284#[inline]
287pub fn set_input_mode_default(mode: InputMode) {
288 INPUT_MODE.set(mode);
289}
290
291pub fn request_input_mode(mode: InputMode) -> bool {
295 let prev = INPUT_MODE.get();
296 if prev == mode {
297 return false;
298 }
299 INPUT_MODE.set(mode);
300 crate::frame_clock::request_frame();
301 true
302}
303
304#[inline]
306pub fn is_focus_visible(focused: bool) -> bool {
307 focused && input_mode() == InputMode::Keyboard
308}
309
310#[cfg(test)]
311mod input_mode_tests {
312 use super::*;
313 use crate::frame_clock::take_frame_request;
314 use crate::modifier::{Interaction, MutableInteractionSource};
315
316 #[test]
317 fn request_input_mode_changes_and_requests_frame() {
318 set_input_mode_default(InputMode::Touch);
319 let _ = take_frame_request();
320
321 assert!(!request_input_mode(InputMode::Touch));
322 assert!(!take_frame_request());
323
324 assert!(request_input_mode(InputMode::Keyboard));
325 assert_eq!(input_mode(), InputMode::Keyboard);
326 assert!(take_frame_request());
327
328 assert!(request_input_mode(InputMode::Touch));
329 assert_eq!(input_mode(), InputMode::Touch);
330 set_input_mode_default(InputMode::Touch);
331 }
332
333 #[test]
334 fn focus_visible_requires_keyboard_mode() {
335 set_input_mode_default(InputMode::Touch);
336 let src = MutableInteractionSource::new();
337 src.emit(Interaction::Focus);
338 assert!(src.source().collect_is_focused());
339 assert!(!src.source().collect_is_focus_visible());
340
341 set_input_mode_default(InputMode::Keyboard);
342 assert!(src.source().collect_is_focus_visible());
343
344 set_input_mode_default(InputMode::Touch);
345 src.emit(Interaction::Unfocus);
346 }
347
348 #[test]
349 fn with_input_mode_overrides_global() {
350 set_input_mode_default(InputMode::Touch);
351 crate::locals::with_input_mode(InputMode::Keyboard, || {
352 assert_eq!(input_mode(), InputMode::Keyboard);
353 });
354 assert_eq!(input_mode(), InputMode::Touch);
355 }
356}