use std::ptr::NonNull;
#[cfg(feature = "api-level-31")]
use jni_sys::{jobject, JNIEnv};
use num_enum::{FromPrimitive, IntoPrimitive};
#[derive(Debug)]
#[non_exhaustive]
pub enum InputEvent {
MotionEvent(MotionEvent),
KeyEvent(KeyEvent),
}
#[cfg(feature = "api-level-31")]
#[derive(Debug)]
pub struct InputEventJava(InputEvent);
#[cfg(feature = "api-level-31")]
impl Drop for InputEventJava {
#[doc(alias = "AInputEvent_release")]
fn drop(&mut self) {
let ptr = match self.0 {
InputEvent::MotionEvent(MotionEvent { ptr })
| InputEvent::KeyEvent(KeyEvent { ptr }) => ptr.as_ptr().cast(),
};
unsafe { ffi::AInputEvent_release(ptr) }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum Source {
Unknown = ffi::AINPUT_SOURCE_UNKNOWN as i32,
Keyboard = ffi::AINPUT_SOURCE_KEYBOARD as i32,
Dpad = ffi::AINPUT_SOURCE_DPAD as i32,
Gamepad = ffi::AINPUT_SOURCE_GAMEPAD as i32,
Touchscreen = ffi::AINPUT_SOURCE_TOUCHSCREEN as i32,
Mouse = ffi::AINPUT_SOURCE_MOUSE as i32,
Stylus = ffi::AINPUT_SOURCE_STYLUS as i32,
BluetoothStylus = ffi::AINPUT_SOURCE_BLUETOOTH_STYLUS as i32,
Trackball = ffi::AINPUT_SOURCE_TRACKBALL as i32,
MouseRelative = ffi::AINPUT_SOURCE_MOUSE_RELATIVE as i32,
Touchpad = ffi::AINPUT_SOURCE_TOUCHPAD as i32,
TouchNavigation = ffi::AINPUT_SOURCE_TOUCH_NAVIGATION as i32,
Joystick = ffi::AINPUT_SOURCE_JOYSTICK as i32,
Hdmi = ffi::AINPUT_SOURCE_HDMI as i32,
Sensor = ffi::AINPUT_SOURCE_SENSOR as i32,
RotaryEncoder = ffi::AINPUT_SOURCE_ROTARY_ENCODER as i32,
Any = ffi::AINPUT_SOURCE_ANY as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
impl Source {
pub fn class(self) -> SourceClass {
let class = i32::from(self) & ffi::AINPUT_SOURCE_CLASS_MASK as i32;
SourceClass::from_bits_retain(class as u8)
}
}
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SourceClass : u8 {
#[doc(alias = "AINPUT_SOURCE_CLASS_BUTTON")]
const BUTTON = ffi::AINPUT_SOURCE_CLASS_BUTTON as u8;
#[doc(alias = "AINPUT_SOURCE_CLASS_POINTER")]
const POINTER = ffi::AINPUT_SOURCE_CLASS_POINTER as u8;
#[doc(alias = "AINPUT_SOURCE_CLASS_NAVIGATION")]
const NAVIGATION = ffi::AINPUT_SOURCE_CLASS_NAVIGATION as u8;
#[doc(alias = "AINPUT_SOURCE_CLASS_POSITION")]
const POSITION = ffi::AINPUT_SOURCE_CLASS_POSITION as u8;
#[doc(alias = "AINPUT_SOURCE_CLASS_JOYSTICK")]
const JOYSTICK = ffi::AINPUT_SOURCE_CLASS_JOYSTICK as u8;
const _ = ffi::AINPUT_SOURCE_CLASS_MASK as u8;
}
}
impl InputEvent {
#[inline]
pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
match ffi::AInputEvent_getType(ptr.as_ptr()) as u32 {
ffi::AINPUT_EVENT_TYPE_KEY => InputEvent::KeyEvent(KeyEvent::from_ptr(ptr)),
ffi::AINPUT_EVENT_TYPE_MOTION => InputEvent::MotionEvent(MotionEvent::from_ptr(ptr)),
x => panic!("Bad event type received: {}", x),
}
}
#[inline]
pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
match self {
InputEvent::MotionEvent(MotionEvent { ptr }) => *ptr,
InputEvent::KeyEvent(KeyEvent { ptr }) => *ptr,
}
}
#[inline]
pub fn source(&self) -> Source {
let source = unsafe { ffi::AInputEvent_getSource(self.ptr().as_ptr()) };
source.into()
}
#[inline]
pub fn device_id(&self) -> i32 {
unsafe { ffi::AInputEvent_getDeviceId(self.ptr().as_ptr()) }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MetaState(pub u32);
impl MetaState {
#[inline]
pub fn alt_on(self) -> bool {
self.0 & ffi::AMETA_ALT_ON != 0
}
#[inline]
pub fn alt_left_on(self) -> bool {
self.0 & ffi::AMETA_ALT_LEFT_ON != 0
}
#[inline]
pub fn alt_right_on(self) -> bool {
self.0 & ffi::AMETA_ALT_RIGHT_ON != 0
}
#[inline]
pub fn shift_on(self) -> bool {
self.0 & ffi::AMETA_SHIFT_ON != 0
}
#[inline]
pub fn shift_left_on(self) -> bool {
self.0 & ffi::AMETA_SHIFT_LEFT_ON != 0
}
#[inline]
pub fn shift_right_on(self) -> bool {
self.0 & ffi::AMETA_SHIFT_RIGHT_ON != 0
}
#[inline]
pub fn sym_on(self) -> bool {
self.0 & ffi::AMETA_SYM_ON != 0
}
#[inline]
pub fn function_on(self) -> bool {
self.0 & ffi::AMETA_FUNCTION_ON != 0
}
#[inline]
pub fn ctrl_on(self) -> bool {
self.0 & ffi::AMETA_CTRL_ON != 0
}
#[inline]
pub fn ctrl_left_on(self) -> bool {
self.0 & ffi::AMETA_CTRL_LEFT_ON != 0
}
#[inline]
pub fn ctrl_right_on(self) -> bool {
self.0 & ffi::AMETA_CTRL_RIGHT_ON != 0
}
#[inline]
pub fn meta_on(self) -> bool {
self.0 & ffi::AMETA_META_ON != 0
}
#[inline]
pub fn meta_left_on(self) -> bool {
self.0 & ffi::AMETA_META_LEFT_ON != 0
}
#[inline]
pub fn meta_right_on(self) -> bool {
self.0 & ffi::AMETA_META_RIGHT_ON != 0
}
#[inline]
pub fn caps_lock_on(self) -> bool {
self.0 & ffi::AMETA_CAPS_LOCK_ON != 0
}
#[inline]
pub fn num_lock_on(self) -> bool {
self.0 & ffi::AMETA_NUM_LOCK_ON != 0
}
#[inline]
pub fn scroll_lock_on(self) -> bool {
self.0 & ffi::AMETA_SCROLL_LOCK_ON != 0
}
}
#[derive(Clone, Debug)]
pub struct MotionEvent {
ptr: NonNull<ffi::AInputEvent>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum MotionAction {
Down = ffi::AMOTION_EVENT_ACTION_DOWN as i32,
Up = ffi::AMOTION_EVENT_ACTION_UP as i32,
Move = ffi::AMOTION_EVENT_ACTION_MOVE as i32,
Cancel = ffi::AMOTION_EVENT_ACTION_CANCEL as i32,
Outside = ffi::AMOTION_EVENT_ACTION_OUTSIDE as i32,
PointerDown = ffi::AMOTION_EVENT_ACTION_POINTER_DOWN as i32,
PointerUp = ffi::AMOTION_EVENT_ACTION_POINTER_UP as i32,
HoverMove = ffi::AMOTION_EVENT_ACTION_HOVER_MOVE as i32,
Scroll = ffi::AMOTION_EVENT_ACTION_SCROLL as i32,
HoverEnter = ffi::AMOTION_EVENT_ACTION_HOVER_ENTER as i32,
HoverExit = ffi::AMOTION_EVENT_ACTION_HOVER_EXIT as i32,
ButtonPress = ffi::AMOTION_EVENT_ACTION_BUTTON_PRESS as i32,
ButtonRelease = ffi::AMOTION_EVENT_ACTION_BUTTON_RELEASE as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum Axis {
X = ffi::AMOTION_EVENT_AXIS_X as i32,
Y = ffi::AMOTION_EVENT_AXIS_Y as i32,
Pressure = ffi::AMOTION_EVENT_AXIS_PRESSURE as i32,
Size = ffi::AMOTION_EVENT_AXIS_SIZE as i32,
TouchMajor = ffi::AMOTION_EVENT_AXIS_TOUCH_MAJOR as i32,
TouchMinor = ffi::AMOTION_EVENT_AXIS_TOUCH_MINOR as i32,
ToolMajor = ffi::AMOTION_EVENT_AXIS_TOOL_MAJOR as i32,
ToolMinor = ffi::AMOTION_EVENT_AXIS_TOOL_MINOR as i32,
Orientation = ffi::AMOTION_EVENT_AXIS_ORIENTATION as i32,
Vscroll = ffi::AMOTION_EVENT_AXIS_VSCROLL as i32,
Hscroll = ffi::AMOTION_EVENT_AXIS_HSCROLL as i32,
Z = ffi::AMOTION_EVENT_AXIS_Z as i32,
Rx = ffi::AMOTION_EVENT_AXIS_RX as i32,
Ry = ffi::AMOTION_EVENT_AXIS_RY as i32,
Rz = ffi::AMOTION_EVENT_AXIS_RZ as i32,
HatX = ffi::AMOTION_EVENT_AXIS_HAT_X as i32,
HatY = ffi::AMOTION_EVENT_AXIS_HAT_Y as i32,
Ltrigger = ffi::AMOTION_EVENT_AXIS_LTRIGGER as i32,
Rtrigger = ffi::AMOTION_EVENT_AXIS_RTRIGGER as i32,
Throttle = ffi::AMOTION_EVENT_AXIS_THROTTLE as i32,
Rudder = ffi::AMOTION_EVENT_AXIS_RUDDER as i32,
Wheel = ffi::AMOTION_EVENT_AXIS_WHEEL as i32,
Gas = ffi::AMOTION_EVENT_AXIS_GAS as i32,
Brake = ffi::AMOTION_EVENT_AXIS_BRAKE as i32,
Distance = ffi::AMOTION_EVENT_AXIS_DISTANCE as i32,
Tilt = ffi::AMOTION_EVENT_AXIS_TILT as i32,
Scroll = ffi::AMOTION_EVENT_AXIS_SCROLL as i32,
RelativeX = ffi::AMOTION_EVENT_AXIS_RELATIVE_X as i32,
RelativeY = ffi::AMOTION_EVENT_AXIS_RELATIVE_Y as i32,
Generic1 = ffi::AMOTION_EVENT_AXIS_GENERIC_1 as i32,
Generic2 = ffi::AMOTION_EVENT_AXIS_GENERIC_2 as i32,
Generic3 = ffi::AMOTION_EVENT_AXIS_GENERIC_3 as i32,
Generic4 = ffi::AMOTION_EVENT_AXIS_GENERIC_4 as i32,
Generic5 = ffi::AMOTION_EVENT_AXIS_GENERIC_5 as i32,
Generic6 = ffi::AMOTION_EVENT_AXIS_GENERIC_6 as i32,
Generic7 = ffi::AMOTION_EVENT_AXIS_GENERIC_7 as i32,
Generic8 = ffi::AMOTION_EVENT_AXIS_GENERIC_8 as i32,
Generic9 = ffi::AMOTION_EVENT_AXIS_GENERIC_9 as i32,
Generic10 = ffi::AMOTION_EVENT_AXIS_GENERIC_10 as i32,
Generic11 = ffi::AMOTION_EVENT_AXIS_GENERIC_11 as i32,
Generic12 = ffi::AMOTION_EVENT_AXIS_GENERIC_12 as i32,
Generic13 = ffi::AMOTION_EVENT_AXIS_GENERIC_13 as i32,
Generic14 = ffi::AMOTION_EVENT_AXIS_GENERIC_14 as i32,
Generic15 = ffi::AMOTION_EVENT_AXIS_GENERIC_15 as i32,
Generic16 = ffi::AMOTION_EVENT_AXIS_GENERIC_16 as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum ToolType {
Unknown = ffi::AMOTION_EVENT_TOOL_TYPE_UNKNOWN as i32,
Finger = ffi::AMOTION_EVENT_TOOL_TYPE_FINGER as i32,
Stylus = ffi::AMOTION_EVENT_TOOL_TYPE_STYLUS as i32,
Mouse = ffi::AMOTION_EVENT_TOOL_TYPE_MOUSE as i32,
Eraser = ffi::AMOTION_EVENT_TOOL_TYPE_ERASER as i32,
Palm = ffi::AMOTION_EVENT_TOOL_TYPE_PALM as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ButtonState(pub u32);
impl ButtonState {
#[inline]
pub fn primary(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_PRIMARY != 0
}
#[inline]
pub fn secondary(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_SECONDARY != 0
}
#[inline]
pub fn teriary(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_TERTIARY != 0
}
#[inline]
pub fn back(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_BACK != 0
}
#[inline]
pub fn forward(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_FORWARD != 0
}
#[inline]
pub fn stylus_primary(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY != 0
}
#[inline]
pub fn stylus_secondary(self) -> bool {
self.0 & ffi::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY != 0
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct EdgeFlags(pub u32);
impl EdgeFlags {
#[inline]
pub fn top(self) -> bool {
self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_TOP != 0
}
#[inline]
pub fn bottom(self) -> bool {
self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_BOTTOM != 0
}
#[inline]
pub fn left(self) -> bool {
self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_LEFT != 0
}
#[inline]
pub fn right(self) -> bool {
self.0 & ffi::AMOTION_EVENT_EDGE_FLAG_RIGHT != 0
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MotionEventFlags(pub u32);
impl MotionEventFlags {
#[inline]
pub fn window_is_obscured(self) -> bool {
self.0 & ffi::AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED != 0
}
}
impl MotionEvent {
#[inline]
pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
Self { ptr }
}
#[cfg(feature = "api-level-31")]
#[doc(alias = "AMotionEvent_fromJava")]
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
let ptr = unsafe { ffi::AMotionEvent_fromJava(env, key_event) };
Some(InputEventJava(InputEvent::MotionEvent(Self::from_ptr(
NonNull::new(ptr.cast_mut())?,
))))
}
#[inline]
pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
self.ptr
}
#[inline]
pub fn source(&self) -> Source {
let source = unsafe { ffi::AInputEvent_getSource(self.ptr.as_ptr()) };
source.into()
}
#[inline]
pub fn device_id(&self) -> i32 {
unsafe { ffi::AInputEvent_getDeviceId(self.ptr.as_ptr()) }
}
#[inline]
pub fn action(&self) -> MotionAction {
let action = unsafe { ffi::AMotionEvent_getAction(self.ptr.as_ptr()) }
& ffi::AMOTION_EVENT_ACTION_MASK as i32;
action.into()
}
#[inline]
pub fn pointer_index(&self) -> usize {
let action = unsafe { ffi::AMotionEvent_getAction(self.ptr.as_ptr()) as u32 };
let index = (action & ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
>> ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
index as usize
}
#[inline]
pub fn pointer_count(&self) -> usize {
unsafe { ffi::AMotionEvent_getPointerCount(self.ptr.as_ptr()) }
}
#[inline]
pub fn pointers(&self) -> PointersIter<'_> {
PointersIter {
event: self.ptr,
next_index: 0,
count: self.pointer_count(),
_marker: std::marker::PhantomData,
}
}
#[inline]
pub fn pointer_at_index(&self, index: usize) -> Pointer<'_> {
if index >= self.pointer_count() {
panic!("Pointer index {} is out of bounds", index);
}
Pointer {
event: self.ptr,
index,
_marker: std::marker::PhantomData,
}
}
#[inline]
pub fn history_size(&self) -> usize {
unsafe { ffi::AMotionEvent_getHistorySize(self.ptr.as_ptr()) }
}
#[inline]
pub fn history(&self) -> HistoricalMotionEventsIter<'_> {
HistoricalMotionEventsIter {
event: self.ptr,
next_history_index: 0,
history_size: self.history_size(),
_marker: std::marker::PhantomData,
}
}
#[inline]
pub fn meta_state(&self) -> MetaState {
unsafe { MetaState(ffi::AMotionEvent_getMetaState(self.ptr.as_ptr()) as u32) }
}
#[inline]
pub fn button_state(&self) -> ButtonState {
unsafe { ButtonState(ffi::AMotionEvent_getButtonState(self.ptr.as_ptr()) as u32) }
}
#[inline]
pub fn down_time(&self) -> i64 {
unsafe { ffi::AMotionEvent_getDownTime(self.ptr.as_ptr()) }
}
#[inline]
pub fn edge_flags(&self) -> EdgeFlags {
unsafe { EdgeFlags(ffi::AMotionEvent_getEdgeFlags(self.ptr.as_ptr()) as u32) }
}
#[inline]
pub fn event_time(&self) -> i64 {
unsafe { ffi::AMotionEvent_getEventTime(self.ptr.as_ptr()) }
}
#[inline]
pub fn flags(&self) -> MotionEventFlags {
unsafe { MotionEventFlags(ffi::AMotionEvent_getFlags(self.ptr.as_ptr()) as u32) }
}
#[inline]
pub fn x_offset(&self) -> f32 {
unsafe { ffi::AMotionEvent_getXOffset(self.ptr.as_ptr()) }
}
#[inline]
pub fn y_offset(&self) -> f32 {
unsafe { ffi::AMotionEvent_getYOffset(self.ptr.as_ptr()) }
}
#[inline]
pub fn x_precision(&self) -> f32 {
unsafe { ffi::AMotionEvent_getXPrecision(self.ptr.as_ptr()) }
}
#[inline]
pub fn y_precision(&self) -> f32 {
unsafe { ffi::AMotionEvent_getYPrecision(self.ptr.as_ptr()) }
}
}
#[derive(Debug)]
pub struct Pointer<'a> {
event: NonNull<ffi::AInputEvent>,
index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> Pointer<'a> {
#[inline]
pub fn pointer_index(&self) -> usize {
self.index
}
#[inline]
pub fn pointer_id(&self) -> i32 {
unsafe { ffi::AMotionEvent_getPointerId(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn axis_value(&self, axis: Axis) -> f32 {
unsafe { ffi::AMotionEvent_getAxisValue(self.event.as_ptr(), axis.into(), self.index) }
}
#[inline]
pub fn orientation(&self) -> f32 {
unsafe { ffi::AMotionEvent_getOrientation(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn pressure(&self) -> f32 {
unsafe { ffi::AMotionEvent_getPressure(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn raw_x(&self) -> f32 {
unsafe { ffi::AMotionEvent_getRawX(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn raw_y(&self) -> f32 {
unsafe { ffi::AMotionEvent_getRawY(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn x(&self) -> f32 {
unsafe { ffi::AMotionEvent_getX(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn y(&self) -> f32 {
unsafe { ffi::AMotionEvent_getY(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn size(&self) -> f32 {
unsafe { ffi::AMotionEvent_getSize(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn tool_major(&self) -> f32 {
unsafe { ffi::AMotionEvent_getToolMajor(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn tool_minor(&self) -> f32 {
unsafe { ffi::AMotionEvent_getToolMinor(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn touch_major(&self) -> f32 {
unsafe { ffi::AMotionEvent_getTouchMajor(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn touch_minor(&self) -> f32 {
unsafe { ffi::AMotionEvent_getTouchMinor(self.event.as_ptr(), self.index) }
}
#[inline]
pub fn tool_type(&self) -> ToolType {
let tool_type = unsafe { ffi::AMotionEvent_getToolType(self.event.as_ptr(), self.index) };
tool_type.into()
}
}
#[derive(Debug)]
pub struct PointersIter<'a> {
event: NonNull<ffi::AInputEvent>,
next_index: usize,
count: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> Iterator for PointersIter<'a> {
type Item = Pointer<'a>;
fn next(&mut self) -> Option<Pointer<'a>> {
if self.next_index < self.count {
let ptr = Pointer {
event: self.event,
index: self.next_index,
_marker: std::marker::PhantomData,
};
self.next_index += 1;
Some(ptr)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.count - self.next_index;
(size, Some(size))
}
}
impl<'a> ExactSizeIterator for PointersIter<'a> {
fn len(&self) -> usize {
self.count - self.next_index
}
}
#[derive(Debug)]
pub struct HistoricalMotionEvent<'a> {
event: NonNull<ffi::AInputEvent>,
history_index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> HistoricalMotionEvent<'a> {
#[inline]
pub fn history_index(&self) -> usize {
self.history_index
}
#[inline]
pub fn event_time(&self) -> i64 {
unsafe { ffi::AMotionEvent_getHistoricalEventTime(self.event.as_ptr(), self.history_index) }
}
#[inline]
pub fn pointers(&self) -> HistoricalPointersIter<'a> {
HistoricalPointersIter {
event: self.event,
history_index: self.history_index,
next_pointer_index: 0,
pointer_count: unsafe { ffi::AMotionEvent_getPointerCount(self.event.as_ptr()) },
_marker: std::marker::PhantomData,
}
}
}
#[derive(Debug)]
pub struct HistoricalMotionEventsIter<'a> {
event: NonNull<ffi::AInputEvent>,
next_history_index: usize,
history_size: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> Iterator for HistoricalMotionEventsIter<'a> {
type Item = HistoricalMotionEvent<'a>;
fn next(&mut self) -> Option<HistoricalMotionEvent<'a>> {
if self.next_history_index < self.history_size {
let res = HistoricalMotionEvent {
event: self.event,
history_index: self.next_history_index,
_marker: std::marker::PhantomData,
};
self.next_history_index += 1;
Some(res)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.history_size - self.next_history_index;
(size, Some(size))
}
}
impl ExactSizeIterator for HistoricalMotionEventsIter<'_> {
fn len(&self) -> usize {
self.history_size - self.next_history_index
}
}
impl<'a> DoubleEndedIterator for HistoricalMotionEventsIter<'a> {
fn next_back(&mut self) -> Option<HistoricalMotionEvent<'a>> {
if self.next_history_index < self.history_size {
self.history_size -= 1;
Some(HistoricalMotionEvent {
event: self.event,
history_index: self.history_size,
_marker: std::marker::PhantomData,
})
} else {
None
}
}
}
#[derive(Debug)]
pub struct HistoricalPointer<'a> {
event: NonNull<ffi::AInputEvent>,
pointer_index: usize,
history_index: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> HistoricalPointer<'a> {
#[inline]
pub fn pointer_index(&self) -> usize {
self.pointer_index
}
#[inline]
pub fn pointer_id(&self) -> i32 {
unsafe { ffi::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 {
ffi::AMotionEvent_getHistoricalAxisValue(
self.event.as_ptr(),
axis.into(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn orientation(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalOrientation(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn pressure(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalPressure(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn raw_x(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalRawX(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn raw_y(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalRawY(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn x(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalX(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn y(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalY(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn size(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalSize(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn tool_major(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalToolMajor(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn tool_minor(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalToolMinor(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn touch_major(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalTouchMajor(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
#[inline]
pub fn touch_minor(&self) -> f32 {
unsafe {
ffi::AMotionEvent_getHistoricalTouchMinor(
self.event.as_ptr(),
self.pointer_index,
self.history_index,
)
}
}
}
#[derive(Debug)]
pub struct HistoricalPointersIter<'a> {
event: NonNull<ffi::AInputEvent>,
history_index: usize,
next_pointer_index: usize,
pointer_count: usize,
_marker: std::marker::PhantomData<&'a MotionEvent>,
}
impl<'a> Iterator for HistoricalPointersIter<'a> {
type Item = HistoricalPointer<'a>;
fn next(&mut self) -> Option<HistoricalPointer<'a>> {
if self.next_pointer_index < self.pointer_count {
let ptr = HistoricalPointer {
event: self.event,
history_index: self.history_index,
pointer_index: self.next_pointer_index,
_marker: std::marker::PhantomData,
};
self.next_pointer_index += 1;
Some(ptr)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.pointer_count - self.next_pointer_index;
(size, Some(size))
}
}
impl ExactSizeIterator for HistoricalPointersIter<'_> {
fn len(&self) -> usize {
self.pointer_count - self.next_pointer_index
}
}
#[derive(Debug)]
pub struct KeyEvent {
ptr: NonNull<ffi::AInputEvent>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum KeyAction {
Down = ffi::AKEY_EVENT_ACTION_DOWN as i32,
Up = ffi::AKEY_EVENT_ACTION_UP as i32,
Multiple = ffi::AKEY_EVENT_ACTION_MULTIPLE as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(i32)]
#[non_exhaustive]
pub enum Keycode {
Unknown = ffi::AKEYCODE_UNKNOWN as i32,
SoftLeft = ffi::AKEYCODE_SOFT_LEFT as i32,
SoftRight = ffi::AKEYCODE_SOFT_RIGHT as i32,
Home = ffi::AKEYCODE_HOME as i32,
Back = ffi::AKEYCODE_BACK as i32,
Call = ffi::AKEYCODE_CALL as i32,
Endcall = ffi::AKEYCODE_ENDCALL as i32,
Keycode0 = ffi::AKEYCODE_0 as i32,
Keycode1 = ffi::AKEYCODE_1 as i32,
Keycode2 = ffi::AKEYCODE_2 as i32,
Keycode3 = ffi::AKEYCODE_3 as i32,
Keycode4 = ffi::AKEYCODE_4 as i32,
Keycode5 = ffi::AKEYCODE_5 as i32,
Keycode6 = ffi::AKEYCODE_6 as i32,
Keycode7 = ffi::AKEYCODE_7 as i32,
Keycode8 = ffi::AKEYCODE_8 as i32,
Keycode9 = ffi::AKEYCODE_9 as i32,
Star = ffi::AKEYCODE_STAR as i32,
Pound = ffi::AKEYCODE_POUND as i32,
DpadUp = ffi::AKEYCODE_DPAD_UP as i32,
DpadDown = ffi::AKEYCODE_DPAD_DOWN as i32,
DpadLeft = ffi::AKEYCODE_DPAD_LEFT as i32,
DpadRight = ffi::AKEYCODE_DPAD_RIGHT as i32,
DpadCenter = ffi::AKEYCODE_DPAD_CENTER as i32,
VolumeUp = ffi::AKEYCODE_VOLUME_UP as i32,
VolumeDown = ffi::AKEYCODE_VOLUME_DOWN as i32,
Power = ffi::AKEYCODE_POWER as i32,
Camera = ffi::AKEYCODE_CAMERA as i32,
Clear = ffi::AKEYCODE_CLEAR as i32,
A = ffi::AKEYCODE_A as i32,
B = ffi::AKEYCODE_B as i32,
C = ffi::AKEYCODE_C as i32,
D = ffi::AKEYCODE_D as i32,
E = ffi::AKEYCODE_E as i32,
F = ffi::AKEYCODE_F as i32,
G = ffi::AKEYCODE_G as i32,
H = ffi::AKEYCODE_H as i32,
I = ffi::AKEYCODE_I as i32,
J = ffi::AKEYCODE_J as i32,
K = ffi::AKEYCODE_K as i32,
L = ffi::AKEYCODE_L as i32,
M = ffi::AKEYCODE_M as i32,
N = ffi::AKEYCODE_N as i32,
O = ffi::AKEYCODE_O as i32,
P = ffi::AKEYCODE_P as i32,
Q = ffi::AKEYCODE_Q as i32,
R = ffi::AKEYCODE_R as i32,
S = ffi::AKEYCODE_S as i32,
T = ffi::AKEYCODE_T as i32,
U = ffi::AKEYCODE_U as i32,
V = ffi::AKEYCODE_V as i32,
W = ffi::AKEYCODE_W as i32,
X = ffi::AKEYCODE_X as i32,
Y = ffi::AKEYCODE_Y as i32,
Z = ffi::AKEYCODE_Z as i32,
Comma = ffi::AKEYCODE_COMMA as i32,
Period = ffi::AKEYCODE_PERIOD as i32,
AltLeft = ffi::AKEYCODE_ALT_LEFT as i32,
AltRight = ffi::AKEYCODE_ALT_RIGHT as i32,
ShiftLeft = ffi::AKEYCODE_SHIFT_LEFT as i32,
ShiftRight = ffi::AKEYCODE_SHIFT_RIGHT as i32,
Tab = ffi::AKEYCODE_TAB as i32,
Space = ffi::AKEYCODE_SPACE as i32,
Sym = ffi::AKEYCODE_SYM as i32,
Explorer = ffi::AKEYCODE_EXPLORER as i32,
Envelope = ffi::AKEYCODE_ENVELOPE as i32,
Enter = ffi::AKEYCODE_ENTER as i32,
Del = ffi::AKEYCODE_DEL as i32,
Grave = ffi::AKEYCODE_GRAVE as i32,
Minus = ffi::AKEYCODE_MINUS as i32,
Equals = ffi::AKEYCODE_EQUALS as i32,
LeftBracket = ffi::AKEYCODE_LEFT_BRACKET as i32,
RightBracket = ffi::AKEYCODE_RIGHT_BRACKET as i32,
Backslash = ffi::AKEYCODE_BACKSLASH as i32,
Semicolon = ffi::AKEYCODE_SEMICOLON as i32,
Apostrophe = ffi::AKEYCODE_APOSTROPHE as i32,
Slash = ffi::AKEYCODE_SLASH as i32,
At = ffi::AKEYCODE_AT as i32,
Num = ffi::AKEYCODE_NUM as i32,
Headsethook = ffi::AKEYCODE_HEADSETHOOK as i32,
Focus = ffi::AKEYCODE_FOCUS as i32,
Plus = ffi::AKEYCODE_PLUS as i32,
Menu = ffi::AKEYCODE_MENU as i32,
Notification = ffi::AKEYCODE_NOTIFICATION as i32,
Search = ffi::AKEYCODE_SEARCH as i32,
MediaPlayPause = ffi::AKEYCODE_MEDIA_PLAY_PAUSE as i32,
MediaStop = ffi::AKEYCODE_MEDIA_STOP as i32,
MediaNext = ffi::AKEYCODE_MEDIA_NEXT as i32,
MediaPrevious = ffi::AKEYCODE_MEDIA_PREVIOUS as i32,
MediaRewind = ffi::AKEYCODE_MEDIA_REWIND as i32,
MediaFastForward = ffi::AKEYCODE_MEDIA_FAST_FORWARD as i32,
Mute = ffi::AKEYCODE_MUTE as i32,
PageUp = ffi::AKEYCODE_PAGE_UP as i32,
PageDown = ffi::AKEYCODE_PAGE_DOWN as i32,
Pictsymbols = ffi::AKEYCODE_PICTSYMBOLS as i32,
SwitchCharset = ffi::AKEYCODE_SWITCH_CHARSET as i32,
ButtonA = ffi::AKEYCODE_BUTTON_A as i32,
ButtonB = ffi::AKEYCODE_BUTTON_B as i32,
ButtonC = ffi::AKEYCODE_BUTTON_C as i32,
ButtonX = ffi::AKEYCODE_BUTTON_X as i32,
ButtonY = ffi::AKEYCODE_BUTTON_Y as i32,
ButtonZ = ffi::AKEYCODE_BUTTON_Z as i32,
ButtonL1 = ffi::AKEYCODE_BUTTON_L1 as i32,
ButtonR1 = ffi::AKEYCODE_BUTTON_R1 as i32,
ButtonL2 = ffi::AKEYCODE_BUTTON_L2 as i32,
ButtonR2 = ffi::AKEYCODE_BUTTON_R2 as i32,
ButtonThumbl = ffi::AKEYCODE_BUTTON_THUMBL as i32,
ButtonThumbr = ffi::AKEYCODE_BUTTON_THUMBR as i32,
ButtonStart = ffi::AKEYCODE_BUTTON_START as i32,
ButtonSelect = ffi::AKEYCODE_BUTTON_SELECT as i32,
ButtonMode = ffi::AKEYCODE_BUTTON_MODE as i32,
Escape = ffi::AKEYCODE_ESCAPE as i32,
ForwardDel = ffi::AKEYCODE_FORWARD_DEL as i32,
CtrlLeft = ffi::AKEYCODE_CTRL_LEFT as i32,
CtrlRight = ffi::AKEYCODE_CTRL_RIGHT as i32,
CapsLock = ffi::AKEYCODE_CAPS_LOCK as i32,
ScrollLock = ffi::AKEYCODE_SCROLL_LOCK as i32,
MetaLeft = ffi::AKEYCODE_META_LEFT as i32,
MetaRight = ffi::AKEYCODE_META_RIGHT as i32,
Function = ffi::AKEYCODE_FUNCTION as i32,
Sysrq = ffi::AKEYCODE_SYSRQ as i32,
Break = ffi::AKEYCODE_BREAK as i32,
MoveHome = ffi::AKEYCODE_MOVE_HOME as i32,
MoveEnd = ffi::AKEYCODE_MOVE_END as i32,
Insert = ffi::AKEYCODE_INSERT as i32,
Forward = ffi::AKEYCODE_FORWARD as i32,
MediaPlay = ffi::AKEYCODE_MEDIA_PLAY as i32,
MediaPause = ffi::AKEYCODE_MEDIA_PAUSE as i32,
MediaClose = ffi::AKEYCODE_MEDIA_CLOSE as i32,
MediaEject = ffi::AKEYCODE_MEDIA_EJECT as i32,
MediaRecord = ffi::AKEYCODE_MEDIA_RECORD as i32,
F1 = ffi::AKEYCODE_F1 as i32,
F2 = ffi::AKEYCODE_F2 as i32,
F3 = ffi::AKEYCODE_F3 as i32,
F4 = ffi::AKEYCODE_F4 as i32,
F5 = ffi::AKEYCODE_F5 as i32,
F6 = ffi::AKEYCODE_F6 as i32,
F7 = ffi::AKEYCODE_F7 as i32,
F8 = ffi::AKEYCODE_F8 as i32,
F9 = ffi::AKEYCODE_F9 as i32,
F10 = ffi::AKEYCODE_F10 as i32,
F11 = ffi::AKEYCODE_F11 as i32,
F12 = ffi::AKEYCODE_F12 as i32,
NumLock = ffi::AKEYCODE_NUM_LOCK as i32,
Numpad0 = ffi::AKEYCODE_NUMPAD_0 as i32,
Numpad1 = ffi::AKEYCODE_NUMPAD_1 as i32,
Numpad2 = ffi::AKEYCODE_NUMPAD_2 as i32,
Numpad3 = ffi::AKEYCODE_NUMPAD_3 as i32,
Numpad4 = ffi::AKEYCODE_NUMPAD_4 as i32,
Numpad5 = ffi::AKEYCODE_NUMPAD_5 as i32,
Numpad6 = ffi::AKEYCODE_NUMPAD_6 as i32,
Numpad7 = ffi::AKEYCODE_NUMPAD_7 as i32,
Numpad8 = ffi::AKEYCODE_NUMPAD_8 as i32,
Numpad9 = ffi::AKEYCODE_NUMPAD_9 as i32,
NumpadDivide = ffi::AKEYCODE_NUMPAD_DIVIDE as i32,
NumpadMultiply = ffi::AKEYCODE_NUMPAD_MULTIPLY as i32,
NumpadSubtract = ffi::AKEYCODE_NUMPAD_SUBTRACT as i32,
NumpadAdd = ffi::AKEYCODE_NUMPAD_ADD as i32,
NumpadDot = ffi::AKEYCODE_NUMPAD_DOT as i32,
NumpadComma = ffi::AKEYCODE_NUMPAD_COMMA as i32,
NumpadEnter = ffi::AKEYCODE_NUMPAD_ENTER as i32,
NumpadEquals = ffi::AKEYCODE_NUMPAD_EQUALS as i32,
NumpadLeftParen = ffi::AKEYCODE_NUMPAD_LEFT_PAREN as i32,
NumpadRightParen = ffi::AKEYCODE_NUMPAD_RIGHT_PAREN as i32,
VolumeMute = ffi::AKEYCODE_VOLUME_MUTE as i32,
Info = ffi::AKEYCODE_INFO as i32,
ChannelUp = ffi::AKEYCODE_CHANNEL_UP as i32,
ChannelDown = ffi::AKEYCODE_CHANNEL_DOWN as i32,
ZoomIn = ffi::AKEYCODE_ZOOM_IN as i32,
ZoomOut = ffi::AKEYCODE_ZOOM_OUT as i32,
Tv = ffi::AKEYCODE_TV as i32,
Window = ffi::AKEYCODE_WINDOW as i32,
Guide = ffi::AKEYCODE_GUIDE as i32,
Dvr = ffi::AKEYCODE_DVR as i32,
Bookmark = ffi::AKEYCODE_BOOKMARK as i32,
Captions = ffi::AKEYCODE_CAPTIONS as i32,
Settings = ffi::AKEYCODE_SETTINGS as i32,
TvPower = ffi::AKEYCODE_TV_POWER as i32,
TvInput = ffi::AKEYCODE_TV_INPUT as i32,
StbPower = ffi::AKEYCODE_STB_POWER as i32,
StbInput = ffi::AKEYCODE_STB_INPUT as i32,
AvrPower = ffi::AKEYCODE_AVR_POWER as i32,
AvrInput = ffi::AKEYCODE_AVR_INPUT as i32,
ProgRed = ffi::AKEYCODE_PROG_RED as i32,
ProgGreen = ffi::AKEYCODE_PROG_GREEN as i32,
ProgYellow = ffi::AKEYCODE_PROG_YELLOW as i32,
ProgBlue = ffi::AKEYCODE_PROG_BLUE as i32,
AppSwitch = ffi::AKEYCODE_APP_SWITCH as i32,
Button1 = ffi::AKEYCODE_BUTTON_1 as i32,
Button2 = ffi::AKEYCODE_BUTTON_2 as i32,
Button3 = ffi::AKEYCODE_BUTTON_3 as i32,
Button4 = ffi::AKEYCODE_BUTTON_4 as i32,
Button5 = ffi::AKEYCODE_BUTTON_5 as i32,
Button6 = ffi::AKEYCODE_BUTTON_6 as i32,
Button7 = ffi::AKEYCODE_BUTTON_7 as i32,
Button8 = ffi::AKEYCODE_BUTTON_8 as i32,
Button9 = ffi::AKEYCODE_BUTTON_9 as i32,
Button10 = ffi::AKEYCODE_BUTTON_10 as i32,
Button11 = ffi::AKEYCODE_BUTTON_11 as i32,
Button12 = ffi::AKEYCODE_BUTTON_12 as i32,
Button13 = ffi::AKEYCODE_BUTTON_13 as i32,
Button14 = ffi::AKEYCODE_BUTTON_14 as i32,
Button15 = ffi::AKEYCODE_BUTTON_15 as i32,
Button16 = ffi::AKEYCODE_BUTTON_16 as i32,
LanguageSwitch = ffi::AKEYCODE_LANGUAGE_SWITCH as i32,
MannerMode = ffi::AKEYCODE_MANNER_MODE as i32,
Keycode3dMode = ffi::AKEYCODE_3D_MODE as i32,
Contacts = ffi::AKEYCODE_CONTACTS as i32,
Calendar = ffi::AKEYCODE_CALENDAR as i32,
Music = ffi::AKEYCODE_MUSIC as i32,
Calculator = ffi::AKEYCODE_CALCULATOR as i32,
ZenkakuHankaku = ffi::AKEYCODE_ZENKAKU_HANKAKU as i32,
Eisu = ffi::AKEYCODE_EISU as i32,
Muhenkan = ffi::AKEYCODE_MUHENKAN as i32,
Henkan = ffi::AKEYCODE_HENKAN as i32,
KatakanaHiragana = ffi::AKEYCODE_KATAKANA_HIRAGANA as i32,
Yen = ffi::AKEYCODE_YEN as i32,
Ro = ffi::AKEYCODE_RO as i32,
Kana = ffi::AKEYCODE_KANA as i32,
Assist = ffi::AKEYCODE_ASSIST as i32,
BrightnessDown = ffi::AKEYCODE_BRIGHTNESS_DOWN as i32,
BrightnessUp = ffi::AKEYCODE_BRIGHTNESS_UP as i32,
MediaAudioTrack = ffi::AKEYCODE_MEDIA_AUDIO_TRACK as i32,
Sleep = ffi::AKEYCODE_SLEEP as i32,
Wakeup = ffi::AKEYCODE_WAKEUP as i32,
Pairing = ffi::AKEYCODE_PAIRING as i32,
MediaTopMenu = ffi::AKEYCODE_MEDIA_TOP_MENU as i32,
Keycode11 = ffi::AKEYCODE_11 as i32,
Keycode12 = ffi::AKEYCODE_12 as i32,
LastChannel = ffi::AKEYCODE_LAST_CHANNEL as i32,
TvDataService = ffi::AKEYCODE_TV_DATA_SERVICE as i32,
VoiceAssist = ffi::AKEYCODE_VOICE_ASSIST as i32,
TvRadioService = ffi::AKEYCODE_TV_RADIO_SERVICE as i32,
TvTeletext = ffi::AKEYCODE_TV_TELETEXT as i32,
TvNumberEntry = ffi::AKEYCODE_TV_NUMBER_ENTRY as i32,
TvTerrestrialAnalog = ffi::AKEYCODE_TV_TERRESTRIAL_ANALOG as i32,
TvTerrestrialDigital = ffi::AKEYCODE_TV_TERRESTRIAL_DIGITAL as i32,
TvSatellite = ffi::AKEYCODE_TV_SATELLITE as i32,
TvSatelliteBs = ffi::AKEYCODE_TV_SATELLITE_BS as i32,
TvSatelliteCs = ffi::AKEYCODE_TV_SATELLITE_CS as i32,
TvSatelliteService = ffi::AKEYCODE_TV_SATELLITE_SERVICE as i32,
TvNetwork = ffi::AKEYCODE_TV_NETWORK as i32,
TvAntennaCable = ffi::AKEYCODE_TV_ANTENNA_CABLE as i32,
TvInputHdmi1 = ffi::AKEYCODE_TV_INPUT_HDMI_1 as i32,
TvInputHdmi2 = ffi::AKEYCODE_TV_INPUT_HDMI_2 as i32,
TvInputHdmi3 = ffi::AKEYCODE_TV_INPUT_HDMI_3 as i32,
TvInputHdmi4 = ffi::AKEYCODE_TV_INPUT_HDMI_4 as i32,
TvInputComposite1 = ffi::AKEYCODE_TV_INPUT_COMPOSITE_1 as i32,
TvInputComposite2 = ffi::AKEYCODE_TV_INPUT_COMPOSITE_2 as i32,
TvInputComponent1 = ffi::AKEYCODE_TV_INPUT_COMPONENT_1 as i32,
TvInputComponent2 = ffi::AKEYCODE_TV_INPUT_COMPONENT_2 as i32,
TvInputVga1 = ffi::AKEYCODE_TV_INPUT_VGA_1 as i32,
TvAudioDescription = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION as i32,
TvAudioDescriptionMixUp = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP as i32,
TvAudioDescriptionMixDown = ffi::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN as i32,
TvZoomMode = ffi::AKEYCODE_TV_ZOOM_MODE as i32,
TvContentsMenu = ffi::AKEYCODE_TV_CONTENTS_MENU as i32,
TvMediaContextMenu = ffi::AKEYCODE_TV_MEDIA_CONTEXT_MENU as i32,
TvTimerProgramming = ffi::AKEYCODE_TV_TIMER_PROGRAMMING as i32,
Help = ffi::AKEYCODE_HELP as i32,
NavigatePrevious = ffi::AKEYCODE_NAVIGATE_PREVIOUS as i32,
NavigateNext = ffi::AKEYCODE_NAVIGATE_NEXT as i32,
NavigateIn = ffi::AKEYCODE_NAVIGATE_IN as i32,
NavigateOut = ffi::AKEYCODE_NAVIGATE_OUT as i32,
StemPrimary = ffi::AKEYCODE_STEM_PRIMARY as i32,
Stem1 = ffi::AKEYCODE_STEM_1 as i32,
Stem2 = ffi::AKEYCODE_STEM_2 as i32,
Stem3 = ffi::AKEYCODE_STEM_3 as i32,
DpadUpLeft = ffi::AKEYCODE_DPAD_UP_LEFT as i32,
DpadDownLeft = ffi::AKEYCODE_DPAD_DOWN_LEFT as i32,
DpadUpRight = ffi::AKEYCODE_DPAD_UP_RIGHT as i32,
DpadDownRight = ffi::AKEYCODE_DPAD_DOWN_RIGHT as i32,
MediaSkipForward = ffi::AKEYCODE_MEDIA_SKIP_FORWARD as i32,
MediaSkipBackward = ffi::AKEYCODE_MEDIA_SKIP_BACKWARD as i32,
MediaStepForward = ffi::AKEYCODE_MEDIA_STEP_FORWARD as i32,
MediaStepBackward = ffi::AKEYCODE_MEDIA_STEP_BACKWARD as i32,
SoftSleep = ffi::AKEYCODE_SOFT_SLEEP as i32,
Cut = ffi::AKEYCODE_CUT as i32,
Copy = ffi::AKEYCODE_COPY as i32,
Paste = ffi::AKEYCODE_PASTE as i32,
SystemNavigationUp = ffi::AKEYCODE_SYSTEM_NAVIGATION_UP as i32,
SystemNavigationDown = ffi::AKEYCODE_SYSTEM_NAVIGATION_DOWN as i32,
SystemNavigationLeft = ffi::AKEYCODE_SYSTEM_NAVIGATION_LEFT as i32,
SystemNavigationRight = ffi::AKEYCODE_SYSTEM_NAVIGATION_RIGHT as i32,
AllApps = ffi::AKEYCODE_ALL_APPS as i32,
Refresh = ffi::AKEYCODE_REFRESH as i32,
ThumbsUp = ffi::AKEYCODE_THUMBS_UP as i32,
ThumbsDown = ffi::AKEYCODE_THUMBS_DOWN as i32,
ProfileSwitch = ffi::AKEYCODE_PROFILE_SWITCH as i32,
#[doc(hidden)]
#[num_enum(catch_all)]
__Unknown(i32),
}
impl KeyEvent {
#[inline]
pub unsafe fn from_ptr(ptr: NonNull<ffi::AInputEvent>) -> Self {
Self { ptr }
}
#[cfg(feature = "api-level-31")]
#[doc(alias = "AKeyEvent_fromJava")]
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
let ptr = unsafe { ffi::AKeyEvent_fromJava(env, key_event) };
Some(InputEventJava(InputEvent::KeyEvent(Self::from_ptr(
NonNull::new(ptr.cast_mut())?,
))))
}
#[inline]
pub fn ptr(&self) -> NonNull<ffi::AInputEvent> {
self.ptr
}
#[inline]
pub fn action(&self) -> KeyAction {
let action = unsafe { ffi::AKeyEvent_getAction(self.ptr.as_ptr()) };
action.into()
}
#[inline]
pub fn source(&self) -> Source {
let source = unsafe { ffi::AInputEvent_getSource(self.ptr.as_ptr()) };
source.into()
}
#[inline]
pub fn device_id(&self) -> i32 {
unsafe { ffi::AInputEvent_getDeviceId(self.ptr.as_ptr()) }
}
#[inline]
pub fn down_time(&self) -> i64 {
unsafe { ffi::AKeyEvent_getDownTime(self.ptr.as_ptr()) }
}
#[inline]
pub fn event_time(&self) -> i64 {
unsafe { ffi::AKeyEvent_getEventTime(self.ptr.as_ptr()) }
}
#[inline]
pub fn key_code(&self) -> Keycode {
let keycode = unsafe { ffi::AKeyEvent_getKeyCode(self.ptr.as_ptr()) };
keycode.into()
}
#[inline]
pub fn repeat_count(&self) -> i32 {
unsafe { ffi::AKeyEvent_getRepeatCount(self.ptr.as_ptr()) }
}
#[inline]
pub fn scan_code(&self) -> i32 {
unsafe { ffi::AKeyEvent_getScanCode(self.ptr.as_ptr()) }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct KeyEventFlags(pub u32);
impl KeyEventFlags {
#[inline]
pub fn cancelled(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_CANCELED != 0
}
#[inline]
pub fn cancelled_long_press(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_CANCELED_LONG_PRESS != 0
}
#[inline]
pub fn editor_action(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_EDITOR_ACTION != 0
}
#[inline]
pub fn fallback(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_FALLBACK != 0
}
#[inline]
pub fn from_system(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_FROM_SYSTEM != 0
}
#[inline]
pub fn keep_touch_mode(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_KEEP_TOUCH_MODE != 0
}
#[inline]
pub fn long_press(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_LONG_PRESS != 0
}
#[inline]
pub fn soft_keyboard(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_SOFT_KEYBOARD != 0
}
#[inline]
pub fn tracking(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_TRACKING != 0
}
#[inline]
pub fn virtual_hard_key(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY != 0
}
#[inline]
pub fn woke_here(&self) -> bool {
self.0 & ffi::AKEY_EVENT_FLAG_WOKE_HERE != 0
}
}
impl KeyEvent {
#[inline]
pub fn flags(&self) -> KeyEventFlags {
unsafe { KeyEventFlags(ffi::AKeyEvent_getFlags(self.ptr.as_ptr()) as u32) }
}
#[inline]
pub fn meta_state(&self) -> MetaState {
unsafe { MetaState(ffi::AKeyEvent_getMetaState(self.ptr.as_ptr()) as u32) }
}
}