1 // TODO: mod docs
2 
3 use std::os::raw::c_int;
4 use std::ptr;
5 use std::ptr::NonNull;
6 
7 use crate::event::InputEvent;
8 use crate::looper::ForeignLooper;
9 
10 // TODO docs
11 #[derive(Debug)]
12 pub struct InputQueue {
13     ptr: NonNull<ffi::AInputQueue>,
14 }
15 
16 // It gets shared between threads in android_native_app_glue
17 unsafe impl Send for InputQueue {}
18 unsafe impl Sync for InputQueue {}
19 
20 #[derive(Debug)]
21 pub struct InputQueueError;
22 
23 impl InputQueue {
24     /// Construct an `InputQueue` from the native pointer.
25     ///
26     /// By calling this function, you assert that the pointer is a valid pointer to an NDK `AInputQueue`.
from_ptr(ptr: NonNull<ffi::AInputQueue>) -> Self27     pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputQueue>) -> Self {
28         Self { ptr }
29     }
30 
ptr(&self) -> NonNull<ffi::AInputQueue>31     pub fn ptr(&self) -> NonNull<ffi::AInputQueue> {
32         self.ptr
33     }
34 
get_event(&self) -> Option<InputEvent>35     pub fn get_event(&self) -> Option<InputEvent> {
36         unsafe {
37             let mut out_event = ptr::null_mut();
38             if ffi::AInputQueue_getEvent(self.ptr.as_ptr(), &mut out_event) < 0 {
39                 None
40             } else {
41                 debug_assert!(!out_event.is_null());
42                 Some(InputEvent::from_ptr(NonNull::new_unchecked(out_event)))
43             }
44         }
45     }
46 
has_events(&self) -> Result<bool, InputQueueError>47     pub fn has_events(&self) -> Result<bool, InputQueueError> {
48         unsafe {
49             match ffi::AInputQueue_hasEvents(self.ptr.as_ptr()) {
50                 0 => Ok(false),
51                 1 => Ok(true),
52                 x if x < 0 => Err(InputQueueError),
53                 x => unreachable!("AInputQueue_hasEvents returned {}", x),
54             }
55         }
56     }
57 
pre_dispatch(&self, event: InputEvent) -> Option<InputEvent>58     pub fn pre_dispatch(&self, event: InputEvent) -> Option<InputEvent> {
59         unsafe {
60             if ffi::AInputQueue_preDispatchEvent(self.ptr.as_ptr(), event.ptr().as_ptr()) == 0 {
61                 Some(event)
62             } else {
63                 None
64             }
65         }
66     }
67 
finish_event(&self, event: InputEvent, handled: bool)68     pub fn finish_event(&self, event: InputEvent, handled: bool) {
69         unsafe {
70             ffi::AInputQueue_finishEvent(self.ptr.as_ptr(), event.ptr().as_ptr(), handled as c_int);
71         }
72     }
73 
attach_looper(&self, looper: &ForeignLooper, id: i32)74     pub fn attach_looper(&self, looper: &ForeignLooper, id: i32) {
75         unsafe {
76             ffi::AInputQueue_attachLooper(
77                 self.ptr.as_ptr(),
78                 looper.ptr().as_ptr(),
79                 id,
80                 None,
81                 std::ptr::null_mut(),
82             );
83         }
84     }
85 
detach_looper(&self)86     pub fn detach_looper(&self) {
87         unsafe {
88             ffi::AInputQueue_detachLooper(self.ptr.as_ptr());
89         }
90     }
91 }
92