use std::{iter::FusedIterator, marker::PhantomData, ptr::NonNull};
use crate::input::{
Axis, Button, ButtonState, EdgeFlags, KeyAction, Keycode, MetaState, MotionAction,
MotionEventFlags, Pointer, PointersIter, Source, ToolType,
};
#[derive(Debug)]
#[repr(transparent)]
pub struct MotionEvent<'a> {
ndk_event: ndk::event::MotionEvent,
_lifetime: PhantomData<&'a ndk::event::MotionEvent>,
}
impl MotionEvent<'_> {
pub(crate) fn new(ndk_event: ndk::event::MotionEvent) -> Self {
Self {
ndk_event,
_lifetime: PhantomData,
}
}
pub(crate) fn into_ndk_event(self) -> ndk::event::MotionEvent {
self.ndk_event
}
#[inline]
pub fn source(&self) -> Source {
let source =
unsafe { ndk_sys::AInputEvent_getSource(self.ndk_event.ptr().as_ptr()) as u32 };
source.into()
}
#[inline]
pub fn device_id(&self) -> i32 {
self.ndk_event.device_id()
}
#[inline]
pub fn action(&self) -> MotionAction {
let action =
unsafe { ndk_sys::AMotionEvent_getAction(self.ndk_event.ptr().as_ptr()) as u32 }
& ndk_sys::AMOTION_EVENT_ACTION_MASK;
action.into()
}
#[inline]
pub fn action_button(&self) -> Button {
let action_button =
unsafe { ndk_sys::AMotionEvent_getActionButton(self.ndk_event.ptr().as_ptr()) as u32 };
action_button.into()
}
#[inline]
pub fn pointer_index(&self) -> usize {
self.ndk_event.pointer_index()
}
#[inline]
pub fn pointer_count(&self) -> usize {
self.ndk_event.pointer_count()
}
#[inline]
pub fn pointers(&self) -> PointersIter<'_> {
PointersIter {
inner: PointersIterImpl {
event: self.ndk_event.ptr(),
pointer_index: 0,
pointer_count: self.ndk_event.pointer_count(),
_marker: std::marker::PhantomData,
},
}
}
#[inline]
pub fn pointer_at_index(&self, index: usize) -> Pointer<'_> {
Pointer {
inner: PointerImpl {
event: self.ndk_event.ptr(),
pointer_index: index,
_marker: std::marker::PhantomData,
},
}
}
#[inline]
pub fn meta_state(&self) -> MetaState {
self.ndk_event.meta_state().into()
}
#[inline]
pub fn button_state(&self) -> ButtonState {
self.ndk_event.button_state().into()
}
#[inline]
pub fn down_time(&self) -> i64 {
self.ndk_event.down_time()
}
#[inline]
pub fn edge_flags(&self) -> EdgeFlags {
self.ndk_event.edge_flags().into()
}
#[inline]
pub fn event_time(&self) -> i64 {
self.ndk_event.event_time()
}
#[inline]
pub fn flags(&self) -> MotionEventFlags {
self.ndk_event.flags().into()
}
#[inline]
pub fn x_precision(&self) -> f32 {
self.ndk_event.x_precision()
}
#[inline]
pub fn y_precision(&self) -> f32 {
self.ndk_event.y_precision()
}
}
#[derive(Debug)]
pub(crate) struct PointerImpl<'a> {
event: NonNull<ndk_sys::AInputEvent>,
pointer_index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent<'a>>,
}
impl PointerImpl<'_> {
#[inline]
pub fn pointer_index(&self) -> usize {
self.pointer_index
}
#[inline]
pub fn pointer_id(&self) -> i32 {
unsafe { ndk_sys::AMotionEvent_getPointerId(self.event.as_ptr(), self.pointer_index) }
}
#[inline]
pub fn axis_value(&self, axis: Axis) -> f32 {
let value: u32 = axis.into();
let value = value as i32;
unsafe {
ndk_sys::AMotionEvent_getAxisValue(self.event.as_ptr(), value, self.pointer_index)
}
}
#[inline]
pub fn raw_x(&self) -> f32 {
unsafe { ndk_sys::AMotionEvent_getRawX(self.event.as_ptr(), self.pointer_index) }
}
#[inline]
pub fn raw_y(&self) -> f32 {
unsafe { ndk_sys::AMotionEvent_getRawY(self.event.as_ptr(), self.pointer_index) }
}
#[inline]
pub fn tool_type(&self) -> ToolType {
let value =
unsafe { ndk_sys::AMotionEvent_getToolType(self.event.as_ptr(), self.pointer_index) };
let value = value as u32;
value.into()
}
pub fn history(&self) -> crate::input::PointerHistoryIter<'_> {
let history_size =
unsafe { ndk_sys::AMotionEvent_getHistorySize(self.event.as_ptr()) } as usize;
crate::input::PointerHistoryIter {
inner: PointerHistoryIterImpl {
event: self.event,
pointer_index: self.pointer_index,
front: 0,
back: history_size,
_marker: std::marker::PhantomData,
},
}
}
}
#[derive(Debug)]
pub(crate) struct PointersIterImpl<'a> {
event: NonNull<ndk_sys::AInputEvent>,
pointer_count: usize,
pointer_index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent<'a>>,
}
impl<'a> Iterator for PointersIterImpl<'a> {
type Item = Pointer<'a>;
fn next(&mut self) -> Option<Pointer<'a>> {
if self.pointer_index == self.pointer_count {
return None;
}
let pointer = Pointer {
inner: PointerImpl {
event: self.event,
pointer_index: self.pointer_index,
_marker: std::marker::PhantomData,
},
};
self.pointer_index += 1;
Some(pointer)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.pointer_count - self.pointer_index;
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for PointersIterImpl<'_> {}
#[derive(Debug)]
pub struct HistoricalPointerImpl<'a> {
event: NonNull<ndk_sys::AInputEvent>,
pointer_index: usize,
history_index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent<'a>>,
}
impl<'a> HistoricalPointerImpl<'a> {
#[inline]
pub fn pointer_index(&self) -> usize {
self.pointer_index
}
#[inline]
pub fn event_time(&self) -> i64 {
unsafe {
ndk_sys::AMotionEvent_getHistoricalEventTime(self.event.as_ptr(), self.history_index)
}
}
#[inline]
pub fn pointer_id(&self) -> i32 {
unsafe { ndk_sys::AMotionEvent_getPointerId(self.event.as_ptr(), self.pointer_index) }
}
#[inline]
pub fn history_index(&self) -> usize {
self.history_index
}
#[inline]
pub fn axis_value(&self, axis: Axis) -> f32 {
unsafe {
ndk_sys::AMotionEvent_getHistoricalAxisValue(
self.event.as_ptr(),
Into::<u32>::into(axis) as i32,
self.pointer_index,
self.history_index,
)
}
}
}
#[derive(Debug)]
pub struct PointerHistoryIterImpl<'a> {
event: NonNull<ndk_sys::AInputEvent>,
pointer_index: usize,
front: usize,
back: usize,
_marker: std::marker::PhantomData<&'a MotionEvent<'a>>,
}
impl<'a> Iterator for PointerHistoryIterImpl<'a> {
type Item = crate::input::HistoricalPointer<'a>;
fn next(&mut self) -> Option<crate::input::HistoricalPointer<'a>> {
if self.front == self.back {
return None;
}
let history_index = self.front;
self.front += 1;
Some(crate::input::HistoricalPointer {
inner: crate::input::HistoricalPointerImpl {
event: self.event,
history_index,
pointer_index: self.pointer_index,
_marker: std::marker::PhantomData,
},
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.back - self.front;
(size, Some(size))
}
}
impl<'a> DoubleEndedIterator for PointerHistoryIterImpl<'a> {
fn next_back(&mut self) -> Option<crate::input::HistoricalPointer<'a>> {
if self.front == self.back {
return None;
}
self.back -= 1;
let history_index = self.back;
Some(crate::input::HistoricalPointer {
inner: crate::input::HistoricalPointerImpl {
event: self.event,
history_index,
pointer_index: self.pointer_index,
_marker: std::marker::PhantomData,
},
})
}
}
impl ExactSizeIterator for PointerHistoryIterImpl<'_> {}
impl FusedIterator for PointerHistoryIterImpl<'_> {}
#[derive(Debug)]
#[repr(transparent)]
pub struct KeyEvent<'a> {
ndk_event: ndk::event::KeyEvent,
_lifetime: PhantomData<&'a ndk::event::KeyEvent>,
}
impl KeyEvent<'_> {
pub(crate) fn new(ndk_event: ndk::event::KeyEvent) -> Self {
Self {
ndk_event,
_lifetime: PhantomData,
}
}
pub(crate) fn into_ndk_event(self) -> ndk::event::KeyEvent {
self.ndk_event
}
#[inline]
pub fn source(&self) -> Source {
let source =
unsafe { ndk_sys::AInputEvent_getSource(self.ndk_event.ptr().as_ptr()) as u32 };
source.into()
}
#[inline]
pub fn device_id(&self) -> i32 {
self.ndk_event.device_id()
}
#[inline]
pub fn action(&self) -> KeyAction {
let action = unsafe { ndk_sys::AKeyEvent_getAction(self.ndk_event.ptr().as_ptr()) as u32 };
action.into()
}
#[inline]
pub fn down_time(&self) -> i64 {
self.ndk_event.down_time()
}
#[inline]
pub fn event_time(&self) -> i64 {
self.ndk_event.event_time()
}
#[inline]
pub fn key_code(&self) -> Keycode {
let keycode =
unsafe { ndk_sys::AKeyEvent_getKeyCode(self.ndk_event.ptr().as_ptr()) as u32 };
keycode.into()
}
#[inline]
pub fn repeat_count(&self) -> i32 {
self.ndk_event.repeat_count()
}
#[inline]
pub fn scan_code(&self) -> i32 {
self.ndk_event.scan_code()
}
#[inline]
pub fn meta_state(&self) -> MetaState {
self.ndk_event.meta_state().into()
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum InputEvent<'a> {
MotionEvent(self::MotionEvent<'a>),
KeyEvent(self::KeyEvent<'a>),
TextEvent(crate::input::TextInputState),
TextAction(crate::input::TextInputAction),
}