Skip to content

Commit 69bb80d

Browse files
authored
input: Split out InputEventJava into Motion and Key with Deref (#503)
When I implemented the `from_java()` constructors for `MotionEvent` and `KeyEvent` in #456, I used a single `InputEventJava` wrapper since that could wrap the existing `enum InputEvent` and only need a single destructor calling `AInputEvent_release()` (which must only be called when the input event was created from Java). This however requires existing callers to `MotionEvent::from_java()` and `KeyEvent::from_java()` to _unwrap_/unpack that nested `enum InputEvent` again in order to get access to the underlying native methods, despite already calling a specific constructor method (since Android makes a distinction between both types). Not that that is even reachable, since the nested `InputEvent` member was private and there was no `Deref` into `&InputEvent` anywhere making it impossible to use this API in any meaningful way. Solve both issues by splitting the `struct` into a `Motion` and `Key` variant, and implement `Deref` on both to their respective type. No wrapper `InputEventJava` remains since there does not appear to be any reason to pass both of these types into a single API.
1 parent a237f62 commit 69bb80d

File tree

1 file changed

+46
-21
lines changed

1 file changed

+46
-21
lines changed

ndk/src/event.rs

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! [`android.view.MotionEvent`]: https://developer.android.com/reference/android/view/MotionEvent
1111
//! [`android.view.KeyEvent`]: https://developer.android.com/reference/android/view/KeyEvent
1212
13-
use std::ptr::NonNull;
13+
use std::{ops::Deref, ptr::NonNull};
1414

1515
#[cfg(feature = "api-level-31")]
1616
use jni_sys::{jobject, JNIEnv};
@@ -27,26 +27,53 @@ pub enum InputEvent {
2727
KeyEvent(KeyEvent),
2828
}
2929

30-
/// Wraps a Java [`InputEvent`] acquired from [`KeyEvent::from_java()`] or
31-
/// [`MotionEvent::from_java()`] with respective [`Drop`] semantics.
30+
/// Wraps a Java [`MotionEvent`] acquired from [`MotionEvent::from_java()`] with respective [`Drop`] semantics.
3231
#[cfg(feature = "api-level-31")]
3332
#[derive(Debug)]
34-
#[doc(alias = "AInputEvent")]
35-
pub struct InputEventJava(InputEvent);
33+
pub struct MotionEventJava(MotionEvent);
34+
35+
#[cfg(feature = "api-level-31")]
36+
impl Deref for MotionEventJava {
37+
type Target = MotionEvent;
38+
39+
fn deref(&self) -> &Self::Target {
40+
&self.0
41+
}
42+
}
43+
44+
#[cfg(feature = "api-level-31")]
45+
impl Drop for MotionEventJava {
46+
/// Releases interface objects created by [`MotionEvent::from_java()`].
47+
///
48+
/// The underlying Java object remains valid and does not change its state.
49+
#[doc(alias = "AInputEvent_release")]
50+
fn drop(&mut self) {
51+
unsafe { ffi::AInputEvent_release(self.0.ptr.as_ptr().cast()) }
52+
}
53+
}
54+
55+
/// Wraps a Java [`KeyEvent`] acquired from [`KeyEvent::from_java()`] with respective [`Drop`] semantics.
56+
#[cfg(feature = "api-level-31")]
57+
#[derive(Debug)]
58+
pub struct KeyEventJava(KeyEvent);
59+
60+
#[cfg(feature = "api-level-31")]
61+
impl Deref for KeyEventJava {
62+
type Target = KeyEvent;
63+
64+
fn deref(&self) -> &Self::Target {
65+
&self.0
66+
}
67+
}
3668

3769
#[cfg(feature = "api-level-31")]
38-
impl Drop for InputEventJava {
39-
/// Releases interface objects created by [`KeyEvent::from_java()`] or
40-
/// [`MotionEvent::from_java()`].
70+
impl Drop for KeyEventJava {
71+
/// Releases interface objects created by [`KeyEvent::from_java()`].
4172
///
4273
/// The underlying Java object remains valid and does not change its state.
4374
#[doc(alias = "AInputEvent_release")]
4475
fn drop(&mut self) {
45-
let ptr = match self.0 {
46-
InputEvent::MotionEvent(MotionEvent { ptr })
47-
| InputEvent::KeyEvent(KeyEvent { ptr }) => ptr.as_ptr().cast(),
48-
};
49-
unsafe { ffi::AInputEvent_release(ptr) }
76+
unsafe { ffi::AInputEvent_release(self.0.ptr.as_ptr().cast()) }
5077
}
5178
}
5279

@@ -641,11 +668,11 @@ impl MotionEvent {
641668
/// [`android.view.MotionEvent`]: https://developer.android.com/reference/android/view/MotionEvent
642669
#[cfg(feature = "api-level-31")]
643670
#[doc(alias = "AMotionEvent_fromJava")]
644-
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
671+
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<MotionEventJava> {
645672
let ptr = unsafe { ffi::AMotionEvent_fromJava(env, key_event) };
646-
Some(InputEventJava(InputEvent::MotionEvent(Self::from_ptr(
647-
NonNull::new(ptr.cast_mut())?,
648-
))))
673+
Some(MotionEventJava(Self::from_ptr(NonNull::new(
674+
ptr.cast_mut(),
675+
)?)))
649676
}
650677

651678
/// Returns a pointer to the native [`ffi::AInputEvent`].
@@ -1994,11 +2021,9 @@ impl KeyEvent {
19942021
/// [`android.view.KeyEvent`]: https://developer.android.com/reference/android/view/KeyEvent
19952022
#[cfg(feature = "api-level-31")]
19962023
#[doc(alias = "AKeyEvent_fromJava")]
1997-
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<InputEventJava> {
2024+
pub unsafe fn from_java(env: *mut JNIEnv, key_event: jobject) -> Option<KeyEventJava> {
19982025
let ptr = unsafe { ffi::AKeyEvent_fromJava(env, key_event) };
1999-
Some(InputEventJava(InputEvent::KeyEvent(Self::from_ptr(
2000-
NonNull::new(ptr.cast_mut())?,
2001-
))))
2026+
Some(KeyEventJava(Self::from_ptr(NonNull::new(ptr.cast_mut())?)))
20022027
}
20032028

20042029
/// Returns a pointer to the native [`ffi::AInputEvent`].

0 commit comments

Comments
 (0)