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 ShiftLeft,
129 ShiftRight,
130 F(u8), Unknown,
132}
133
134#[derive(Clone, Copy, Debug, PartialEq, Eq)]
135pub enum KeyEventType {
136 Down,
138 Up,
140 Unknown,
142}
143
144#[derive(Clone, Debug)]
145pub struct KeyEvent {
146 pub key: Key,
147 pub modifiers: Modifiers,
148 pub is_repeat: bool,
149 pub event_type: KeyEventType,
151 pub utf16_code_point: u16,
154 pub physical: Option<String>,
161}
162
163#[derive(Clone, Debug)]
164pub struct TextInputEvent {
165 pub text: String,
166}
167
168#[derive(Clone, Debug)]
169pub enum ImeEvent {
170 Start,
172 Update {
174 text: String,
175 cursor: Option<(usize, usize)>, },
177 Commit(String),
179 Cancel,
181}
182
183#[derive(Clone, Debug)]
184pub enum InputEvent {
185 Pointer(PointerEvent),
186 Key(KeyEvent),
187 Text(TextInputEvent),
188 Ime(ImeEvent),
189 Gamepad(GamepadEvent),
190}
191
192#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
195pub struct GamepadId(pub u32);
196
197#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
200pub enum GamepadButton {
201 South,
203 East,
205 West,
207 North,
209 Start,
210 Select,
211 LeftShoulder,
212 RightShoulder,
213 LeftStick,
214 RightStick,
215 DPadUp,
216 DPadDown,
217 DPadLeft,
218 DPadRight,
219}
220
221#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
223pub enum GamepadAxis {
224 LeftStickX,
225 LeftStickY,
226 RightStickX,
227 RightStickY,
228 LeftTrigger,
229 RightTrigger,
230}
231
232#[derive(Clone, Debug)]
233pub enum GamepadEvent {
234 Connected {
235 id: GamepadId,
236 name: String,
237 },
238 Disconnected {
239 id: GamepadId,
240 },
241 Button {
242 id: GamepadId,
243 button: GamepadButton,
244 pressed: bool,
245 },
246 Axis {
247 id: GamepadId,
248 axis: GamepadAxis,
249 value: f32,
251 },
252}
253
254impl GamepadEvent {
255 pub fn id(&self) -> GamepadId {
256 match *self {
257 GamepadEvent::Connected { id, .. } => id,
258 GamepadEvent::Disconnected { id } => id,
259 GamepadEvent::Button { id, .. } => id,
260 GamepadEvent::Axis { id, .. } => id,
261 }
262 }
263}
264
265#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
266pub enum InputMode {
267 #[default]
268 Touch,
269 Keyboard,
271}
272
273thread_local! {
274 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
275}
276
277#[inline]
282pub fn input_mode() -> InputMode {
283 crate::locals::local_input_mode().unwrap_or_else(|| INPUT_MODE.get())
284}
285
286#[inline]
289pub fn set_input_mode_default(mode: InputMode) {
290 INPUT_MODE.set(mode);
291}
292
293pub fn request_input_mode(mode: InputMode) -> bool {
297 let prev = INPUT_MODE.get();
298 if prev == mode {
299 return false;
300 }
301 INPUT_MODE.set(mode);
302 crate::frame_clock::request_frame();
303 true
304}
305
306#[inline]
308pub fn is_focus_visible(focused: bool) -> bool {
309 focused && input_mode() == InputMode::Keyboard
310}
311
312#[cfg(test)]
313mod input_mode_tests {
314 use super::*;
315 use crate::frame_clock::take_frame_request;
316 use crate::modifier::{Interaction, MutableInteractionSource};
317
318 #[test]
319 fn request_input_mode_changes_and_requests_frame() {
320 set_input_mode_default(InputMode::Touch);
321 let _ = take_frame_request();
322
323 assert!(!request_input_mode(InputMode::Touch));
324 assert!(!take_frame_request());
325
326 assert!(request_input_mode(InputMode::Keyboard));
327 assert_eq!(input_mode(), InputMode::Keyboard);
328 assert!(take_frame_request());
329
330 assert!(request_input_mode(InputMode::Touch));
331 assert_eq!(input_mode(), InputMode::Touch);
332 set_input_mode_default(InputMode::Touch);
333 }
334
335 #[test]
336 fn focus_visible_requires_keyboard_mode() {
337 set_input_mode_default(InputMode::Touch);
338 let src = MutableInteractionSource::new();
339 src.emit(Interaction::Focus);
340 assert!(src.source().collect_is_focused());
341 assert!(!src.source().collect_is_focus_visible());
342
343 set_input_mode_default(InputMode::Keyboard);
344 assert!(src.source().collect_is_focus_visible());
345
346 set_input_mode_default(InputMode::Touch);
347 src.emit(Interaction::Unfocus);
348 }
349
350 #[test]
351 fn with_input_mode_overrides_global() {
352 set_input_mode_default(InputMode::Touch);
353 crate::locals::with_input_mode(InputMode::Keyboard, || {
354 assert_eq!(input_mode(), InputMode::Keyboard);
355 });
356 assert_eq!(input_mode(), InputMode::Touch);
357 }
358}