From cae771b8f79ad65eaf97d0e6f522dcfbdbfccea6 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 25 Jun 2025 10:10:16 +0200 Subject: [PATCH] Revert "input: Replace open-coded types with `ndk::event` definitions (#163)" This reverts commit 51d05d48c8f59a7e9a1d41c1577870842206ce32 for backwards compatibility with the existing `0.6` releases. For now, it's creating a lot of busy work having to always make this revert in order to test various topic branch changes with winit 0.30. Lets save this breaking change until we have more reasons to break semver compatibility (in itself this doesn't fix or enable any features, so we can live without it for now). --- android-activity/CHANGELOG.md | 13 +- android-activity/Cargo.toml | 1 - android-activity/src/game_activity/input.rs | 24 +- android-activity/src/game_activity/mod.rs | 6 +- android-activity/src/input.rs | 837 +++++++++++++++++- android-activity/src/input/sdk.rs | 6 +- android-activity/src/native_activity/input.rs | 70 +- 7 files changed, 904 insertions(+), 53 deletions(-) diff --git a/android-activity/CHANGELOG.md b/android-activity/CHANGELOG.md index be0c1ac0..e0c31706 100644 --- a/android-activity/CHANGELOG.md +++ b/android-activity/CHANGELOG.md @@ -6,19 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed -- input: Replaced custom types with their `ndk` crate equivalent. - > [!NOTE] - > These types existed because the `ndk` crate didn't provide them in an extensible way. Now that they have the `#[non_exhaustive]` flag and contain a `__Unknown(T)` variant to provide lossless conversions, and not to mention use an ABI type that matches how it is being used by most functions (when the original constants were defined in a "typeless" way), the `ndk` types are used and reexported once again. +### Added - > [!IMPORTANT] - > **Relevant breaking changes**: - > - `repr()` types for some `enum`s have changed to match the ABI type that is used by most functions that are returning or consuming this wrapper type. - > - `Source::is_xxx_class()` functions are replaced by querying `Source::class()` and comparing against variants from the returned `SourceClass` `bitflags` enum. - > - `SourceFlags::TRACKBALL` (from `Source::is_trackball_class()`) is named `SourceClass::NAVIGATION` in the `ndk`. +- The `ndk` and `ndk-sys` crates are now re-exported under `android_activity::ndk` and `android_activity::ndk_sys` ([#194](https://github.com/rust-mobile/android-activity/pull/194)) +### Changed - rust-version bumped to 1.73.0 ([#193](https://github.com/rust-mobile/android-activity/pull/193)) -- The `ndk` and `ndk-sys` crates are now re-exported under `android_activity::ndk` and `android_activity::ndk_sys` ([#194](https://github.com/rust-mobile/android-activity/pull/194)) - GameActivity updated to 4.0.0 (requires the corresponding 4.0.0 `.aar` release from Google) ([#191](https://github.com/rust-mobile/android-activity/pull/191)) ## [0.6.0] - 2024-04-26 diff --git a/android-activity/Cargo.toml b/android-activity/Cargo.toml index 276d1bdc..ec463580 100644 --- a/android-activity/Cargo.toml +++ b/android-activity/Cargo.toml @@ -32,7 +32,6 @@ default = [] game-activity = [] native-activity = [] api-level-30 = ["ndk/api-level-30"] -api-level-33 = ["api-level-30", "ndk/api-level-33"] [dependencies] log = "0.4" diff --git a/android-activity/src/game_activity/input.rs b/android-activity/src/game_activity/input.rs index f8fac2b3..66b94fe9 100644 --- a/android-activity/src/game_activity/input.rs +++ b/android-activity/src/game_activity/input.rs @@ -13,12 +13,10 @@ // The `Class` was also bound differently to `android-ndk-rs` considering how the class is defined // by masking bits from the `Source`. -use ndk::event::ButtonState; - use crate::activity_impl::ffi::{GameActivityKeyEvent, GameActivityMotionEvent}; use crate::input::{ - Axis, Button, EdgeFlags, KeyAction, KeyEventFlags, Keycode, MetaState, MotionAction, - MotionEventFlags, Pointer, PointersIter, Source, ToolType, + Axis, Button, ButtonState, EdgeFlags, KeyAction, KeyEventFlags, Keycode, MetaState, + MotionAction, MotionEventFlags, Pointer, PointersIter, Source, ToolType, }; // Note: try to keep this wrapper API compatible with the AInputEvent API if possible @@ -49,7 +47,7 @@ impl<'a> MotionEvent<'a> { /// #[inline] pub fn source(&self) -> Source { - let source = self.ga_event.source; + let source = self.ga_event.source as u32; source.into() } @@ -65,7 +63,7 @@ impl<'a> MotionEvent<'a> { /// See [the MotionEvent docs](https://developer.android.com/reference/android/view/MotionEvent#getActionMasked()) #[inline] pub fn action(&self) -> MotionAction { - let action = self.ga_event.action & ndk_sys::AMOTION_EVENT_ACTION_MASK as i32; + let action = self.ga_event.action as u32 & ndk_sys::AMOTION_EVENT_ACTION_MASK; action.into() } @@ -178,7 +176,6 @@ impl<'a> MotionEvent<'a> { /// See [the NDK /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getbuttonstate) #[inline] - // TODO: Button enum to signify only one bitflag can be set? pub fn button_state(&self) -> ButtonState { ButtonState(self.ga_event.buttonState as u32) } @@ -281,7 +278,7 @@ impl PointerImpl<'_> { #[inline] pub fn axis_value(&self, axis: Axis) -> f32 { let pointer = &self.event.ga_event.pointers[self.index]; - let axis: i32 = axis.into(); + let axis: u32 = axis.into(); pointer.axisValues[axis as usize] } @@ -300,7 +297,8 @@ impl PointerImpl<'_> { #[inline] pub fn tool_type(&self) -> ToolType { let pointer = &self.event.ga_event.pointers[self.index]; - pointer.toolType.into() + let tool_type = pointer.toolType as u32; + tool_type.into() } } @@ -667,7 +665,7 @@ impl<'a> KeyEvent<'a> { /// #[inline] pub fn source(&self) -> Source { - let source = self.ga_event.source; + let source = self.ga_event.source as u32; source.into() } @@ -683,13 +681,13 @@ impl<'a> KeyEvent<'a> { /// See [the KeyEvent docs](https://developer.android.com/reference/android/view/KeyEvent#getAction()) #[inline] pub fn action(&self) -> KeyAction { - let action = self.ga_event.action; + let action = self.ga_event.action as u32; action.into() } #[inline] pub fn action_button(&self) -> KeyAction { - let action = self.ga_event.action; + let action = self.ga_event.action as u32; action.into() } @@ -719,7 +717,7 @@ impl<'a> KeyEvent<'a> { /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getkeycode) #[inline] pub fn key_code(&self) -> Keycode { - let keycode = self.ga_event.keyCode; + let keycode = self.ga_event.keyCode as u32; keycode.into() } diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 129175d8..fe2a9f3d 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -547,11 +547,13 @@ impl AndroidAppInner { } pub fn enable_motion_axis(&mut self, axis: Axis) { - unsafe { ffi::GameActivityPointerAxes_enableAxis(axis.into()) } + let axis: u32 = axis.into(); + unsafe { ffi::GameActivityPointerAxes_enableAxis(axis as i32) } } pub fn disable_motion_axis(&mut self, axis: Axis) { - unsafe { ffi::GameActivityPointerAxes_disableAxis(axis.into()) } + let axis: u32 = axis.into(); + unsafe { ffi::GameActivityPointerAxes_disableAxis(axis as i32) } } pub fn create_waker(&self) -> AndroidAppWaker { diff --git a/android-activity/src/input.rs b/android-activity/src/input.rs index 909f8950..96c7d68b 100644 --- a/android-activity/src/input.rs +++ b/android-activity/src/input.rs @@ -1,7 +1,4 @@ -pub use ndk::event::{ - Axis, EdgeFlags, KeyAction, KeyEventFlags, Keycode, MetaState, MotionAction, MotionEventFlags, - Source, SourceClass, ToolType, -}; +use bitflags::bitflags; pub use crate::activity_impl::input::*; use crate::InputStatus; @@ -9,6 +6,238 @@ use crate::InputStatus; mod sdk; pub use sdk::*; +/// An enum representing the source of an [`MotionEvent`] or [`KeyEvent`] +/// +/// See [the InputDevice docs](https://developer.android.com/reference/android/view/InputDevice#SOURCE_ANY) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// This implements `Into` and `From` for converting to/from Android +/// SDK integer values. +/// +#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum Source { + BluetoothStylus = 0x0000c002, + Dpad = 0x00000201, + /// Either a gamepad or a joystick + Gamepad = 0x00000401, + Hdmi = 0x02000001, + /// Either a gamepad or a joystick + Joystick = 0x01000010, + /// Pretty much any device with buttons. Query the keyboard type to determine + /// if it has alphabetic keys and can be used for text entry. + Keyboard = 0x00000101, + /// A pointing device, such as a mouse or trackpad + Mouse = 0x00002002, + /// A pointing device, such as a mouse or trackpad whose relative motions should be treated as navigation events + MouseRelative = 0x00020004, + /// An input device akin to a scroll wheel + RotaryEncoder = 0x00400000, + Sensor = 0x04000000, + Stylus = 0x00004002, + Touchpad = 0x00100008, + Touchscreen = 0x00001002, + TouchNavigation = 0x00200000, + Trackball = 0x00010004, + + // We need to consider that the enum variants may be extended across + // different versions of Android (i.e. effectively at runtime) but at the + // same time we don't want it to be an API break to extend this enum in + // future releases of `android-activity` with new variants from the latest + // NDK/SDK. + // + // We can't just use `#[non_exhaustive]` because that only really helps + // when adding new variants in sync with android-activity releases. + // + // On the other hand we also can't rely on a catch-all `Unknown(u32)` that + // only really helps with unknown variants seen at runtime. + // + // What we aim for instead is to have a hidden catch-all variant that + // is considered (practically) unmatchable so code is forced to have + // a `unknown => {}` catch-all pattern match that will cover unknown variants + // either in the form of Rust variants added in future versions or + // in the form of an `__Unknown(u32)` integer that represents an unknown + // variant seen at runtime. + // + // Any `unknown => {}` pattern match can rely on `IntoPrimitive` to convert + // the `unknown` variant to the integer that comes from the Android SDK + // in case that values needs to be passed on, even without knowing its + // semantic meaning at compile time. + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +// ndk_sys doesn't currently have the `TRACKBALL` flag so we define our +// own internal class constants for now +bitflags! { + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] + struct SourceFlags: u32 { + const CLASS_MASK = 0x000000ff; + + const BUTTON = 0x00000001; + const POINTER = 0x00000002; + const TRACKBALL = 0x00000004; + const POSITION = 0x00000008; + const JOYSTICK = 0x00000010; + const NONE = 0; + } +} + +impl Source { + #[inline] + pub fn is_button_class(self) -> bool { + let class = SourceFlags::from_bits_truncate(self.into()); + class.contains(SourceFlags::BUTTON) + } + #[inline] + pub fn is_pointer_class(self) -> bool { + let class = SourceFlags::from_bits_truncate(self.into()); + class.contains(SourceFlags::POINTER) + } + #[inline] + pub fn is_trackball_class(self) -> bool { + let class = SourceFlags::from_bits_truncate(self.into()); + class.contains(SourceFlags::TRACKBALL) + } + #[inline] + pub fn is_position_class(self) -> bool { + let class = SourceFlags::from_bits_truncate(self.into()); + class.contains(SourceFlags::POSITION) + } + #[inline] + pub fn is_joystick_class(self) -> bool { + let class = SourceFlags::from_bits_truncate(self.into()); + class.contains(SourceFlags::JOYSTICK) + } +} + +/// A bitfield representing the state of modifier keys during an event. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-25) +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct MetaState(pub u32); + +impl MetaState { + #[inline] + pub fn alt_on(self) -> bool { + self.0 & ndk_sys::AMETA_ALT_ON != 0 + } + #[inline] + pub fn alt_left_on(self) -> bool { + self.0 & ndk_sys::AMETA_ALT_LEFT_ON != 0 + } + #[inline] + pub fn alt_right_on(self) -> bool { + self.0 & ndk_sys::AMETA_ALT_RIGHT_ON != 0 + } + #[inline] + pub fn shift_on(self) -> bool { + self.0 & ndk_sys::AMETA_SHIFT_ON != 0 + } + #[inline] + pub fn shift_left_on(self) -> bool { + self.0 & ndk_sys::AMETA_SHIFT_LEFT_ON != 0 + } + #[inline] + pub fn shift_right_on(self) -> bool { + self.0 & ndk_sys::AMETA_SHIFT_RIGHT_ON != 0 + } + #[inline] + pub fn sym_on(self) -> bool { + self.0 & ndk_sys::AMETA_SYM_ON != 0 + } + #[inline] + pub fn function_on(self) -> bool { + self.0 & ndk_sys::AMETA_FUNCTION_ON != 0 + } + #[inline] + pub fn ctrl_on(self) -> bool { + self.0 & ndk_sys::AMETA_CTRL_ON != 0 + } + #[inline] + pub fn ctrl_left_on(self) -> bool { + self.0 & ndk_sys::AMETA_CTRL_LEFT_ON != 0 + } + #[inline] + pub fn ctrl_right_on(self) -> bool { + self.0 & ndk_sys::AMETA_CTRL_RIGHT_ON != 0 + } + #[inline] + pub fn meta_on(self) -> bool { + self.0 & ndk_sys::AMETA_META_ON != 0 + } + #[inline] + pub fn meta_left_on(self) -> bool { + self.0 & ndk_sys::AMETA_META_LEFT_ON != 0 + } + #[inline] + pub fn meta_right_on(self) -> bool { + self.0 & ndk_sys::AMETA_META_RIGHT_ON != 0 + } + #[inline] + pub fn caps_lock_on(self) -> bool { + self.0 & ndk_sys::AMETA_CAPS_LOCK_ON != 0 + } + #[inline] + pub fn num_lock_on(self) -> bool { + self.0 & ndk_sys::AMETA_NUM_LOCK_ON != 0 + } + #[inline] + pub fn scroll_lock_on(self) -> bool { + self.0 & ndk_sys::AMETA_SCROLL_LOCK_ON != 0 + } +} + +impl From for MetaState { + fn from(value: ndk::event::MetaState) -> Self { + Self(value.0) + } +} + +/// A motion action. +/// +/// See [the NDK +/// docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-29) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// This implements `Into` and `From` for converting to/from Android +/// SDK integer values. +/// +#[derive(Copy, Clone, Debug, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum MotionAction { + Down = ndk_sys::AMOTION_EVENT_ACTION_DOWN, + Up = ndk_sys::AMOTION_EVENT_ACTION_UP, + Move = ndk_sys::AMOTION_EVENT_ACTION_MOVE, + Cancel = ndk_sys::AMOTION_EVENT_ACTION_CANCEL, + Outside = ndk_sys::AMOTION_EVENT_ACTION_OUTSIDE, + PointerDown = ndk_sys::AMOTION_EVENT_ACTION_POINTER_DOWN, + PointerUp = ndk_sys::AMOTION_EVENT_ACTION_POINTER_UP, + HoverMove = ndk_sys::AMOTION_EVENT_ACTION_HOVER_MOVE, + Scroll = ndk_sys::AMOTION_EVENT_ACTION_SCROLL, + HoverEnter = ndk_sys::AMOTION_EVENT_ACTION_HOVER_ENTER, + HoverExit = ndk_sys::AMOTION_EVENT_ACTION_HOVER_EXIT, + ButtonPress = ndk_sys::AMOTION_EVENT_ACTION_BUTTON_PRESS, + ButtonRelease = ndk_sys::AMOTION_EVENT_ACTION_BUTTON_RELEASE, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + /// Identifies buttons that are associated with motion events. /// /// See [the NDK @@ -40,6 +269,606 @@ pub enum Button { __Unknown(u32), } +/// An axis of a motion event. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-32) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// This implements `Into` and `From` for converting to/from Android +/// SDK integer values. +/// +#[derive(Copy, Clone, Debug, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum Axis { + X = ndk_sys::AMOTION_EVENT_AXIS_X, + Y = ndk_sys::AMOTION_EVENT_AXIS_Y, + Pressure = ndk_sys::AMOTION_EVENT_AXIS_PRESSURE, + Size = ndk_sys::AMOTION_EVENT_AXIS_SIZE, + TouchMajor = ndk_sys::AMOTION_EVENT_AXIS_TOUCH_MAJOR, + TouchMinor = ndk_sys::AMOTION_EVENT_AXIS_TOUCH_MINOR, + ToolMajor = ndk_sys::AMOTION_EVENT_AXIS_TOOL_MAJOR, + ToolMinor = ndk_sys::AMOTION_EVENT_AXIS_TOOL_MINOR, + Orientation = ndk_sys::AMOTION_EVENT_AXIS_ORIENTATION, + Vscroll = ndk_sys::AMOTION_EVENT_AXIS_VSCROLL, + Hscroll = ndk_sys::AMOTION_EVENT_AXIS_HSCROLL, + Z = ndk_sys::AMOTION_EVENT_AXIS_Z, + Rx = ndk_sys::AMOTION_EVENT_AXIS_RX, + Ry = ndk_sys::AMOTION_EVENT_AXIS_RY, + Rz = ndk_sys::AMOTION_EVENT_AXIS_RZ, + HatX = ndk_sys::AMOTION_EVENT_AXIS_HAT_X, + HatY = ndk_sys::AMOTION_EVENT_AXIS_HAT_Y, + Ltrigger = ndk_sys::AMOTION_EVENT_AXIS_LTRIGGER, + Rtrigger = ndk_sys::AMOTION_EVENT_AXIS_RTRIGGER, + Throttle = ndk_sys::AMOTION_EVENT_AXIS_THROTTLE, + Rudder = ndk_sys::AMOTION_EVENT_AXIS_RUDDER, + Wheel = ndk_sys::AMOTION_EVENT_AXIS_WHEEL, + Gas = ndk_sys::AMOTION_EVENT_AXIS_GAS, + Brake = ndk_sys::AMOTION_EVENT_AXIS_BRAKE, + Distance = ndk_sys::AMOTION_EVENT_AXIS_DISTANCE, + Tilt = ndk_sys::AMOTION_EVENT_AXIS_TILT, + Scroll = ndk_sys::AMOTION_EVENT_AXIS_SCROLL, + RelativeX = ndk_sys::AMOTION_EVENT_AXIS_RELATIVE_X, + RelativeY = ndk_sys::AMOTION_EVENT_AXIS_RELATIVE_Y, + Generic1 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_1, + Generic2 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_2, + Generic3 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_3, + Generic4 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_4, + Generic5 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_5, + Generic6 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_6, + Generic7 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_7, + Generic8 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_8, + Generic9 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_9, + Generic10 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_10, + Generic11 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_11, + Generic12 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_12, + Generic13 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_13, + Generic14 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_14, + Generic15 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_15, + Generic16 = ndk_sys::AMOTION_EVENT_AXIS_GENERIC_16, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +/// The tool type of a pointer. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-48) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// Implements `Into` and `From` for converting to/from Android SDK +/// integer values. +/// +#[derive(Copy, Clone, Debug, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum ToolType { + /// Unknown tool type. + /// + /// This constant is used when the tool type is not known or is not relevant, such as for a trackball or other non-pointing device. + Unknown = ndk_sys::AMOTION_EVENT_TOOL_TYPE_UNKNOWN, + + /// The tool is a finger. + Finger = ndk_sys::AMOTION_EVENT_TOOL_TYPE_FINGER, + + /// The tool is a stylus. + Stylus = ndk_sys::AMOTION_EVENT_TOOL_TYPE_STYLUS, + + /// The tool is a mouse. + Mouse = ndk_sys::AMOTION_EVENT_TOOL_TYPE_MOUSE, + + /// The tool is an eraser or a stylus being used in an inverted posture. + Eraser = ndk_sys::AMOTION_EVENT_TOOL_TYPE_ERASER, + + /// The tool is a palm and should be rejected + Palm = ndk_sys::AMOTION_EVENT_TOOL_TYPE_PALM, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +/// A bitfield representing the state of buttons during a motion event. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-33) +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct ButtonState(pub u32); + +impl ButtonState { + #[inline] + pub fn primary(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_PRIMARY != 0 + } + #[inline] + pub fn secondary(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_SECONDARY != 0 + } + #[inline] + pub fn teriary(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_TERTIARY != 0 + } + #[inline] + pub fn back(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_BACK != 0 + } + #[inline] + pub fn forward(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_FORWARD != 0 + } + #[inline] + pub fn stylus_primary(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY != 0 + } + #[inline] + pub fn stylus_secondary(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY != 0 + } +} + +impl From for ButtonState { + fn from(value: ndk::event::ButtonState) -> Self { + Self(value.0) + } +} + +/// A bitfield representing which edges were touched by a motion event. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-31) +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct EdgeFlags(pub u32); + +impl EdgeFlags { + #[inline] + pub fn top(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_EDGE_FLAG_TOP != 0 + } + #[inline] + pub fn bottom(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_EDGE_FLAG_BOTTOM != 0 + } + #[inline] + pub fn left(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_EDGE_FLAG_LEFT != 0 + } + #[inline] + pub fn right(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_EDGE_FLAG_RIGHT != 0 + } +} + +impl From for EdgeFlags { + fn from(value: ndk::event::EdgeFlags) -> Self { + Self(value.0) + } +} + +/// Flags associated with this [`MotionEvent`]. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-30) +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct MotionEventFlags(pub u32); + +impl MotionEventFlags { + #[inline] + pub fn window_is_obscured(self) -> bool { + self.0 & ndk_sys::AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED != 0 + } +} + +impl From for MotionEventFlags { + fn from(value: ndk::event::MotionEventFlags) -> Self { + Self(value.0) + } +} + +/// Key actions. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-27) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// Implements `Into` and `From` for converting to/from Android SDK +/// integer values. +/// +#[derive(Copy, Clone, Debug, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum KeyAction { + Down = ndk_sys::AKEY_EVENT_ACTION_DOWN, + Up = ndk_sys::AKEY_EVENT_ACTION_UP, + Multiple = ndk_sys::AKEY_EVENT_ACTION_MULTIPLE, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +/// Key codes. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-39) +/// +/// # Android Extensible Enum +/// +/// This is a runtime [extensible enum](`crate#android-extensible-enums`) and +/// should be handled similar to a `#[non_exhaustive]` enum to maintain +/// forwards compatibility. +/// +/// Implements `Into` and `From` for converting to/from Android SDK +/// integer values. +/// +#[derive(Copy, Clone, Debug, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum Keycode { + Unknown = ndk_sys::AKEYCODE_UNKNOWN, + SoftLeft = ndk_sys::AKEYCODE_SOFT_LEFT, + SoftRight = ndk_sys::AKEYCODE_SOFT_RIGHT, + Home = ndk_sys::AKEYCODE_HOME, + Back = ndk_sys::AKEYCODE_BACK, + Call = ndk_sys::AKEYCODE_CALL, + Endcall = ndk_sys::AKEYCODE_ENDCALL, + Keycode0 = ndk_sys::AKEYCODE_0, + Keycode1 = ndk_sys::AKEYCODE_1, + Keycode2 = ndk_sys::AKEYCODE_2, + Keycode3 = ndk_sys::AKEYCODE_3, + Keycode4 = ndk_sys::AKEYCODE_4, + Keycode5 = ndk_sys::AKEYCODE_5, + Keycode6 = ndk_sys::AKEYCODE_6, + Keycode7 = ndk_sys::AKEYCODE_7, + Keycode8 = ndk_sys::AKEYCODE_8, + Keycode9 = ndk_sys::AKEYCODE_9, + Star = ndk_sys::AKEYCODE_STAR, + Pound = ndk_sys::AKEYCODE_POUND, + DpadUp = ndk_sys::AKEYCODE_DPAD_UP, + DpadDown = ndk_sys::AKEYCODE_DPAD_DOWN, + DpadLeft = ndk_sys::AKEYCODE_DPAD_LEFT, + DpadRight = ndk_sys::AKEYCODE_DPAD_RIGHT, + DpadCenter = ndk_sys::AKEYCODE_DPAD_CENTER, + VolumeUp = ndk_sys::AKEYCODE_VOLUME_UP, + VolumeDown = ndk_sys::AKEYCODE_VOLUME_DOWN, + Power = ndk_sys::AKEYCODE_POWER, + Camera = ndk_sys::AKEYCODE_CAMERA, + Clear = ndk_sys::AKEYCODE_CLEAR, + A = ndk_sys::AKEYCODE_A, + B = ndk_sys::AKEYCODE_B, + C = ndk_sys::AKEYCODE_C, + D = ndk_sys::AKEYCODE_D, + E = ndk_sys::AKEYCODE_E, + F = ndk_sys::AKEYCODE_F, + G = ndk_sys::AKEYCODE_G, + H = ndk_sys::AKEYCODE_H, + I = ndk_sys::AKEYCODE_I, + J = ndk_sys::AKEYCODE_J, + K = ndk_sys::AKEYCODE_K, + L = ndk_sys::AKEYCODE_L, + M = ndk_sys::AKEYCODE_M, + N = ndk_sys::AKEYCODE_N, + O = ndk_sys::AKEYCODE_O, + P = ndk_sys::AKEYCODE_P, + Q = ndk_sys::AKEYCODE_Q, + R = ndk_sys::AKEYCODE_R, + S = ndk_sys::AKEYCODE_S, + T = ndk_sys::AKEYCODE_T, + U = ndk_sys::AKEYCODE_U, + V = ndk_sys::AKEYCODE_V, + W = ndk_sys::AKEYCODE_W, + X = ndk_sys::AKEYCODE_X, + Y = ndk_sys::AKEYCODE_Y, + Z = ndk_sys::AKEYCODE_Z, + Comma = ndk_sys::AKEYCODE_COMMA, + Period = ndk_sys::AKEYCODE_PERIOD, + AltLeft = ndk_sys::AKEYCODE_ALT_LEFT, + AltRight = ndk_sys::AKEYCODE_ALT_RIGHT, + ShiftLeft = ndk_sys::AKEYCODE_SHIFT_LEFT, + ShiftRight = ndk_sys::AKEYCODE_SHIFT_RIGHT, + Tab = ndk_sys::AKEYCODE_TAB, + Space = ndk_sys::AKEYCODE_SPACE, + Sym = ndk_sys::AKEYCODE_SYM, + Explorer = ndk_sys::AKEYCODE_EXPLORER, + Envelope = ndk_sys::AKEYCODE_ENVELOPE, + Enter = ndk_sys::AKEYCODE_ENTER, + Del = ndk_sys::AKEYCODE_DEL, + Grave = ndk_sys::AKEYCODE_GRAVE, + Minus = ndk_sys::AKEYCODE_MINUS, + Equals = ndk_sys::AKEYCODE_EQUALS, + LeftBracket = ndk_sys::AKEYCODE_LEFT_BRACKET, + RightBracket = ndk_sys::AKEYCODE_RIGHT_BRACKET, + Backslash = ndk_sys::AKEYCODE_BACKSLASH, + Semicolon = ndk_sys::AKEYCODE_SEMICOLON, + Apostrophe = ndk_sys::AKEYCODE_APOSTROPHE, + Slash = ndk_sys::AKEYCODE_SLASH, + At = ndk_sys::AKEYCODE_AT, + Num = ndk_sys::AKEYCODE_NUM, + Headsethook = ndk_sys::AKEYCODE_HEADSETHOOK, + Focus = ndk_sys::AKEYCODE_FOCUS, + Plus = ndk_sys::AKEYCODE_PLUS, + Menu = ndk_sys::AKEYCODE_MENU, + Notification = ndk_sys::AKEYCODE_NOTIFICATION, + Search = ndk_sys::AKEYCODE_SEARCH, + MediaPlayPause = ndk_sys::AKEYCODE_MEDIA_PLAY_PAUSE, + MediaStop = ndk_sys::AKEYCODE_MEDIA_STOP, + MediaNext = ndk_sys::AKEYCODE_MEDIA_NEXT, + MediaPrevious = ndk_sys::AKEYCODE_MEDIA_PREVIOUS, + MediaRewind = ndk_sys::AKEYCODE_MEDIA_REWIND, + MediaFastForward = ndk_sys::AKEYCODE_MEDIA_FAST_FORWARD, + Mute = ndk_sys::AKEYCODE_MUTE, + PageUp = ndk_sys::AKEYCODE_PAGE_UP, + PageDown = ndk_sys::AKEYCODE_PAGE_DOWN, + Pictsymbols = ndk_sys::AKEYCODE_PICTSYMBOLS, + SwitchCharset = ndk_sys::AKEYCODE_SWITCH_CHARSET, + ButtonA = ndk_sys::AKEYCODE_BUTTON_A, + ButtonB = ndk_sys::AKEYCODE_BUTTON_B, + ButtonC = ndk_sys::AKEYCODE_BUTTON_C, + ButtonX = ndk_sys::AKEYCODE_BUTTON_X, + ButtonY = ndk_sys::AKEYCODE_BUTTON_Y, + ButtonZ = ndk_sys::AKEYCODE_BUTTON_Z, + ButtonL1 = ndk_sys::AKEYCODE_BUTTON_L1, + ButtonR1 = ndk_sys::AKEYCODE_BUTTON_R1, + ButtonL2 = ndk_sys::AKEYCODE_BUTTON_L2, + ButtonR2 = ndk_sys::AKEYCODE_BUTTON_R2, + ButtonThumbl = ndk_sys::AKEYCODE_BUTTON_THUMBL, + ButtonThumbr = ndk_sys::AKEYCODE_BUTTON_THUMBR, + ButtonStart = ndk_sys::AKEYCODE_BUTTON_START, + ButtonSelect = ndk_sys::AKEYCODE_BUTTON_SELECT, + ButtonMode = ndk_sys::AKEYCODE_BUTTON_MODE, + Escape = ndk_sys::AKEYCODE_ESCAPE, + ForwardDel = ndk_sys::AKEYCODE_FORWARD_DEL, + CtrlLeft = ndk_sys::AKEYCODE_CTRL_LEFT, + CtrlRight = ndk_sys::AKEYCODE_CTRL_RIGHT, + CapsLock = ndk_sys::AKEYCODE_CAPS_LOCK, + ScrollLock = ndk_sys::AKEYCODE_SCROLL_LOCK, + MetaLeft = ndk_sys::AKEYCODE_META_LEFT, + MetaRight = ndk_sys::AKEYCODE_META_RIGHT, + Function = ndk_sys::AKEYCODE_FUNCTION, + Sysrq = ndk_sys::AKEYCODE_SYSRQ, + Break = ndk_sys::AKEYCODE_BREAK, + MoveHome = ndk_sys::AKEYCODE_MOVE_HOME, + MoveEnd = ndk_sys::AKEYCODE_MOVE_END, + Insert = ndk_sys::AKEYCODE_INSERT, + Forward = ndk_sys::AKEYCODE_FORWARD, + MediaPlay = ndk_sys::AKEYCODE_MEDIA_PLAY, + MediaPause = ndk_sys::AKEYCODE_MEDIA_PAUSE, + MediaClose = ndk_sys::AKEYCODE_MEDIA_CLOSE, + MediaEject = ndk_sys::AKEYCODE_MEDIA_EJECT, + MediaRecord = ndk_sys::AKEYCODE_MEDIA_RECORD, + F1 = ndk_sys::AKEYCODE_F1, + F2 = ndk_sys::AKEYCODE_F2, + F3 = ndk_sys::AKEYCODE_F3, + F4 = ndk_sys::AKEYCODE_F4, + F5 = ndk_sys::AKEYCODE_F5, + F6 = ndk_sys::AKEYCODE_F6, + F7 = ndk_sys::AKEYCODE_F7, + F8 = ndk_sys::AKEYCODE_F8, + F9 = ndk_sys::AKEYCODE_F9, + F10 = ndk_sys::AKEYCODE_F10, + F11 = ndk_sys::AKEYCODE_F11, + F12 = ndk_sys::AKEYCODE_F12, + NumLock = ndk_sys::AKEYCODE_NUM_LOCK, + Numpad0 = ndk_sys::AKEYCODE_NUMPAD_0, + Numpad1 = ndk_sys::AKEYCODE_NUMPAD_1, + Numpad2 = ndk_sys::AKEYCODE_NUMPAD_2, + Numpad3 = ndk_sys::AKEYCODE_NUMPAD_3, + Numpad4 = ndk_sys::AKEYCODE_NUMPAD_4, + Numpad5 = ndk_sys::AKEYCODE_NUMPAD_5, + Numpad6 = ndk_sys::AKEYCODE_NUMPAD_6, + Numpad7 = ndk_sys::AKEYCODE_NUMPAD_7, + Numpad8 = ndk_sys::AKEYCODE_NUMPAD_8, + Numpad9 = ndk_sys::AKEYCODE_NUMPAD_9, + NumpadDivide = ndk_sys::AKEYCODE_NUMPAD_DIVIDE, + NumpadMultiply = ndk_sys::AKEYCODE_NUMPAD_MULTIPLY, + NumpadSubtract = ndk_sys::AKEYCODE_NUMPAD_SUBTRACT, + NumpadAdd = ndk_sys::AKEYCODE_NUMPAD_ADD, + NumpadDot = ndk_sys::AKEYCODE_NUMPAD_DOT, + NumpadComma = ndk_sys::AKEYCODE_NUMPAD_COMMA, + NumpadEnter = ndk_sys::AKEYCODE_NUMPAD_ENTER, + NumpadEquals = ndk_sys::AKEYCODE_NUMPAD_EQUALS, + NumpadLeftParen = ndk_sys::AKEYCODE_NUMPAD_LEFT_PAREN, + NumpadRightParen = ndk_sys::AKEYCODE_NUMPAD_RIGHT_PAREN, + VolumeMute = ndk_sys::AKEYCODE_VOLUME_MUTE, + Info = ndk_sys::AKEYCODE_INFO, + ChannelUp = ndk_sys::AKEYCODE_CHANNEL_UP, + ChannelDown = ndk_sys::AKEYCODE_CHANNEL_DOWN, + ZoomIn = ndk_sys::AKEYCODE_ZOOM_IN, + ZoomOut = ndk_sys::AKEYCODE_ZOOM_OUT, + Tv = ndk_sys::AKEYCODE_TV, + Window = ndk_sys::AKEYCODE_WINDOW, + Guide = ndk_sys::AKEYCODE_GUIDE, + Dvr = ndk_sys::AKEYCODE_DVR, + Bookmark = ndk_sys::AKEYCODE_BOOKMARK, + Captions = ndk_sys::AKEYCODE_CAPTIONS, + Settings = ndk_sys::AKEYCODE_SETTINGS, + TvPower = ndk_sys::AKEYCODE_TV_POWER, + TvInput = ndk_sys::AKEYCODE_TV_INPUT, + StbPower = ndk_sys::AKEYCODE_STB_POWER, + StbInput = ndk_sys::AKEYCODE_STB_INPUT, + AvrPower = ndk_sys::AKEYCODE_AVR_POWER, + AvrInput = ndk_sys::AKEYCODE_AVR_INPUT, + ProgRed = ndk_sys::AKEYCODE_PROG_RED, + ProgGreen = ndk_sys::AKEYCODE_PROG_GREEN, + ProgYellow = ndk_sys::AKEYCODE_PROG_YELLOW, + ProgBlue = ndk_sys::AKEYCODE_PROG_BLUE, + AppSwitch = ndk_sys::AKEYCODE_APP_SWITCH, + Button1 = ndk_sys::AKEYCODE_BUTTON_1, + Button2 = ndk_sys::AKEYCODE_BUTTON_2, + Button3 = ndk_sys::AKEYCODE_BUTTON_3, + Button4 = ndk_sys::AKEYCODE_BUTTON_4, + Button5 = ndk_sys::AKEYCODE_BUTTON_5, + Button6 = ndk_sys::AKEYCODE_BUTTON_6, + Button7 = ndk_sys::AKEYCODE_BUTTON_7, + Button8 = ndk_sys::AKEYCODE_BUTTON_8, + Button9 = ndk_sys::AKEYCODE_BUTTON_9, + Button10 = ndk_sys::AKEYCODE_BUTTON_10, + Button11 = ndk_sys::AKEYCODE_BUTTON_11, + Button12 = ndk_sys::AKEYCODE_BUTTON_12, + Button13 = ndk_sys::AKEYCODE_BUTTON_13, + Button14 = ndk_sys::AKEYCODE_BUTTON_14, + Button15 = ndk_sys::AKEYCODE_BUTTON_15, + Button16 = ndk_sys::AKEYCODE_BUTTON_16, + LanguageSwitch = ndk_sys::AKEYCODE_LANGUAGE_SWITCH, + MannerMode = ndk_sys::AKEYCODE_MANNER_MODE, + Keycode3dMode = ndk_sys::AKEYCODE_3D_MODE, + Contacts = ndk_sys::AKEYCODE_CONTACTS, + Calendar = ndk_sys::AKEYCODE_CALENDAR, + Music = ndk_sys::AKEYCODE_MUSIC, + Calculator = ndk_sys::AKEYCODE_CALCULATOR, + ZenkakuHankaku = ndk_sys::AKEYCODE_ZENKAKU_HANKAKU, + Eisu = ndk_sys::AKEYCODE_EISU, + Muhenkan = ndk_sys::AKEYCODE_MUHENKAN, + Henkan = ndk_sys::AKEYCODE_HENKAN, + KatakanaHiragana = ndk_sys::AKEYCODE_KATAKANA_HIRAGANA, + Yen = ndk_sys::AKEYCODE_YEN, + Ro = ndk_sys::AKEYCODE_RO, + Kana = ndk_sys::AKEYCODE_KANA, + Assist = ndk_sys::AKEYCODE_ASSIST, + BrightnessDown = ndk_sys::AKEYCODE_BRIGHTNESS_DOWN, + BrightnessUp = ndk_sys::AKEYCODE_BRIGHTNESS_UP, + MediaAudioTrack = ndk_sys::AKEYCODE_MEDIA_AUDIO_TRACK, + Sleep = ndk_sys::AKEYCODE_SLEEP, + Wakeup = ndk_sys::AKEYCODE_WAKEUP, + Pairing = ndk_sys::AKEYCODE_PAIRING, + MediaTopMenu = ndk_sys::AKEYCODE_MEDIA_TOP_MENU, + Keycode11 = ndk_sys::AKEYCODE_11, + Keycode12 = ndk_sys::AKEYCODE_12, + LastChannel = ndk_sys::AKEYCODE_LAST_CHANNEL, + TvDataService = ndk_sys::AKEYCODE_TV_DATA_SERVICE, + VoiceAssist = ndk_sys::AKEYCODE_VOICE_ASSIST, + TvRadioService = ndk_sys::AKEYCODE_TV_RADIO_SERVICE, + TvTeletext = ndk_sys::AKEYCODE_TV_TELETEXT, + TvNumberEntry = ndk_sys::AKEYCODE_TV_NUMBER_ENTRY, + TvTerrestrialAnalog = ndk_sys::AKEYCODE_TV_TERRESTRIAL_ANALOG, + TvTerrestrialDigital = ndk_sys::AKEYCODE_TV_TERRESTRIAL_DIGITAL, + TvSatellite = ndk_sys::AKEYCODE_TV_SATELLITE, + TvSatelliteBs = ndk_sys::AKEYCODE_TV_SATELLITE_BS, + TvSatelliteCs = ndk_sys::AKEYCODE_TV_SATELLITE_CS, + TvSatelliteService = ndk_sys::AKEYCODE_TV_SATELLITE_SERVICE, + TvNetwork = ndk_sys::AKEYCODE_TV_NETWORK, + TvAntennaCable = ndk_sys::AKEYCODE_TV_ANTENNA_CABLE, + TvInputHdmi1 = ndk_sys::AKEYCODE_TV_INPUT_HDMI_1, + TvInputHdmi2 = ndk_sys::AKEYCODE_TV_INPUT_HDMI_2, + TvInputHdmi3 = ndk_sys::AKEYCODE_TV_INPUT_HDMI_3, + TvInputHdmi4 = ndk_sys::AKEYCODE_TV_INPUT_HDMI_4, + TvInputComposite1 = ndk_sys::AKEYCODE_TV_INPUT_COMPOSITE_1, + TvInputComposite2 = ndk_sys::AKEYCODE_TV_INPUT_COMPOSITE_2, + TvInputComponent1 = ndk_sys::AKEYCODE_TV_INPUT_COMPONENT_1, + TvInputComponent2 = ndk_sys::AKEYCODE_TV_INPUT_COMPONENT_2, + TvInputVga1 = ndk_sys::AKEYCODE_TV_INPUT_VGA_1, + TvAudioDescription = ndk_sys::AKEYCODE_TV_AUDIO_DESCRIPTION, + TvAudioDescriptionMixUp = ndk_sys::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP, + TvAudioDescriptionMixDown = ndk_sys::AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN, + TvZoomMode = ndk_sys::AKEYCODE_TV_ZOOM_MODE, + TvContentsMenu = ndk_sys::AKEYCODE_TV_CONTENTS_MENU, + TvMediaContextMenu = ndk_sys::AKEYCODE_TV_MEDIA_CONTEXT_MENU, + TvTimerProgramming = ndk_sys::AKEYCODE_TV_TIMER_PROGRAMMING, + Help = ndk_sys::AKEYCODE_HELP, + NavigatePrevious = ndk_sys::AKEYCODE_NAVIGATE_PREVIOUS, + NavigateNext = ndk_sys::AKEYCODE_NAVIGATE_NEXT, + NavigateIn = ndk_sys::AKEYCODE_NAVIGATE_IN, + NavigateOut = ndk_sys::AKEYCODE_NAVIGATE_OUT, + StemPrimary = ndk_sys::AKEYCODE_STEM_PRIMARY, + Stem1 = ndk_sys::AKEYCODE_STEM_1, + Stem2 = ndk_sys::AKEYCODE_STEM_2, + Stem3 = ndk_sys::AKEYCODE_STEM_3, + DpadUpLeft = ndk_sys::AKEYCODE_DPAD_UP_LEFT, + DpadDownLeft = ndk_sys::AKEYCODE_DPAD_DOWN_LEFT, + DpadUpRight = ndk_sys::AKEYCODE_DPAD_UP_RIGHT, + DpadDownRight = ndk_sys::AKEYCODE_DPAD_DOWN_RIGHT, + MediaSkipForward = ndk_sys::AKEYCODE_MEDIA_SKIP_FORWARD, + MediaSkipBackward = ndk_sys::AKEYCODE_MEDIA_SKIP_BACKWARD, + MediaStepForward = ndk_sys::AKEYCODE_MEDIA_STEP_FORWARD, + MediaStepBackward = ndk_sys::AKEYCODE_MEDIA_STEP_BACKWARD, + SoftSleep = ndk_sys::AKEYCODE_SOFT_SLEEP, + Cut = ndk_sys::AKEYCODE_CUT, + Copy = ndk_sys::AKEYCODE_COPY, + Paste = ndk_sys::AKEYCODE_PASTE, + SystemNavigationUp = ndk_sys::AKEYCODE_SYSTEM_NAVIGATION_UP, + SystemNavigationDown = ndk_sys::AKEYCODE_SYSTEM_NAVIGATION_DOWN, + SystemNavigationLeft = ndk_sys::AKEYCODE_SYSTEM_NAVIGATION_LEFT, + SystemNavigationRight = ndk_sys::AKEYCODE_SYSTEM_NAVIGATION_RIGHT, + AllApps = ndk_sys::AKEYCODE_ALL_APPS, + Refresh = ndk_sys::AKEYCODE_REFRESH, + ThumbsUp = ndk_sys::AKEYCODE_THUMBS_UP, + ThumbsDown = ndk_sys::AKEYCODE_THUMBS_DOWN, + ProfileSwitch = ndk_sys::AKEYCODE_PROFILE_SWITCH, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +/// Flags associated with [`KeyEvent`]. +/// +/// See [the NDK docs](https://developer.android.com/ndk/reference/group/input#anonymous-enum-28) +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct KeyEventFlags(pub u32); + +impl KeyEventFlags { + #[inline] + pub fn cancelled(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_CANCELED != 0 + } + #[inline] + pub fn cancelled_long_press(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_CANCELED_LONG_PRESS != 0 + } + #[inline] + pub fn editor_action(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_EDITOR_ACTION != 0 + } + #[inline] + pub fn fallback(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_FALLBACK != 0 + } + #[inline] + pub fn from_system(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_FROM_SYSTEM != 0 + } + #[inline] + pub fn keep_touch_mode(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_KEEP_TOUCH_MODE != 0 + } + #[inline] + pub fn long_press(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_LONG_PRESS != 0 + } + #[inline] + pub fn soft_keyboard(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_SOFT_KEYBOARD != 0 + } + #[inline] + pub fn tracking(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_TRACKING != 0 + } + #[inline] + pub fn virtual_hard_key(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY != 0 + } + #[inline] + pub fn woke_here(&self) -> bool { + self.0 & ndk_sys::AKEY_EVENT_FLAG_WOKE_HERE != 0 + } +} + +impl From for KeyEventFlags { + fn from(value: ndk::event::KeyEventFlags) -> Self { + Self(value.0) + } +} + /// This struct holds a span within a region of text from `start` to `end`. /// /// The `start` index may be greater than the `end` index (swapping `start` and `end` will represent the same span) diff --git a/android-activity/src/input/sdk.rs b/android-activity/src/input/sdk.rs index 978ad5a8..b40a7df7 100644 --- a/android-activity/src/input/sdk.rs +++ b/android-activity/src/input/sdk.rs @@ -246,8 +246,10 @@ impl KeyCharacterMap { /// a [`AppError::JavaError`] in case there is a spurious JNI error or an exception /// is caught. pub fn get(&self, key_code: Keycode, meta_state: MetaState) -> Result { - let key_code = key_code.into(); - let meta_state = meta_state.0 as i32; + let key_code: u32 = key_code.into(); + let key_code = key_code as jni_sys::jint; + let meta_state: u32 = meta_state.0; + let meta_state = meta_state as jni_sys::jint; // Since we expect this API to be called from the `main` thread then we expect to already be // attached to the JVM diff --git a/android-activity/src/native_activity/input.rs b/android-activity/src/native_activity/input.rs index 15591086..96187ecd 100644 --- a/android-activity/src/native_activity/input.rs +++ b/android-activity/src/native_activity/input.rs @@ -1,10 +1,8 @@ use std::marker::PhantomData; -use ndk::event::ButtonState; - use crate::input::{ - Axis, EdgeFlags, KeyAction, Keycode, MetaState, MotionAction, MotionEventFlags, Pointer, - PointersIter, Source, ToolType, + Axis, Button, ButtonState, EdgeFlags, KeyAction, Keycode, MetaState, MotionAction, + MotionEventFlags, Pointer, PointersIter, Source, ToolType, }; /// A motion event @@ -32,7 +30,13 @@ impl MotionEvent<'_> { /// #[inline] pub fn source(&self) -> Source { - self.ndk_event.source() + // XXX: we use `AInputEvent_getSource` directly (instead of calling + // ndk_event.source()) since we have our own `Source` enum that we + // share between backends, which may also capture unknown variants + // added in new versions of Android. + let source = + unsafe { ndk_sys::AInputEvent_getSource(self.ndk_event.ptr().as_ptr()) as u32 }; + source.into() } /// Get the device id associated with the event. @@ -47,7 +51,13 @@ impl MotionEvent<'_> { /// See [the MotionEvent docs](https://developer.android.com/reference/android/view/MotionEvent#getActionMasked()) #[inline] pub fn action(&self) -> MotionAction { - self.ndk_event.action() + // XXX: we use `AMotionEvent_getAction` directly since we have our own + // `MotionAction` enum that we share between backends, which may also + // capture unknown variants added in new versions of Android. + let action = + unsafe { ndk_sys::AMotionEvent_getAction(self.ndk_event.ptr().as_ptr()) as u32 } + & ndk_sys::AMOTION_EVENT_ACTION_MASK; + action.into() } /// Returns which button has been modified during a press or release action. @@ -57,11 +67,10 @@ impl MotionEvent<'_> { /// /// See [the MotionEvent docs](https://developer.android.com/reference/android/view/MotionEvent#getActionButton()) #[inline] - #[cfg(feature = "api-level-33")] - #[doc(alias = "AMotionEvent_getActionButton")] - // TODO: Button enum to signify only one bitflag can be set? - pub fn action_button(&self) -> ButtonState { - self.ndk_event.action_button() + 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() } /// Returns the pointer index of an `Up` or `Down` event. @@ -145,7 +154,7 @@ impl MotionEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getmetastate) #[inline] pub fn meta_state(&self) -> MetaState { - self.ndk_event.meta_state() + self.ndk_event.meta_state().into() } /// Returns the button state during this event, as a bitfield. @@ -154,7 +163,7 @@ impl MotionEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getbuttonstate) #[inline] pub fn button_state(&self) -> ButtonState { - self.ndk_event.button_state() + self.ndk_event.button_state().into() } /// Returns the time of the start of this gesture, in the `java.lang.System.nanoTime()` time @@ -173,7 +182,7 @@ impl MotionEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getedgeflags) #[inline] pub fn edge_flags(&self) -> EdgeFlags { - self.ndk_event.edge_flags() + self.ndk_event.edge_flags().into() } /// Returns the time of this event, in the `java.lang.System.nanoTime()` time base @@ -191,7 +200,7 @@ impl MotionEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#amotionevent_getflags) #[inline] pub fn flags(&self) -> MotionEventFlags { - self.ndk_event.flags() + self.ndk_event.flags().into() } /* Missing from GameActivity currently... @@ -252,7 +261,8 @@ impl PointerImpl<'_> { #[inline] pub fn axis_value(&self, axis: Axis) -> f32 { - let value: i32 = axis.into(); + let value: u32 = axis.into(); + let value = value as i32; self.ndk_pointer.axis_value(value.into()) } @@ -269,6 +279,7 @@ impl PointerImpl<'_> { #[inline] pub fn tool_type(&self) -> ToolType { let value: i32 = self.ndk_pointer.tool_type().into(); + let value = value as u32; value.into() } } @@ -320,9 +331,16 @@ impl KeyEvent<'_> { } /// Get the source of the event. + /// #[inline] pub fn source(&self) -> Source { - self.ndk_event.source() + // XXX: we use `AInputEvent_getSource` directly (instead of calling + // ndk_event.source()) since we have our own `Source` enum that we + // share between backends, which may also capture unknown variants + // added in new versions of Android. + let source = + unsafe { ndk_sys::AInputEvent_getSource(self.ndk_event.ptr().as_ptr()) as u32 }; + source.into() } /// Get the device id associated with the event. @@ -337,7 +355,11 @@ impl KeyEvent<'_> { /// See [the KeyEvent docs](https://developer.android.com/reference/android/view/KeyEvent#getAction()) #[inline] pub fn action(&self) -> KeyAction { - self.ndk_event.action() + // XXX: we use `AInputEvent_getAction` directly since we have our own + // `KeyAction` enum that we share between backends, which may also + // capture unknown variants added in new versions of Android. + let action = unsafe { ndk_sys::AKeyEvent_getAction(self.ndk_event.ptr().as_ptr()) as u32 }; + action.into() } /// Returns the last time the key was pressed. This is on the scale of @@ -366,7 +388,12 @@ impl KeyEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getkeycode) #[inline] pub fn key_code(&self) -> Keycode { - self.ndk_event.key_code() + // XXX: we use `AInputEvent_getKeyCode` directly since we have our own + // `Keycode` enum that we share between backends, which may also + // capture unknown variants added in new versions of Android. + let keycode = + unsafe { ndk_sys::AKeyEvent_getKeyCode(self.ndk_event.ptr().as_ptr()) as u32 }; + keycode.into() } /// Returns the number of repeats of a key. @@ -393,12 +420,13 @@ impl KeyEvent<'_> { /// docs](https://developer.android.com/ndk/reference/group/input#akeyevent_getmetastate) #[inline] pub fn meta_state(&self) -> MetaState { - self.ndk_event.meta_state() + self.ndk_event.meta_state().into() } } // We use our own wrapper type for input events to have better consistency -// with GameActivity +// with GameActivity and ensure the enum can be extended without needing a +// semver bump /// Enum of possible input events #[derive(Debug)] #[non_exhaustive]