Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions android-activity/src/game_activity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,32 @@ impl AndroidAppInner {
}
}

// TODO: move into a trait
pub fn show_soft_input(&self, show_implicit: bool) {
unsafe {
let activity = (*self.native_app.as_ptr()).activity;
let flags = if show_implicit {
ffi::ShowImeFlags_SHOW_IMPLICIT
} else {
0
};
ffi::GameActivity_showSoftInput(activity, flags);
}
}

// TODO: move into a trait
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
unsafe {
let activity = (*self.native_app.as_ptr()).activity;
let flags = if hide_implicit_only {
ffi::HideImeFlags_HIDE_IMPLICIT_ONLY
} else {
0
};
ffi::GameActivity_hideSoftInput(activity, flags);
}
}

pub fn enable_motion_axis(&mut self, axis: Axis) {
unsafe { ffi::GameActivityPointerAxes_enableAxis(axis as i32) }
}
Expand Down
25 changes: 25 additions & 0 deletions android-activity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,35 @@ impl AndroidApp {
self.inner.write().unwrap().enable_motion_axis(axis);
}

/// Disable input axis
///
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
/// and other axis should be enabled explicitly.
pub fn disable_motion_axis(&self, axis: input::Axis) {
self.inner.write().unwrap().disable_motion_axis(axis);
}

/// Explicitly request that the current input method's soft input area be
/// shown to the user, if needed.
///
/// Call this if the user interacts with your view in such a way that they
/// have expressed they would like to start performing input into it.
pub fn show_soft_input(&self, show_implicit: bool) {
self.inner.read().unwrap().show_soft_input(show_implicit);
}

/// Request to hide the soft input window from the context of the window
/// that is currently accepting input.
///
/// This should be called as a result of the user doing some action that
/// fairly explicitly requests to have the input window hidden.
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
self.inner
.read()
.unwrap()
.hide_soft_input(hide_implicit_only);
}

/// Query and process all out-standing input event
///
/// Applications are generally either expected to call this in-sync with their rendering or
Expand Down
53 changes: 49 additions & 4 deletions android-activity/src/native_activity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@ mod ffi;

pub mod input {
pub use ndk::event::{
Axis, ButtonState, EdgeFlags, InputEvent, KeyAction, KeyEvent, KeyEventFlags, Keycode,
MetaState, MotionAction, MotionEvent, MotionEventFlags, Pointer, Source,
Axis, ButtonState, EdgeFlags, KeyAction, KeyEvent, KeyEventFlags, Keycode, MetaState,
MotionAction, MotionEvent, MotionEventFlags, Pointer, Source,
};

// We use our own wrapper type for input events to have better consistency
// with GameActivity and ensure the enum can be extended without needing a
// semver bump
#[derive(Debug)]
#[non_exhaustive]
pub enum InputEvent {
MotionEvent(self::MotionEvent),
KeyEvent(self::KeyEvent),
}
}

// The only time it's safe to update the android_app->savedState pointer is
Expand Down Expand Up @@ -369,6 +379,32 @@ impl AndroidAppInner {
}
}

// TODO: move into a trait
pub fn show_soft_input(&self, show_implicit: bool) {
let na = self.native_activity();
unsafe {
let flags = if show_implicit {
ffi::ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT
} else {
0
};
ffi::ANativeActivity_showSoftInput(na as *mut _, flags);
}
}

// TODO: move into a trait
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
let na = self.native_activity();
unsafe {
let flags = if hide_implicit_only {
ffi::ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY
} else {
0
};
ffi::ANativeActivity_hideSoftInput(na as *mut _, flags);
}
}

pub fn enable_motion_axis(&self, _axis: input::Axis) {
// NOP - The InputQueue API doesn't let us optimize which axis values are read
}
Expand Down Expand Up @@ -403,16 +439,25 @@ impl AndroidAppInner {
// ref: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/jni/android_view_InputQueue.cpp
//
while let Ok(Some(event)) = queue.get_event() {
if let Some(event) = queue.pre_dispatch(event) {
if let Some(ndk_event) = queue.pre_dispatch(event) {
let event = match ndk_event {
ndk::event::InputEvent::MotionEvent(e) => input::InputEvent::MotionEvent(e),
ndk::event::InputEvent::KeyEvent(e) => input::InputEvent::KeyEvent(e),
};
callback(&event);

let ndk_event = match event {
input::InputEvent::MotionEvent(e) => ndk::event::InputEvent::MotionEvent(e),
input::InputEvent::KeyEvent(e) => ndk::event::InputEvent::KeyEvent(e),
};

// Always report events as 'handled'. This means we won't get
// so called 'fallback' events generated (such as converting trackball
// events into emulated keypad events), but we could conceivably
// implement similar emulation somewhere else in the stack if
// necessary, and this will be more consistent with the GameActivity
// input handling that doesn't do any kind of emulation.
queue.finish_event(event, true);
queue.finish_event(ndk_event, true);
}
}
}
Expand Down