android_ndk/
event.rs

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