ndk/
event.rs

1//! Bindings for [`AInputEvent`, `AKeyEvent` and `AMotionEvent`]
2//!
3//! Most of these operations directly wrap functions in the NDK.
4//!
5//! See also the Java docs for [`android.view.InputEvent`], [`android.view.MotionEvent`], and
6//! [`android.view.KeyEvent`].
7//!
8//! [`AInputEvent`, `AKeyEvent` and `AMotionEvent`]: https://developer.android.com/ndk/reference/group/input
9//! [`android.view.InputEvent`]: https://developer.android.com/reference/android/view/InputEvent
10//! [`android.view.MotionEvent`]: https://developer.android.com/reference/android/view/MotionEvent
11//! [`android.view.KeyEvent`]: https://developer.android.com/reference/android/view/KeyEvent
12
13use std::ptr::NonNull;
14
15#[cfg(feature = "api-level-31")]
16use jni_sys::{jobject, JNIEnv};
17use num_enum::{FromPrimitive, IntoPrimitive};
18
19/// A native [`AInputEvent *`]
20///
21/// [`AInputEvent *`]: https://developer.android.com/ndk/reference/group/input#ainputevent
22#[derive(Debug)]
23#[non_exhaustive]
24pub enum InputEvent {
25    MotionEvent(MotionEvent),
26    KeyEvent(KeyEvent),
27}
28
29/// Wraps a Java [`InputEvent`] acquired from [`KeyEvent::from_java()`] or
30/// [`MotionEvent::from_java()`] with respective [`Drop`] semantics.
31#[cfg(feature = "api-level-31")]
32#[derive(Debug)]
33pub struct InputEventJava(InputEvent);
34
35#[cfg(feature = "api-level-31")]
36impl Drop for InputEventJava {
37    /// Releases interface objects created by [`KeyEvent::from_java()`] or
38    /// [`MotionEvent::from_java()`].
39    ///
40    /// The underlying Java object remains valid and does not change its state.
41    #[doc(alias = "AInputEvent_release")]
42    fn drop(&mut self) {
43        let ptr = match self.0 {
44            InputEvent::MotionEvent(MotionEvent { ptr })
45            | InputEvent::KeyEvent(KeyEvent { ptr }) => ptr.as_ptr().cast(),
46        };
47        unsafe { ffi::AInputEvent_release(ptr) }
48    }
49}
50
51/// An enum representing the source of an [`InputEvent`].
52#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
53#[repr(i32)]
54#[non_exhaustive]
55pub enum Source {
56    Unknown = ffi::AINPUT_SOURCE_UNKNOWN as i32,
57    Keyboard = ffi::AINPUT_SOURCE_KEYBOARD as i32,
58    Dpad = ffi::AINPUT_SOURCE_DPAD as i32,
59    Gamepad = ffi::AINPUT_SOURCE_GAMEPAD as i32,
60    Touchscreen = ffi::AINPUT_SOURCE_TOUCHSCREEN as i32,
61    Mouse = ffi::AINPUT_SOURCE_MOUSE as i32,
62    Stylus = ffi::AINPUT_SOURCE_STYLUS as i32,
63    BluetoothStylus = ffi::AINPUT_SOURCE_BLUETOOTH_STYLUS as i32,
64    Trackball = ffi::AINPUT_SOURCE_TRACKBALL as i32,
65    MouseRelative = ffi::AINPUT_SOURCE_MOUSE_RELATIVE as i32,
66    Touchpad = ffi::AINPUT_SOURCE_TOUCHPAD as i32,
67    TouchNavigation = ffi::AINPUT_SOURCE_TOUCH_NAVIGATION as i32,
68    Joystick = ffi::AINPUT_SOURCE_JOYSTICK as i32,
69    Hdmi = ffi::AINPUT_SOURCE_HDMI as i32,
70    Sensor = ffi::AINPUT_SOURCE_SENSOR as i32,
71    RotaryEncoder = ffi::AINPUT_SOURCE_ROTARY_ENCODER as i32,
72    Any = ffi::AINPUT_SOURCE_ANY as i32,
73
74    #[doc(hidden)]
75    #[num_enum(catch_all)]
76    __Unknown(i32),
77}
78
79impl Source {
80    pub fn class(self) -> SourceClass {
81        let class = i32::from(self) & ffi::AINPUT_SOURCE_CLASS_MASK as i32;
82        // The mask fits in a u8.
83        SourceClass::from_bits_retain(class as u8)
84    }
85}
86
87bitflags::bitflags! {
88    /// Flags representing the class of an [`InputEvent`] [`Source`].
89    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
90    pub struct SourceClass : u8 {
91        #[doc(alias = "AINPUT_SOURCE_CLASS_BUTTON")]
92        const BUTTON = ffi::AINPUT_SOURCE_CLASS_BUTTON as u8;
93        #[doc(alias = "AINPUT_SOURCE_CLASS_POINTER")]
94        const POINTER = ffi::AINPUT_SOURCE_CLASS_POINTER as u8;
95        #[doc(alias = "AINPUT_SOURCE_CLASS_NAVIGATION")]
96        const NAVIGATION = ffi::AINPUT_SOURCE_CLASS_NAVIGATION as u8;
97        #[doc(alias = "AINPUT_SOURCE_CLASS_POSITION")]
98        const POSITION = ffi::AINPUT_SOURCE_CLASS_POSITION as u8;
99        #[doc(alias = "AINPUT_SOURCE_CLASS_JOYSTICK")]
100        const JOYSTICK = ffi::AINPUT_SOURCE_CLASS_JOYSTICK as u8;
101
102        // https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags
103        const _ = ffi::AINPUT_SOURCE_CLASS_MASK as u8;
104    }
105}
106
107impl InputEvent {
108    /// Initialize an [`InputEvent`] from a pointer
109    ///
110    /// # Safety
111    /// By calling this function, you assert that the pointer is a valid pointer to a
112    /// native [`ffi::AInputEvent`].
113    #[inline]
114    pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
115        match ffi::AInputEvent_getType(ptr.as_ptr()) as u32 {
116            ffi::AINPUT_EVENT_TYPE_KEY => InputEvent::KeyEvent(KeyEvent::from_ptr(ptr)),
117            ffi::AINPUT_EVENT_TYPE_MOTION => InputEvent::MotionEvent(MotionEvent::from_ptr(ptr)),
118            x => panic!("Bad event type received: {}", x),
119        }
120    }
121
122    /// Returns a pointer to the native [`ffi::AInputEvent`].
123    #[inline]
124    pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
125        match self {
126            InputEvent::MotionEvent(MotionEvent { ptr }) => *ptr,
127            InputEvent::KeyEvent(KeyEvent { ptr }) => *ptr,
128        }
129    }
130
131    /// Get the source of the event.
132    ///
133    /// See [the NDK
134    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getsource)
135    #[inline]
136    pub fn source(&self) -> Source {
137        let source = unsafe { ffi::AInputEvent_getSource(self.ptr().as_ptr()) };
138        source.into()
139    }
140
141    /// Get the device id associated with the event.
142    ///
143    /// See [the NDK
144    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getdeviceid)
145    #[inline]
146    pub fn device_id(&self) -> i32 {
147        unsafe { ffi::AInputEvent_getDeviceId(self.ptr().as_ptr()) }
148    }
149}
150
151/// A bitfield representing the state of modifier keys during an event.
152#[derive(Copy, Clone, Debug, PartialEq, Eq)]
153pub struct MetaState(pub u32);
154
155impl MetaState {
156    #[inline]
157    pub fn alt_on(self) -> bool {
158        self.0 & ffi::AMETA_ALT_ON != 0
159    }
160    #[inline]
161    pub fn alt_left_on(self) -> bool {
162        self.0 & ffi::AMETA_ALT_LEFT_ON != 0
163    }
164    #[inline]
165    pub fn alt_right_on(self) -> bool {
166        self.0 & ffi::AMETA_ALT_RIGHT_ON != 0
167    }
168    #[inline]
169    pub fn shift_on(self) -> bool {
170        self.0 & ffi::AMETA_SHIFT_ON != 0
171    }
172    #[inline]
173    pub fn shift_left_on(self) -> bool {
174        self.0 & ffi::AMETA_SHIFT_LEFT_ON != 0
175    }
176    #[inline]
177    pub fn shift_right_on(self) -> bool {
178        self.0 & ffi::AMETA_SHIFT_RIGHT_ON != 0
179    }
180    #[inline]
181    pub fn sym_on(self) -> bool {
182        self.0 & ffi::AMETA_SYM_ON != 0
183    }
184    #[inline]
185    pub fn function_on(self) -> bool {
186        self.0 & ffi::AMETA_FUNCTION_ON != 0
187    }
188    #[inline]
189    pub fn ctrl_on(self) -> bool {
190        self.0 & ffi::AMETA_CTRL_ON != 0
191    }
192    #[inline]
193    pub fn ctrl_left_on(self) -> bool {
194        self.0 & ffi::AMETA_CTRL_LEFT_ON != 0
195    }
196    #[inline]
197    pub fn ctrl_right_on(self) -> bool {
198        self.0 & ffi::AMETA_CTRL_RIGHT_ON != 0
199    }
200    #[inline]
201    pub fn meta_on(self) -> bool {
202        self.0 & ffi::AMETA_META_ON != 0
203    }
204    #[inline]
205    pub fn meta_left_on(self) -> bool {
206        self.0 & ffi::AMETA_META_LEFT_ON != 0
207    }
208    #[inline]
209    pub fn meta_right_on(self) -> bool {
210        self.0 & ffi::AMETA_META_RIGHT_ON != 0
211    }
212    #[inline]
213    pub fn caps_lock_on(self) -> bool {
214        self.0 & ffi::AMETA_CAPS_LOCK_ON != 0
215    }
216    #[inline]
217    pub fn num_lock_on(self) -> bool {
218        self.0 & ffi::AMETA_NUM_LOCK_ON != 0
219    }
220    #[inline]
221    pub fn scroll_lock_on(self) -> bool {
222        self.0 & ffi::AMETA_SCROLL_LOCK_ON != 0
223    }
224}
225
226/// A motion event
227///
228/// Wraps an [`AInputEvent *`] of the [`ffi::AINPUT_EVENT_TYPE_MOTION`] type.
229///
230/// For general discussion of motion events in Android, see [the relevant
231/// javadoc](https://developer.android.com/reference/android/view/MotionEvent).
232///
233/// [`AInputEvent *`]: https://developer.android.com/ndk/reference/group/input#ainputevent
234#[derive(Clone, Debug)]
235pub struct MotionEvent {
236    ptr: NonNull<ffi::AInputEvent>,
237}
238
239// TODO: thread safety?
240
241/// A motion action.
242#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
243#[repr(i32)]
244#[non_exhaustive]
245pub enum MotionAction {
246    Down = ffi::AMOTION_EVENT_ACTION_DOWN as i32,
247    Up = ffi::AMOTION_EVENT_ACTION_UP as i32,
248    Move = ffi::AMOTION_EVENT_ACTION_MOVE as i32,
249    Cancel = ffi::AMOTION_EVENT_ACTION_CANCEL as i32,
250    Outside = ffi::AMOTION_EVENT_ACTION_OUTSIDE as i32,
251    PointerDown = ffi::AMOTION_EVENT_ACTION_POINTER_DOWN as i32,
252    PointerUp = ffi::AMOTION_EVENT_ACTION_POINTER_UP as i32,
253    HoverMove = ffi::AMOTION_EVENT_ACTION_HOVER_MOVE as i32,
254    Scroll = ffi::AMOTION_EVENT_ACTION_SCROLL as i32,
255    HoverEnter = ffi::AMOTION_EVENT_ACTION_HOVER_ENTER as i32,
256    HoverExit = ffi::AMOTION_EVENT_ACTION_HOVER_EXIT as i32,
257    ButtonPress = ffi::AMOTION_EVENT_ACTION_BUTTON_PRESS as i32,
258    ButtonRelease = ffi::AMOTION_EVENT_ACTION_BUTTON_RELEASE as i32,
259
260    #[doc(hidden)]
261    #[num_enum(catch_all)]
262    __Unknown(i32),
263}
264
265/// An axis of a motion event.
266#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
267#[repr(i32)]
268#[non_exhaustive]
269pub enum Axis {
270    X = ffi::AMOTION_EVENT_AXIS_X as i32,
271    Y = ffi::AMOTION_EVENT_AXIS_Y as i32,
272    Pressure = ffi::AMOTION_EVENT_AXIS_PRESSURE as i32,
273    Size = ffi::AMOTION_EVENT_AXIS_SIZE as i32,
274    TouchMajor = ffi::AMOTION_EVENT_AXIS_TOUCH_MAJOR as i32,
275    TouchMinor = ffi::AMOTION_EVENT_AXIS_TOUCH_MINOR as i32,
276    ToolMajor = ffi::AMOTION_EVENT_AXIS_TOOL_MAJOR as i32,
277    ToolMinor = ffi::AMOTION_EVENT_AXIS_TOOL_MINOR as i32,
278    Orientation = ffi::AMOTION_EVENT_AXIS_ORIENTATION as i32,
279    Vscroll = ffi::AMOTION_EVENT_AXIS_VSCROLL as i32,
280    Hscroll = ffi::AMOTION_EVENT_AXIS_HSCROLL as i32,
281    Z = ffi::AMOTION_EVENT_AXIS_Z as i32,
282    Rx = ffi::AMOTION_EVENT_AXIS_RX as i32,
283    Ry = ffi::AMOTION_EVENT_AXIS_RY as i32,
284    Rz = ffi::AMOTION_EVENT_AXIS_RZ as i32,
285    HatX = ffi::AMOTION_EVENT_AXIS_HAT_X as i32,
286    HatY = ffi::AMOTION_EVENT_AXIS_HAT_Y as i32,
287    Ltrigger = ffi::AMOTION_EVENT_AXIS_LTRIGGER as i32,
288    Rtrigger = ffi::AMOTION_EVENT_AXIS_RTRIGGER as i32,
289    Throttle = ffi::AMOTION_EVENT_AXIS_THROTTLE as i32,
290    Rudder = ffi::AMOTION_EVENT_AXIS_RUDDER as i32,
291    Wheel = ffi::AMOTION_EVENT_AXIS_WHEEL as i32,
292    Gas = ffi::AMOTION_EVENT_AXIS_GAS as i32,
293    Brake = ffi::AMOTION_EVENT_AXIS_BRAKE as i32,
294    Distance = ffi::AMOTION_EVENT_AXIS_DISTANCE as i32,
295    Tilt = ffi::AMOTION_EVENT_AXIS_TILT as i32,
296    Scroll = ffi::AMOTION_EVENT_AXIS_SCROLL as i32,
297    RelativeX = ffi::AMOTION_EVENT_AXIS_RELATIVE_X as i32,
298    RelativeY = ffi::AMOTION_EVENT_AXIS_RELATIVE_Y as i32,
299    Generic1 = ffi::AMOTION_EVENT_AXIS_GENERIC_1 as i32,
300    Generic2 = ffi::AMOTION_EVENT_AXIS_GENERIC_2 as i32,
301    Generic3 = ffi::AMOTION_EVENT_AXIS_GENERIC_3 as i32,
302    Generic4 = ffi::AMOTION_EVENT_AXIS_GENERIC_4 as i32,
303    Generic5 = ffi::AMOTION_EVENT_AXIS_GENERIC_5 as i32,
304    Generic6 = ffi::AMOTION_EVENT_AXIS_GENERIC_6 as i32,
305    Generic7 = ffi::AMOTION_EVENT_AXIS_GENERIC_7 as i32,
306    Generic8 = ffi::AMOTION_EVENT_AXIS_GENERIC_8 as i32,
307    Generic9 = ffi::AMOTION_EVENT_AXIS_GENERIC_9 as i32,
308    Generic10 = ffi::AMOTION_EVENT_AXIS_GENERIC_10 as i32,
309    Generic11 = ffi::AMOTION_EVENT_AXIS_GENERIC_11 as i32,
310    Generic12 = ffi::AMOTION_EVENT_AXIS_GENERIC_12 as i32,
311    Generic13 = ffi::AMOTION_EVENT_AXIS_GENERIC_13 as i32,
312    Generic14 = ffi::AMOTION_EVENT_AXIS_GENERIC_14 as i32,
313    Generic15 = ffi::AMOTION_EVENT_AXIS_GENERIC_15 as i32,
314    Generic16 = ffi::AMOTION_EVENT_AXIS_GENERIC_16 as i32,
315
316    #[doc(hidden)]
317    #[num_enum(catch_all)]
318    __Unknown(i32),
319}
320
321/// The tool type of a pointer.
322#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
323#[repr(i32)]
324#[non_exhaustive]
325pub enum ToolType {
326    Unknown = ffi::AMOTION_EVENT_TOOL_TYPE_UNKNOWN as i32,
327    Finger = ffi::AMOTION_EVENT_TOOL_TYPE_FINGER as i32,
328    Stylus = ffi::AMOTION_EVENT_TOOL_TYPE_STYLUS as i32,
329    Mouse = ffi::AMOTION_EVENT_TOOL_TYPE_MOUSE as i32,
330    Eraser = ffi::AMOTION_EVENT_TOOL_TYPE_ERASER as i32,
331    Palm = ffi::AMOTION_EVENT_TOOL_TYPE_PALM as i32,
332
333    #[doc(hidden)]
334    #[num_enum(catch_all)]
335    __Unknown(i32),
336}
337
338/// A bitfield representing the state of buttons during a motion event.
339#[derive(Copy, Clone, Debug, PartialEq, Eq)]
340pub struct ButtonState(pub u32);
341
342impl ButtonState {
343    #[inline]
344    pub fn primary(self) -> bool {
345        self.0 & ffi::AMOTION_EVENT_BUTTON_PRIMARY != 0
346    }
347    #[inline]
348    pub fn secondary(self) -> bool {
349        self.0 & ffi::AMOTION_EVENT_BUTTON_SECONDARY != 0
350    }
351    #[inline]
352    pub fn teriary(self) -> bool {
353        self.0 & ffi::AMOTION_EVENT_BUTTON_TERTIARY != 0
354    }
355    #[inline]
356    pub fn back(self) -> bool {
357        self.0 & ffi::AMOTION_EVENT_BUTTON_BACK != 0
358    }
359    #[inline]
360    pub fn forward(self) -> bool {
361        self.0 & ffi::AMOTION_EVENT_BUTTON_FORWARD != 0
362    }
363    #[inline]
364    pub fn stylus_primary(self) -> bool {
365        self.0 & ffi::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY != 0
366    }
367    #[inline]
368    pub fn stylus_secondary(self) -> bool {
369        self.0 & ffi::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY != 0
370    }
371}
372
373/// A bitfield representing which edges were touched by a motion event.
374#[derive(Copy, Clone, Debug, PartialEq, Eq)]
375pub struct EdgeFlags(pub u32);
376
377impl EdgeFlags {
378    #[inline]
379    pub fn top(self) -> bool {
380        self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_TOP != 0
381    }
382    #[inline]
383    pub fn bottom(self) -> bool {
384        self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_BOTTOM != 0
385    }
386    #[inline]
387    pub fn left(self) -> bool {
388        self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_LEFT != 0
389    }
390    #[inline]
391    pub fn right(self) -> bool {
392        self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_RIGHT != 0
393    }
394}
395
396/// Flags associated with this [`MotionEvent`].
397#[derive(Copy, Clone, Debug, PartialEq, Eq)]
398pub struct MotionEventFlags(pub u32);
399
400impl MotionEventFlags {
401    #[inline]
402    pub fn window_is_obscured(self) -> bool {
403        self.0 & ffi::AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED != 0
404    }
405}
406
407impl MotionEvent {
408    /// Constructs a MotionEvent from a pointer to a native [`ffi::AInputEvent`]
409    ///
410    /// # Safety
411    /// By calling this method, you assert that the pointer is a valid, non-null pointer to a
412    /// native [`ffi::AInputEvent`] and that [`ffi::AInputEvent`]
413    /// is an `AMotionEvent`.
414    #[inline]
415    pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
416        Self { ptr }
417    }
418
419    /// Creates a native [`InputEvent`] object that is a copy of the specified
420    /// Java [`android.view.MotionEvent`]. The result may be used with generic and
421    /// [`MotionEvent`]-specific functions.
422    ///
423    /// # Safety
424    ///
425    /// This function should be called with a healthy JVM pointer and with a non-null
426    /// [`android.view.MotionEvent`].
427    ///
428    /// [`android.view.MotionEvent`]: https://developer.android.com/reference/android/view/MotionEvent
429    #[cfg(feature = "api-level-31")]
430    #[doc(alias = "AMotionEvent_fromJava")]
431    pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
432        let ptr = unsafe { ffi::AMotionEvent_fromJava(env, key_event) };
433        Some(InputEventJava(InputEvent::MotionEvent(Self::from_ptr(
434            NonNull::new(ptr.cast_mut())?,
435        ))))
436    }
437
438    /// Returns a pointer to the native [`ffi::AInputEvent`].
439    #[inline]
440    pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
441        self.ptr
442    }
443
444    /// Get the source of the event.
445    ///
446    /// See [the NDK
447    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getsource)
448    #[inline]
449    pub fn source(&self) -> Source {
450        let source = unsafe { ffi::AInputEvent_getSource(self.ptr.as_ptr()) };
451        source.into()
452    }
453
454    /// Get the device id associated with the event.
455    ///
456    /// See [the NDK
457    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getdeviceid)
458    #[inline]
459    pub fn device_id(&self) -> i32 {
460        unsafe { ffi::AInputEvent_getDeviceId(self.ptr.as_ptr()) }
461    }
462
463    /// Returns the motion action associated with the event.
464    ///
465    /// See [the NDK
466    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getaction)
467    #[inline]
468    pub fn action(&self) -> MotionAction {
469        let action = unsafe { ffi::AMotionEvent_getAction(self.ptr.as_ptr()) }
470            & ffi::AMOTION_EVENT_ACTION_MASK as i32;
471        action.into()
472    }
473
474    /// Returns the pointer index of an `Up` or `Down` event.
475    ///
476    /// Pointer indices can change per motion event.  For an identifier that stays the same, see
477    /// [`Pointer::pointer_id()`].
478    ///
479    /// This only has a meaning when the [action][Self::action] is one of [`Up`][MotionAction::Up],
480    /// [`Down`][MotionAction::Down], [`PointerUp`][MotionAction::PointerUp],
481    /// or [`PointerDown`][MotionAction::PointerDown].
482    #[inline]
483    pub fn pointer_index(&self) -> usize {
484        let action = unsafe { ffi::AMotionEvent_getAction(self.ptr.as_ptr()) as u32 };
485        let index = (action & ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
486            >> ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
487        index as usize
488    }
489
490    /*
491    /// Returns the pointer id associated with the given pointer index.
492    ///
493    /// See [the NDK
494    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getpointerid)
495    // TODO: look at output with out-of-range pointer index
496    // Probably -1 though
497    pub fn pointer_id_for(&self, pointer_index: usize) -> i32 {
498        unsafe { ffi::AMotionEvent_getPointerId(self.ptr.as_ptr(), pointer_index) }
499    }
500    */
501
502    /// Returns the number of pointers in this event
503    ///
504    /// See [the NDK
505    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getpointercount)
506    #[inline]
507    pub fn pointer_count(&self) -> usize {
508        unsafe { ffi::AMotionEvent_getPointerCount(self.ptr.as_ptr()) }
509    }
510
511    /// An iterator over the pointers in this motion event
512    #[inline]
513    pub fn pointers(&self) -> PointersIter<'_> {
514        PointersIter {
515            event: self.ptr,
516            next_index: 0,
517            count: self.pointer_count(),
518            _marker: std::marker::PhantomData,
519        }
520    }
521
522    /// The pointer at a given pointer index. Panics if the pointer index is out of bounds.
523    ///
524    /// If you need to loop over all the pointers, prefer the [`pointers()`][Self::pointers] method.
525    #[inline]
526    pub fn pointer_at_index(&self, index: usize) -> Pointer<'_> {
527        if index >= self.pointer_count() {
528            panic!("Pointer index {} is out of bounds", index);
529        }
530        Pointer {
531            event: self.ptr,
532            index,
533            _marker: std::marker::PhantomData,
534        }
535    }
536
537    /// Returns the size of the history contained in this event.
538    ///
539    /// See [the NDK
540    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_gethistorysize)
541    #[inline]
542    pub fn history_size(&self) -> usize {
543        unsafe { ffi::AMotionEvent_getHistorySize(self.ptr.as_ptr()) }
544    }
545
546    /// An iterator over the historical events contained in this event.
547    #[inline]
548    pub fn history(&self) -> HistoricalMotionEventsIter<'_> {
549        HistoricalMotionEventsIter {
550            event: self.ptr,
551            next_history_index: 0,
552            history_size: self.history_size(),
553            _marker: std::marker::PhantomData,
554        }
555    }
556
557    /// Returns the state of any modifier keys that were pressed during the event.
558    ///
559    /// See [the NDK
560    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getmetastate)
561    #[inline]
562    pub fn meta_state(&self) -> MetaState {
563        unsafe { MetaState(ffi::AMotionEvent_getMetaState(self.ptr.as_ptr()) as u32) }
564    }
565
566    /// Returns the button state during this event, as a bitfield.
567    ///
568    /// See [the NDK
569    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getbuttonstate)
570    #[inline]
571    pub fn button_state(&self) -> ButtonState {
572        unsafe { ButtonState(ffi::AMotionEvent_getButtonState(self.ptr.as_ptr()) as u32) }
573    }
574
575    /// Returns the time of the start of this gesture, in the `java.lang.System.nanoTime()` time
576    /// base
577    ///
578    /// See [the NDK
579    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getdowntime)
580    #[inline]
581    pub fn down_time(&self) -> i64 {
582        unsafe { ffi::AMotionEvent_getDownTime(self.ptr.as_ptr()) }
583    }
584
585    /// Returns a bitfield indicating which edges were touched by this event.
586    ///
587    /// See [the NDK
588    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getedgeflags)
589    #[inline]
590    pub fn edge_flags(&self) -> EdgeFlags {
591        unsafe { EdgeFlags(ffi::AMotionEvent_getEdgeFlags(self.ptr.as_ptr()) as u32) }
592    }
593
594    /// Returns the time of this event, in the `java.lang.System.nanoTime()` time base
595    ///
596    /// See [the NDK
597    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_geteventtime)
598    #[inline]
599    pub fn event_time(&self) -> i64 {
600        unsafe { ffi::AMotionEvent_getEventTime(self.ptr.as_ptr()) }
601    }
602
603    /// The flags associated with a motion event.
604    ///
605    /// See [the NDK
606    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getflags)
607    #[inline]
608    pub fn flags(&self) -> MotionEventFlags {
609        unsafe { MotionEventFlags(ffi::AMotionEvent_getFlags(self.ptr.as_ptr()) as u32) }
610    }
611
612    /// Returns the offset in the x direction between the coordinates and the raw coordinates
613    ///
614    /// See [the NDK
615    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getxoffset)
616    #[inline]
617    pub fn x_offset(&self) -> f32 {
618        unsafe { ffi::AMotionEvent_getXOffset(self.ptr.as_ptr()) }
619    }
620
621    /// Returns the offset in the y direction between the coordinates and the raw coordinates
622    ///
623    /// See [the NDK
624    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getyoffset)
625    #[inline]
626    pub fn y_offset(&self) -> f32 {
627        unsafe { ffi::AMotionEvent_getYOffset(self.ptr.as_ptr()) }
628    }
629
630    /// Returns the precision of the x value of the coordinates
631    ///
632    /// See [the NDK
633    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getxprecision)
634    #[inline]
635    pub fn x_precision(&self) -> f32 {
636        unsafe { ffi::AMotionEvent_getXPrecision(self.ptr.as_ptr()) }
637    }
638
639    /// Returns the precision of the y value of the coordinates
640    ///
641    /// See [the NDK
642    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getyprecision)
643    #[inline]
644    pub fn y_precision(&self) -> f32 {
645        unsafe { ffi::AMotionEvent_getYPrecision(self.ptr.as_ptr()) }
646    }
647}
648
649/// A view into the data of a specific pointer in a motion event.
650#[derive(Debug)]
651pub struct Pointer<'a> {
652    event: NonNull<ffi::AInputEvent>,
653    index: usize,
654    _marker: std::marker::PhantomData<&'a MotionEvent>,
655}
656
657// TODO: thread safety?
658
659impl<'a> Pointer<'a> {
660    #[inline]
661    pub fn pointer_index(&self) -> usize {
662        self.index
663    }
664
665    #[inline]
666    pub fn pointer_id(&self) -> i32 {
667        unsafe { ffi::AMotionEvent_getPointerId(self.event.as_ptr(), self.index) }
668    }
669
670    #[inline]
671    pub fn axis_value(&self, axis: Axis) -> f32 {
672        unsafe { ffi::AMotionEvent_getAxisValue(self.event.as_ptr(), axis.into(), self.index) }
673    }
674
675    #[inline]
676    pub fn orientation(&self) -> f32 {
677        unsafe { ffi::AMotionEvent_getOrientation(self.event.as_ptr(), self.index) }
678    }
679
680    #[inline]
681    pub fn pressure(&self) -> f32 {
682        unsafe { ffi::AMotionEvent_getPressure(self.event.as_ptr(), self.index) }
683    }
684
685    #[inline]
686    pub fn raw_x(&self) -> f32 {
687        unsafe { ffi::AMotionEvent_getRawX(self.event.as_ptr(), self.index) }
688    }
689
690    #[inline]
691    pub fn raw_y(&self) -> f32 {
692        unsafe { ffi::AMotionEvent_getRawY(self.event.as_ptr(), self.index) }
693    }
694
695    #[inline]
696    pub fn x(&self) -> f32 {
697        unsafe { ffi::AMotionEvent_getX(self.event.as_ptr(), self.index) }
698    }
699
700    #[inline]
701    pub fn y(&self) -> f32 {
702        unsafe { ffi::AMotionEvent_getY(self.event.as_ptr(), self.index) }
703    }
704
705    #[inline]
706    pub fn size(&self) -> f32 {
707        unsafe { ffi::AMotionEvent_getSize(self.event.as_ptr(), self.index) }
708    }
709
710    #[inline]
711    pub fn tool_major(&self) -> f32 {
712        unsafe { ffi::AMotionEvent_getToolMajor(self.event.as_ptr(), self.index) }
713    }
714
715    #[inline]
716    pub fn tool_minor(&self) -> f32 {
717        unsafe { ffi::AMotionEvent_getToolMinor(self.event.as_ptr(), self.index) }
718    }
719
720    #[inline]
721    pub fn touch_major(&self) -> f32 {
722        unsafe { ffi::AMotionEvent_getTouchMajor(self.event.as_ptr(), self.index) }
723    }
724
725    #[inline]
726    pub fn touch_minor(&self) -> f32 {
727        unsafe { ffi::AMotionEvent_getTouchMinor(self.event.as_ptr(), self.index) }
728    }
729
730    #[inline]
731    pub fn tool_type(&self) -> ToolType {
732        let tool_type = unsafe { ffi::AMotionEvent_getToolType(self.event.as_ptr(), self.index) };
733        tool_type.into()
734    }
735}
736
737/// An iterator over the pointers in a [`MotionEvent`].
738#[derive(Debug)]
739pub struct PointersIter<'a> {
740    event: NonNull<ffi::AInputEvent>,
741    next_index: usize,
742    count: usize,
743    _marker: std::marker::PhantomData<&'a MotionEvent>,
744}
745
746// TODO: thread safety?
747
748impl<'a> Iterator for PointersIter<'a> {
749    type Item = Pointer<'a>;
750    fn next(&mut self) -> Option<Pointer<'a>> {
751        if self.next_index < self.count {
752            let ptr = Pointer {
753                event: self.event,
754                index: self.next_index,
755                _marker: std::marker::PhantomData,
756            };
757            self.next_index += 1;
758            Some(ptr)
759        } else {
760            None
761        }
762    }
763
764    fn size_hint(&self) -> (usize, Option<usize>) {
765        let size = self.count - self.next_index;
766        (size, Some(size))
767    }
768}
769impl<'a> ExactSizeIterator for PointersIter<'a> {
770    fn len(&self) -> usize {
771        self.count - self.next_index
772    }
773}
774
775/// Represents a view into a past moment of a motion event
776#[derive(Debug)]
777pub struct HistoricalMotionEvent<'a> {
778    event: NonNull<ffi::AInputEvent>,
779    history_index: usize,
780    _marker: std::marker::PhantomData<&'a MotionEvent>,
781}
782
783// TODO: thread safety?
784
785impl<'a> HistoricalMotionEvent<'a> {
786    /// Returns the "history index" associated with this historical event.  Older events have smaller indices.
787    #[inline]
788    pub fn history_index(&self) -> usize {
789        self.history_index
790    }
791
792    /// Returns the time of the historical event, in the `java.lang.System.nanoTime()` time base
793    ///
794    /// See [the NDK
795    /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_gethistoricaleventtime)
796    #[inline]
797    pub fn event_time(&self) -> i64 {
798        unsafe { ffi::AMotionEvent_getHistoricalEventTime(self.event.as_ptr(), self.history_index) }
799    }
800
801    /// An iterator over the pointers of this historical motion event
802    #[inline]
803    pub fn pointers(&self) -> HistoricalPointersIter<'a> {
804        HistoricalPointersIter {
805            event: self.event,
806            history_index: self.history_index,
807            next_pointer_index: 0,
808            pointer_count: unsafe { ffi::AMotionEvent_getPointerCount(self.event.as_ptr()) },
809            _marker: std::marker::PhantomData,
810        }
811    }
812}
813
814/// An iterator over all the historical moments in a [`MotionEvent`].
815///
816/// It iterates from oldest to newest.
817#[derive(Debug)]
818pub struct HistoricalMotionEventsIter<'a> {
819    event: NonNull<ffi::AInputEvent>,
820    next_history_index: usize,
821    history_size: usize,
822    _marker: std::marker::PhantomData<&'a MotionEvent>,
823}
824
825// TODO: thread safety?
826
827impl<'a> Iterator for HistoricalMotionEventsIter<'a> {
828    type Item = HistoricalMotionEvent<'a>;
829
830    fn next(&mut self) -> Option<HistoricalMotionEvent<'a>> {
831        if self.next_history_index < self.history_size {
832            let res = HistoricalMotionEvent {
833                event: self.event,
834                history_index: self.next_history_index,
835                _marker: std::marker::PhantomData,
836            };
837            self.next_history_index += 1;
838            Some(res)
839        } else {
840            None
841        }
842    }
843
844    fn size_hint(&self) -> (usize, Option<usize>) {
845        let size = self.history_size - self.next_history_index;
846        (size, Some(size))
847    }
848}
849impl ExactSizeIterator for HistoricalMotionEventsIter<'_> {
850    fn len(&self) -> usize {
851        self.history_size - self.next_history_index
852    }
853}
854impl<'a> DoubleEndedIterator for HistoricalMotionEventsIter<'a> {
855    fn next_back(&mut self) -> Option<HistoricalMotionEvent<'a>> {
856        if self.next_history_index < self.history_size {
857            self.history_size -= 1;
858            Some(HistoricalMotionEvent {
859                event: self.event,
860                history_index: self.history_size,
861                _marker: std::marker::PhantomData,
862            })
863        } else {
864            None
865        }
866    }
867}
868
869/// A view into a pointer at a historical moment
870#[derive(Debug)]
871pub struct HistoricalPointer<'a> {
872    event: NonNull<ffi::AInputEvent>,
873    pointer_index: usize,
874    history_index: usize,
875    _marker: std::marker::PhantomData<&'a MotionEvent>,
876}
877
878// TODO: thread safety?
879
880impl<'a> HistoricalPointer<'a> {
881    #[inline]
882    pub fn pointer_index(&self) -> usize {
883        self.pointer_index
884    }
885
886    #[inline]
887    pub fn pointer_id(&self) -> i32 {
888        unsafe { ffi::AMotionEvent_getPointerId(self.event.as_ptr(), self.pointer_index) }
889    }
890
891    #[inline]
892    pub fn history_index(&self) -> usize {
893        self.history_index
894    }
895
896    #[inline]
897    pub fn axis_value(&self, axis: Axis) -> f32 {
898        unsafe {
899            ffi::AMotionEvent_getHistoricalAxisValue(
900                self.event.as_ptr(),
901                axis.into(),
902                self.pointer_index,
903                self.history_index,
904            )
905        }
906    }
907
908    #[inline]
909    pub fn orientation(&self) -> f32 {
910        unsafe {
911            ffi::AMotionEvent_getHistoricalOrientation(
912                self.event.as_ptr(),
913                self.pointer_index,
914                self.history_index,
915            )
916        }
917    }
918
919    #[inline]
920    pub fn pressure(&self) -> f32 {
921        unsafe {
922            ffi::AMotionEvent_getHistoricalPressure(
923                self.event.as_ptr(),
924                self.pointer_index,
925                self.history_index,
926            )
927        }
928    }
929
930    #[inline]
931    pub fn raw_x(&self) -> f32 {
932        unsafe {
933            ffi::AMotionEvent_getHistoricalRawX(
934                self.event.as_ptr(),
935                self.pointer_index,
936                self.history_index,
937            )
938        }
939    }
940
941    #[inline]
942    pub fn raw_y(&self) -> f32 {
943        unsafe {
944            ffi::AMotionEvent_getHistoricalRawY(
945                self.event.as_ptr(),
946                self.pointer_index,
947                self.history_index,
948            )
949        }
950    }
951
952    #[inline]
953    pub fn x(&self) -> f32 {
954        unsafe {
955            ffi::AMotionEvent_getHistoricalX(
956                self.event.as_ptr(),
957                self.pointer_index,
958                self.history_index,
959            )
960        }
961    }
962
963    #[inline]
964    pub fn y(&self) -> f32 {
965        unsafe {
966            ffi::AMotionEvent_getHistoricalY(
967                self.event.as_ptr(),
968                self.pointer_index,
969                self.history_index,
970            )
971        }
972    }
973
974    #[inline]
975    pub fn size(&self) -> f32 {
976        unsafe {
977            ffi::AMotionEvent_getHistoricalSize(
978                self.event.as_ptr(),
979                self.pointer_index,
980                self.history_index,
981            )
982        }
983    }
984
985    #[inline]
986    pub fn tool_major(&self) -> f32 {
987        unsafe {
988            ffi::AMotionEvent_getHistoricalToolMajor(
989                self.event.as_ptr(),
990                self.pointer_index,
991                self.history_index,
992            )
993        }
994    }
995
996    #[inline]
997    pub fn tool_minor(&self) -> f32 {
998        unsafe {
999            ffi::AMotionEvent_getHistoricalToolMinor(
1000                self.event.as_ptr(),
1001                self.pointer_index,
1002                self.history_index,
1003            )
1004        }
1005    }
1006
1007    #[inline]
1008    pub fn touch_major(&self) -> f32 {
1009        unsafe {
1010            ffi::AMotionEvent_getHistoricalTouchMajor(
1011                self.event.as_ptr(),
1012                self.pointer_index,
1013                self.history_index,
1014            )
1015        }
1016    }
1017
1018    #[inline]
1019    pub fn touch_minor(&self) -> f32 {
1020        unsafe {
1021            ffi::AMotionEvent_getHistoricalTouchMinor(
1022                self.event.as_ptr(),
1023                self.pointer_index,
1024                self.history_index,
1025            )
1026        }
1027    }
1028}
1029
1030/// An iterator over the pointers in a historical motion event
1031#[derive(Debug)]
1032pub struct HistoricalPointersIter<'a> {
1033    event: NonNull<ffi::AInputEvent>,
1034    history_index: usize,
1035    next_pointer_index: usize,
1036    pointer_count: usize,
1037    _marker: std::marker::PhantomData<&'a MotionEvent>,
1038}
1039
1040// TODO: thread safety?
1041
1042impl<'a> Iterator for HistoricalPointersIter<'a> {
1043    type Item = HistoricalPointer<'a>;
1044
1045    fn next(&mut self) -> Option<HistoricalPointer<'a>> {
1046        if self.next_pointer_index < self.pointer_count {
1047            let ptr = HistoricalPointer {
1048                event: self.event,
1049                history_index: self.history_index,
1050                pointer_index: self.next_pointer_index,
1051                _marker: std::marker::PhantomData,
1052            };
1053            self.next_pointer_index += 1;
1054            Some(ptr)
1055        } else {
1056            None
1057        }
1058    }
1059
1060    fn size_hint(&self) -> (usize, Option<usize>) {
1061        let size = self.pointer_count - self.next_pointer_index;
1062        (size, Some(size))
1063    }
1064}
1065impl ExactSizeIterator for HistoricalPointersIter<'_> {
1066    fn len(&self) -> usize {
1067        self.pointer_count - self.next_pointer_index
1068    }
1069}
1070
1071/// A key event
1072///
1073/// Wraps an [`AInputEvent *`] of the [`ffi::AINPUT_EVENT_TYPE_KEY`] type.
1074///
1075/// For general discussion of key events in Android, see [the relevant
1076/// javadoc](https://developer.android.com/reference/android/view/KeyEvent).
1077///
1078/// [`AInputEvent *`]: https://developer.android.com/ndk/reference/group/input#ainputevent
1079#[derive(Debug)]
1080pub struct KeyEvent {
1081    ptr: NonNull<ffi::AInputEvent>,
1082}
1083
1084// TODO: thread safety?
1085
1086/// Key actions.
1087/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-27)
1088#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
1089#[repr(i32)]
1090#[non_exhaustive]
1091pub enum KeyAction {
1092    Down = ffi::AKEY_EVENT_ACTION_DOWN as i32,
1093    Up = ffi::AKEY_EVENT_ACTION_UP as i32,
1094    Multiple = ffi::AKEY_EVENT_ACTION_MULTIPLE as i32,
1095
1096    #[doc(hidden)]
1097    #[num_enum(catch_all)]
1098    __Unknown(i32),
1099}
1100
1101/// Key codes.
1102#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
1103#[repr(i32)]
1104#[non_exhaustive]
1105pub enum Keycode {
1106    Unknown = ffi::AKEYCODE_UNKNOWN as i32,
1107    SoftLeft = ffi::AKEYCODE_SOFT_LEFT as i32,
1108    SoftRight = ffi::AKEYCODE_SOFT_RIGHT as i32,
1109    Home = ffi::AKEYCODE_HOME as i32,
1110    Back = ffi::AKEYCODE_BACK as i32,
1111    Call = ffi::AKEYCODE_CALL as i32,
1112    Endcall = ffi::AKEYCODE_ENDCALL as i32,
1113    Keycode0 = ffi::AKEYCODE_0 as i32,
1114    Keycode1 = ffi::AKEYCODE_1 as i32,
1115    Keycode2 = ffi::AKEYCODE_2 as i32,
1116    Keycode3 = ffi::AKEYCODE_3 as i32,
1117    Keycode4 = ffi::AKEYCODE_4 as i32,
1118    Keycode5 = ffi::AKEYCODE_5 as i32,
1119    Keycode6 = ffi::AKEYCODE_6 as i32,
1120    Keycode7 = ffi::AKEYCODE_7 as i32,
1121    Keycode8 = ffi::AKEYCODE_8 as i32,
1122    Keycode9 = ffi::AKEYCODE_9 as i32,
1123    Star = ffi::AKEYCODE_STAR as i32,
1124    Pound = ffi::AKEYCODE_POUND as i32,
1125    DpadUp = ffi::AKEYCODE_DPAD_UP as i32,
1126    DpadDown = ffi::AKEYCODE_DPAD_DOWN as i32,
1127    DpadLeft = ffi::AKEYCODE_DPAD_LEFT as i32,
1128    DpadRight = ffi::AKEYCODE_DPAD_RIGHT as i32,
1129    DpadCenter = ffi::AKEYCODE_DPAD_CENTER as i32,
1130    VolumeUp = ffi::AKEYCODE_VOLUME_UP as i32,
1131    VolumeDown = ffi::AKEYCODE_VOLUME_DOWN as i32,
1132    Power = ffi::AKEYCODE_POWER as i32,
1133    Camera = ffi::AKEYCODE_CAMERA as i32,
1134    Clear = ffi::AKEYCODE_CLEAR as i32,
1135    A = ffi::AKEYCODE_A as i32,
1136    B = ffi::AKEYCODE_B as i32,
1137    C = ffi::AKEYCODE_C as i32,
1138    D = ffi::AKEYCODE_D as i32,
1139    E = ffi::AKEYCODE_E as i32,
1140    F = ffi::AKEYCODE_F as i32,
1141    G = ffi::AKEYCODE_G as i32,
1142    H = ffi::AKEYCODE_H as i32,
1143    I = ffi::AKEYCODE_I as i32,
1144    J = ffi::AKEYCODE_J as i32,
1145    K = ffi::AKEYCODE_K as i32,
1146    L = ffi::AKEYCODE_L as i32,
1147    M = ffi::AKEYCODE_M as i32,
1148    N = ffi::AKEYCODE_N as i32,
1149    O = ffi::AKEYCODE_O as i32,
1150    P = ffi::AKEYCODE_P as i32,
1151    Q = ffi::AKEYCODE_Q as i32,
1152    R = ffi::AKEYCODE_R as i32,
1153    S = ffi::AKEYCODE_S as i32,
1154    T = ffi::AKEYCODE_T as i32,
1155    U = ffi::AKEYCODE_U as i32,
1156    V = ffi::AKEYCODE_V as i32,
1157    W = ffi::AKEYCODE_W as i32,
1158    X = ffi::AKEYCODE_X as i32,
1159    Y = ffi::AKEYCODE_Y as i32,
1160    Z = ffi::AKEYCODE_Z as i32,
1161    Comma = ffi::AKEYCODE_COMMA as i32,
1162    Period = ffi::AKEYCODE_PERIOD as i32,
1163    AltLeft = ffi::AKEYCODE_ALT_LEFT as i32,
1164    AltRight = ffi::AKEYCODE_ALT_RIGHT as i32,
1165    ShiftLeft = ffi::AKEYCODE_SHIFT_LEFT as i32,
1166    ShiftRight = ffi::AKEYCODE_SHIFT_RIGHT as i32,
1167    Tab = ffi::AKEYCODE_TAB as i32,
1168    Space = ffi::AKEYCODE_SPACE as i32,
1169    Sym = ffi::AKEYCODE_SYM as i32,
1170    Explorer = ffi::AKEYCODE_EXPLORER as i32,
1171    Envelope = ffi::AKEYCODE_ENVELOPE as i32,
1172    Enter = ffi::AKEYCODE_ENTER as i32,
1173    Del = ffi::AKEYCODE_DEL as i32,
1174    Grave = ffi::AKEYCODE_GRAVE as i32,
1175    Minus = ffi::AKEYCODE_MINUS as i32,
1176    Equals = ffi::AKEYCODE_EQUALS as i32,
1177    LeftBracket = ffi::AKEYCODE_LEFT_BRACKET as i32,
1178    RightBracket = ffi::AKEYCODE_RIGHT_BRACKET as i32,
1179    Backslash = ffi::AKEYCODE_BACKSLASH as i32,
1180    Semicolon = ffi::AKEYCODE_SEMICOLON as i32,
1181    Apostrophe = ffi::AKEYCODE_APOSTROPHE as i32,
1182    Slash = ffi::AKEYCODE_SLASH as i32,
1183    At = ffi::AKEYCODE_AT as i32,
1184    Num = ffi::AKEYCODE_NUM as i32,
1185    Headsethook = ffi::AKEYCODE_HEADSETHOOK as i32,
1186    Focus = ffi::AKEYCODE_FOCUS as i32,
1187    Plus = ffi::AKEYCODE_PLUS as i32,
1188    Menu = ffi::AKEYCODE_MENU as i32,
1189    Notification = ffi::AKEYCODE_NOTIFICATION as i32,
1190    Search = ffi::AKEYCODE_SEARCH as i32,
1191    MediaPlayPause = ffi::AKEYCODE_MEDIA_PLAY_PAUSE as i32,
1192    MediaStop = ffi::AKEYCODE_MEDIA_STOP as i32,
1193    MediaNext = ffi::AKEYCODE_MEDIA_NEXT as i32,
1194    MediaPrevious = ffi::AKEYCODE_MEDIA_PREVIOUS as i32,
1195    MediaRewind = ffi::AKEYCODE_MEDIA_REWIND as i32,
1196    MediaFastForward = ffi::AKEYCODE_MEDIA_FAST_FORWARD as i32,
1197    Mute = ffi::AKEYCODE_MUTE as i32,
1198    PageUp = ffi::AKEYCODE_PAGE_UP as i32,
1199    PageDown = ffi::AKEYCODE_PAGE_DOWN as i32,
1200    Pictsymbols = ffi::AKEYCODE_PICTSYMBOLS as i32,
1201    SwitchCharset = ffi::AKEYCODE_SWITCH_CHARSET as i32,
1202    ButtonA = ffi::AKEYCODE_BUTTON_A as i32,
1203    ButtonB = ffi::AKEYCODE_BUTTON_B as i32,
1204    ButtonC = ffi::AKEYCODE_BUTTON_C as i32,
1205    ButtonX = ffi::AKEYCODE_BUTTON_X as i32,
1206    ButtonY = ffi::AKEYCODE_BUTTON_Y as i32,
1207    ButtonZ = ffi::AKEYCODE_BUTTON_Z as i32,
1208    ButtonL1 = ffi::AKEYCODE_BUTTON_L1 as i32,
1209    ButtonR1 = ffi::AKEYCODE_BUTTON_R1 as i32,
1210    ButtonL2 = ffi::AKEYCODE_BUTTON_L2 as i32,
1211    ButtonR2 = ffi::AKEYCODE_BUTTON_R2 as i32,
1212    ButtonThumbl = ffi::AKEYCODE_BUTTON_THUMBL as i32,
1213    ButtonThumbr = ffi::AKEYCODE_BUTTON_THUMBR as i32,
1214    ButtonStart = ffi::AKEYCODE_BUTTON_START as i32,
1215    ButtonSelect = ffi::AKEYCODE_BUTTON_SELECT as i32,
1216    ButtonMode = ffi::AKEYCODE_BUTTON_MODE as i32,
1217    Escape = ffi::AKEYCODE_ESCAPE as i32,
1218    ForwardDel = ffi::AKEYCODE_FORWARD_DEL as i32,
1219    CtrlLeft = ffi::AKEYCODE_CTRL_LEFT as i32,
1220    CtrlRight = ffi::AKEYCODE_CTRL_RIGHT as i32,
1221    CapsLock = ffi::AKEYCODE_CAPS_LOCK as i32,
1222    ScrollLock = ffi::AKEYCODE_SCROLL_LOCK as i32,
1223    MetaLeft = ffi::AKEYCODE_META_LEFT as i32,
1224    MetaRight = ffi::AKEYCODE_META_RIGHT as i32,
1225    Function = ffi::AKEYCODE_FUNCTION as i32,
1226    Sysrq = ffi::AKEYCODE_SYSRQ as i32,
1227    Break = ffi::AKEYCODE_BREAK as i32,
1228    MoveHome = ffi::AKEYCODE_MOVE_HOME as i32,
1229    MoveEnd = ffi::AKEYCODE_MOVE_END as i32,
1230    Insert = ffi::AKEYCODE_INSERT as i32,
1231    Forward = ffi::AKEYCODE_FORWARD as i32,
1232    MediaPlay = ffi::AKEYCODE_MEDIA_PLAY as i32,
1233    MediaPause = ffi::AKEYCODE_MEDIA_PAUSE as i32,
1234    MediaClose = ffi::AKEYCODE_MEDIA_CLOSE as i32,
1235    MediaEject = ffi::AKEYCODE_MEDIA_EJECT as i32,
1236    MediaRecord = ffi::AKEYCODE_MEDIA_RECORD as i32,
1237    F1 = ffi::AKEYCODE_F1 as i32,
1238    F2 = ffi::AKEYCODE_F2 as i32,
1239    F3 = ffi::AKEYCODE_F3 as i32,
1240    F4 = ffi::AKEYCODE_F4 as i32,
1241    F5 = ffi::AKEYCODE_F5 as i32,
1242    F6 = ffi::AKEYCODE_F6 as i32,
1243    F7 = ffi::AKEYCODE_F7 as i32,
1244    F8 = ffi::AKEYCODE_F8 as i32,
1245    F9 = ffi::AKEYCODE_F9 as i32,
1246    F10 = ffi::AKEYCODE_F10 as i32,
1247    F11 = ffi::AKEYCODE_F11 as i32,
1248    F12 = ffi::AKEYCODE_F12 as i32,
1249    NumLock = ffi::AKEYCODE_NUM_LOCK as i32,
1250    Numpad0 = ffi::AKEYCODE_NUMPAD_0 as i32,
1251    Numpad1 = ffi::AKEYCODE_NUMPAD_1 as i32,
1252    Numpad2 = ffi::AKEYCODE_NUMPAD_2 as i32,
1253    Numpad3 = ffi::AKEYCODE_NUMPAD_3 as i32,
1254    Numpad4 = ffi::AKEYCODE_NUMPAD_4 as i32,
1255    Numpad5 = ffi::AKEYCODE_NUMPAD_5 as i32,
1256    Numpad6 = ffi::AKEYCODE_NUMPAD_6 as i32,
1257    Numpad7 = ffi::AKEYCODE_NUMPAD_7 as i32,
1258    Numpad8 = ffi::AKEYCODE_NUMPAD_8 as i32,
1259    Numpad9 = ffi::AKEYCODE_NUMPAD_9 as i32,
1260    NumpadDivide = ffi::AKEYCODE_NUMPAD_DIVIDE as i32,
1261    NumpadMultiply = ffi::AKEYCODE_NUMPAD_MULTIPLY as i32,
1262    NumpadSubtract = ffi::AKEYCODE_NUMPAD_SUBTRACT as i32,
1263    NumpadAdd = ffi::AKEYCODE_NUMPAD_ADD as i32,
1264    NumpadDot = ffi::AKEYCODE_NUMPAD_DOT as i32,
1265    NumpadComma = ffi::AKEYCODE_NUMPAD_COMMA as i32,
1266    NumpadEnter = ffi::AKEYCODE_NUMPAD_ENTER as i32,
1267    NumpadEquals = ffi::AKEYCODE_NUMPAD_EQUALS as i32,
1268    NumpadLeftParen = ffi::AKEYCODE_NUMPAD_LEFT_PAREN as i32,
1269    NumpadRightParen = ffi::AKEYCODE_NUMPAD_RIGHT_PAREN as i32,
1270    VolumeMute = ffi::AKEYCODE_VOLUME_MUTE as i32,
1271    Info = ffi::AKEYCODE_INFO as i32,
1272    ChannelUp = ffi::AKEYCODE_CHANNEL_UP as i32,
1273    ChannelDown = ffi::AKEYCODE_CHANNEL_DOWN as i32,
1274    ZoomIn = ffi::AKEYCODE_ZOOM_IN as i32,
1275    ZoomOut = ffi::AKEYCODE_ZOOM_OUT as i32,
1276    Tv = ffi::AKEYCODE_TV as i32,
1277    Window = ffi::AKEYCODE_WINDOW as i32,
1278    Guide = ffi::AKEYCODE_GUIDE as i32,
1279    Dvr = ffi::AKEYCODE_DVR as i32,
1280    Bookmark = ffi::AKEYCODE_BOOKMARK as i32,
1281    Captions = ffi::AKEYCODE_CAPTIONS as i32,
1282    Settings = ffi::AKEYCODE_SETTINGS as i32,
1283    TvPower = ffi::AKEYCODE_TV_POWER as i32,
1284    TvInput = ffi::AKEYCODE_TV_INPUT as i32,
1285    StbPower = ffi::AKEYCODE_STB_POWER as i32,
1286    StbInput = ffi::AKEYCODE_STB_INPUT as i32,
1287    AvrPower = ffi::AKEYCODE_AVR_POWER as i32,
1288    AvrInput = ffi::AKEYCODE_AVR_INPUT as i32,
1289    ProgRed = ffi::AKEYCODE_PROG_RED as i32,
1290    ProgGreen = ffi::AKEYCODE_PROG_GREEN as i32,
1291    ProgYellow = ffi::AKEYCODE_PROG_YELLOW as i32,
1292    ProgBlue = ffi::AKEYCODE_PROG_BLUE as i32,
1293    AppSwitch = ffi::AKEYCODE_APP_SWITCH as i32,
1294    Button1 = ffi::AKEYCODE_BUTTON_1 as i32,
1295    Button2 = ffi::AKEYCODE_BUTTON_2 as i32,
1296    Button3 = ffi::AKEYCODE_BUTTON_3 as i32,
1297    Button4 = ffi::AKEYCODE_BUTTON_4 as i32,
1298    Button5 = ffi::AKEYCODE_BUTTON_5 as i32,
1299    Button6 = ffi::AKEYCODE_BUTTON_6 as i32,
1300    Button7 = ffi::AKEYCODE_BUTTON_7 as i32,
1301    Button8 = ffi::AKEYCODE_BUTTON_8 as i32,
1302    Button9 = ffi::AKEYCODE_BUTTON_9 as i32,
1303    Button10 = ffi::AKEYCODE_BUTTON_10 as i32,
1304    Button11 = ffi::AKEYCODE_BUTTON_11 as i32,
1305    Button12 = ffi::AKEYCODE_BUTTON_12 as i32,
1306    Button13 = ffi::AKEYCODE_BUTTON_13 as i32,
1307    Button14 = ffi::AKEYCODE_BUTTON_14 as i32,
1308    Button15 = ffi::AKEYCODE_BUTTON_15 as i32,
1309    Button16 = ffi::AKEYCODE_BUTTON_16 as i32,
1310    LanguageSwitch = ffi::AKEYCODE_LANGUAGE_SWITCH as i32,
1311    MannerMode = ffi::AKEYCODE_MANNER_MODE as i32,
1312    Keycode3dMode = ffi::AKEYCODE_3D_MODE as i32,
1313    Contacts = ffi::AKEYCODE_CONTACTS as i32,
1314    Calendar = ffi::AKEYCODE_CALENDAR as i32,
1315    Music = ffi::AKEYCODE_MUSIC as i32,
1316    Calculator = ffi::AKEYCODE_CALCULATOR as i32,
1317    ZenkakuHankaku = ffi::AKEYCODE_ZENKAKU_HANKAKU as i32,
1318    Eisu = ffi::AKEYCODE_EISU as i32,
1319    Muhenkan = ffi::AKEYCODE_MUHENKAN as i32,
1320    Henkan = ffi::AKEYCODE_HENKAN as i32,
1321    KatakanaHiragana = ffi::AKEYCODE_KATAKANA_HIRAGANA as i32,
1322    Yen = ffi::AKEYCODE_YEN as i32,
1323    Ro = ffi::AKEYCODE_RO as i32,
1324    Kana = ffi::AKEYCODE_KANA as i32,
1325    Assist = ffi::AKEYCODE_ASSIST as i32,
1326    BrightnessDown = ffi::AKEYCODE_BRIGHTNESS_DOWN as i32,
1327    BrightnessUp = ffi::AKEYCODE_BRIGHTNESS_UP as i32,
1328    MediaAudioTrack = ffi::AKEYCODE_MEDIA_AUDIO_TRACK as i32,
1329    Sleep = ffi::AKEYCODE_SLEEP as i32,
1330    Wakeup = ffi::AKEYCODE_WAKEUP as i32,
1331    Pairing = ffi::AKEYCODE_PAIRING as i32,
1332    MediaTopMenu = ffi::AKEYCODE_MEDIA_TOP_MENU as i32,
1333    Keycode11 = ffi::AKEYCODE_11 as i32,
1334    Keycode12 = ffi::AKEYCODE_12 as i32,
1335    LastChannel = ffi::AKEYCODE_LAST_CHANNEL as i32,
1336    TvDataService = ffi::AKEYCODE_TV_DATA_SERVICE as i32,
1337    VoiceAssist = ffi::AKEYCODE_VOICE_ASSIST as i32,
1338    TvRadioService = ffi::AKEYCODE_TV_RADIO_SERVICE as i32,
1339    TvTeletext = ffi::AKEYCODE_TV_TELETEXT as i32,
1340    TvNumberEntry = ffi::AKEYCODE_TV_NUMBER_ENTRY as i32,
1341    TvTerrestrialAnalog = ffi::AKEYCODE_TV_TERRESTRIAL_ANALOG as i32,
1342    TvTerrestrialDigital = ffi::AKEYCODE_TV_TERRESTRIAL_DIGITAL as i32,
1343    TvSatellite = ffi::AKEYCODE_TV_SATELLITE as i32,
1344    TvSatelliteBs = ffi::AKEYCODE_TV_SATELLITE_BS as i32,
1345    TvSatelliteCs = ffi::AKEYCODE_TV_SATELLITE_CS as i32,
1346    TvSatelliteService = ffi::AKEYCODE_TV_SATELLITE_SERVICE as i32,
1347    TvNetwork = ffi::AKEYCODE_TV_NETWORK as i32,
1348    TvAntennaCable = ffi::AKEYCODE_TV_ANTENNA_CABLE as i32,
1349    TvInputHdmi1 = ffi::AKEYCODE_TV_INPUT_HDMI_1 as i32,
1350    TvInputHdmi2 = ffi::AKEYCODE_TV_INPUT_HDMI_2 as i32,
1351    TvInputHdmi3 = ffi::AKEYCODE_TV_INPUT_HDMI_3 as i32,
1352    TvInputHdmi4 = ffi::AKEYCODE_TV_INPUT_HDMI_4 as i32,
1353    TvInputComposite1 = ffi::AKEYCODE_TV_INPUT_COMPOSITE_1 as i32,
1354    TvInputComposite2 = ffi::AKEYCODE_TV_INPUT_COMPOSITE_2 as i32,
1355    TvInputComponent1 = ffi::AKEYCODE_TV_INPUT_COMPONENT_1 as i32,
1356    TvInputComponent2 = ffi::AKEYCODE_TV_INPUT_COMPONENT_2 as i32,
1357    TvInputVga1 = ffi::AKEYCODE_TV_INPUT_VGA_1 as i32,
1358    TvAudioDescription = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION as i32,
1359    TvAudioDescriptionMixUp = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP as i32,
1360    TvAudioDescriptionMixDown = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN as i32,
1361    TvZoomMode = ffi::AKEYCODE_TV_ZOOM_MODE as i32,
1362    TvContentsMenu = ffi::AKEYCODE_TV_CONTENTS_MENU as i32,
1363    TvMediaContextMenu = ffi::AKEYCODE_TV_MEDIA_CONTEXT_MENU as i32,
1364    TvTimerProgramming = ffi::AKEYCODE_TV_TIMER_PROGRAMMING as i32,
1365    Help = ffi::AKEYCODE_HELP as i32,
1366    NavigatePrevious = ffi::AKEYCODE_NAVIGATE_PREVIOUS as i32,
1367    NavigateNext = ffi::AKEYCODE_NAVIGATE_NEXT as i32,
1368    NavigateIn = ffi::AKEYCODE_NAVIGATE_IN as i32,
1369    NavigateOut = ffi::AKEYCODE_NAVIGATE_OUT as i32,
1370    StemPrimary = ffi::AKEYCODE_STEM_PRIMARY as i32,
1371    Stem1 = ffi::AKEYCODE_STEM_1 as i32,
1372    Stem2 = ffi::AKEYCODE_STEM_2 as i32,
1373    Stem3 = ffi::AKEYCODE_STEM_3 as i32,
1374    DpadUpLeft = ffi::AKEYCODE_DPAD_UP_LEFT as i32,
1375    DpadDownLeft = ffi::AKEYCODE_DPAD_DOWN_LEFT as i32,
1376    DpadUpRight = ffi::AKEYCODE_DPAD_UP_RIGHT as i32,
1377    DpadDownRight = ffi::AKEYCODE_DPAD_DOWN_RIGHT as i32,
1378    MediaSkipForward = ffi::AKEYCODE_MEDIA_SKIP_FORWARD as i32,
1379    MediaSkipBackward = ffi::AKEYCODE_MEDIA_SKIP_BACKWARD as i32,
1380    MediaStepForward = ffi::AKEYCODE_MEDIA_STEP_FORWARD as i32,
1381    MediaStepBackward = ffi::AKEYCODE_MEDIA_STEP_BACKWARD as i32,
1382    SoftSleep = ffi::AKEYCODE_SOFT_SLEEP as i32,
1383    Cut = ffi::AKEYCODE_CUT as i32,
1384    Copy = ffi::AKEYCODE_COPY as i32,
1385    Paste = ffi::AKEYCODE_PASTE as i32,
1386    SystemNavigationUp = ffi::AKEYCODE_SYSTEM_NAVIGATION_UP as i32,
1387    SystemNavigationDown = ffi::AKEYCODE_SYSTEM_NAVIGATION_DOWN as i32,
1388    SystemNavigationLeft = ffi::AKEYCODE_SYSTEM_NAVIGATION_LEFT as i32,
1389    SystemNavigationRight = ffi::AKEYCODE_SYSTEM_NAVIGATION_RIGHT as i32,
1390    AllApps = ffi::AKEYCODE_ALL_APPS as i32,
1391    Refresh = ffi::AKEYCODE_REFRESH as i32,
1392    ThumbsUp = ffi::AKEYCODE_THUMBS_UP as i32,
1393    ThumbsDown = ffi::AKEYCODE_THUMBS_DOWN as i32,
1394    ProfileSwitch = ffi::AKEYCODE_PROFILE_SWITCH as i32,
1395
1396    #[doc(hidden)]
1397    #[num_enum(catch_all)]
1398    __Unknown(i32),
1399}
1400
1401impl KeyEvent {
1402    /// Constructs a KeyEvent from a pointer to a native [`ffi::AInputEvent`]
1403    ///
1404    /// # Safety
1405    /// By calling this method, you assert that the pointer is a valid, non-null pointer to an
1406    /// [`ffi::AInputEvent`], and that [`ffi::AInputEvent`] is an `AKeyEvent`.
1407    #[inline]
1408    pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
1409        Self { ptr }
1410    }
1411
1412    /// Creates a native [`InputEvent`] object that is a copy of the specified Java
1413    /// [`android.view.KeyEvent`]. The result may be used with generic and [`KeyEvent`]-specific
1414    /// functions.
1415    ///
1416    /// # Safety
1417    ///
1418    /// This function should be called with a healthy JVM pointer and with a non-null
1419    /// [`android.view.KeyEvent`].
1420    ///
1421    /// [`android.view.KeyEvent`]: https://developer.android.com/reference/android/view/KeyEvent
1422    #[cfg(feature = "api-level-31")]
1423    #[doc(alias = "AKeyEvent_fromJava")]
1424    pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
1425        let ptr = unsafe { ffi::AKeyEvent_fromJava(env, key_event) };
1426        Some(InputEventJava(InputEvent::KeyEvent(Self::from_ptr(
1427            NonNull::new(ptr.cast_mut())?,
1428        ))))
1429    }
1430
1431    /// Returns a pointer to the native [`ffi::AInputEvent`].
1432    #[inline]
1433    pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
1434        self.ptr
1435    }
1436
1437    /// Returns the key action represented by this event.
1438    ///
1439    /// See [the NDK
1440    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getaction)
1441    #[inline]
1442    pub fn action(&self) -> KeyAction {
1443        let action = unsafe { ffi::AKeyEvent_getAction(self.ptr.as_ptr()) };
1444        action.into()
1445    }
1446
1447    /// Get the source of the event.
1448    ///
1449    /// See [the NDK
1450    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getsource)
1451    #[inline]
1452    pub fn source(&self) -> Source {
1453        let source = unsafe { ffi::AInputEvent_getSource(self.ptr.as_ptr()) };
1454        source.into()
1455    }
1456
1457    /// Get the device id associated with the event.
1458    ///
1459    /// See [the NDK
1460    /// docs](https://developer.android.com/ndk/reference/group/input#ainputevent_getdeviceid)
1461    #[inline]
1462    pub fn device_id(&self) -> i32 {
1463        unsafe { ffi::AInputEvent_getDeviceId(self.ptr.as_ptr()) }
1464    }
1465
1466    /// Returns the last time the key was pressed.  This is on the scale of
1467    /// `java.lang.System.nanoTime()`, which has nanosecond precision, but no defined start time.
1468    ///
1469    /// See [the NDK
1470    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getdowntime)
1471    #[inline]
1472    pub fn down_time(&self) -> i64 {
1473        unsafe { ffi::AKeyEvent_getDownTime(self.ptr.as_ptr()) }
1474    }
1475
1476    /// Returns the time this event occured.  This is on the scale of
1477    /// `java.lang.System.nanoTime()`, which has nanosecond precision, but no defined start time.
1478    ///
1479    /// See [the NDK
1480    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_geteventtime)
1481    #[inline]
1482    pub fn event_time(&self) -> i64 {
1483        unsafe { ffi::AKeyEvent_getEventTime(self.ptr.as_ptr()) }
1484    }
1485
1486    /// Returns the keycode associated with this key event
1487    ///
1488    /// See [the NDK
1489    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getkeycode)
1490    #[inline]
1491    pub fn key_code(&self) -> Keycode {
1492        let keycode = unsafe { ffi::AKeyEvent_getKeyCode(self.ptr.as_ptr()) };
1493        keycode.into()
1494    }
1495
1496    /// Returns the number of repeats of a key.
1497    ///
1498    /// See [the NDK
1499    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getrepeatcount)
1500    #[inline]
1501    pub fn repeat_count(&self) -> i32 {
1502        unsafe { ffi::AKeyEvent_getRepeatCount(self.ptr.as_ptr()) }
1503    }
1504
1505    /// Returns the hardware keycode of a key.  This varies from device to device.
1506    ///
1507    /// See [the NDK
1508    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getscancode)
1509    #[inline]
1510    pub fn scan_code(&self) -> i32 {
1511        unsafe { ffi::AKeyEvent_getScanCode(self.ptr.as_ptr()) }
1512    }
1513}
1514
1515/// Flags associated with [`KeyEvent`].
1516#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1517pub struct KeyEventFlags(pub u32);
1518
1519impl KeyEventFlags {
1520    #[inline]
1521    pub fn cancelled(&self) -> bool {
1522        self.0 & ffi::AKEY_EVENT_FLAG_CANCELED != 0
1523    }
1524    #[inline]
1525    pub fn cancelled_long_press(&self) -> bool {
1526        self.0 & ffi::AKEY_EVENT_FLAG_CANCELED_LONG_PRESS != 0
1527    }
1528    #[inline]
1529    pub fn editor_action(&self) -> bool {
1530        self.0 & ffi::AKEY_EVENT_FLAG_EDITOR_ACTION != 0
1531    }
1532    #[inline]
1533    pub fn fallback(&self) -> bool {
1534        self.0 & ffi::AKEY_EVENT_FLAG_FALLBACK != 0
1535    }
1536    #[inline]
1537    pub fn from_system(&self) -> bool {
1538        self.0 & ffi::AKEY_EVENT_FLAG_FROM_SYSTEM != 0
1539    }
1540    #[inline]
1541    pub fn keep_touch_mode(&self) -> bool {
1542        self.0 & ffi::AKEY_EVENT_FLAG_KEEP_TOUCH_MODE != 0
1543    }
1544    #[inline]
1545    pub fn long_press(&self) -> bool {
1546        self.0 & ffi::AKEY_EVENT_FLAG_LONG_PRESS != 0
1547    }
1548    #[inline]
1549    pub fn soft_keyboard(&self) -> bool {
1550        self.0 & ffi::AKEY_EVENT_FLAG_SOFT_KEYBOARD != 0
1551    }
1552    #[inline]
1553    pub fn tracking(&self) -> bool {
1554        self.0 & ffi::AKEY_EVENT_FLAG_TRACKING != 0
1555    }
1556    #[inline]
1557    pub fn virtual_hard_key(&self) -> bool {
1558        self.0 & ffi::AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY != 0
1559    }
1560    #[inline]
1561    pub fn woke_here(&self) -> bool {
1562        self.0 & ffi::AKEY_EVENT_FLAG_WOKE_HERE != 0
1563    }
1564}
1565
1566impl KeyEvent {
1567    /// Flags associated with this [`KeyEvent`].
1568    ///
1569    /// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getflags)
1570    #[inline]
1571    pub fn flags(&self) -> KeyEventFlags {
1572        unsafe { KeyEventFlags(ffi::AKeyEvent_getFlags(self.ptr.as_ptr()) as u32) }
1573    }
1574
1575    /// Returns the state of the modifiers during this key event, represented by a bitmask.
1576    ///
1577    /// See [the NDK
1578    /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getmetastate)
1579    #[inline]
1580    pub fn meta_state(&self) -> MetaState {
1581        unsafe { MetaState(ffi::AKeyEvent_getMetaState(self.ptr.as_ptr()) as u32) }
1582    }
1583}