Skip to content

Commit

Permalink
android: Show keyboard with WindowInsetsController.
Browse files Browse the repository at this point in the history
  • Loading branch information
xorgy committed Jul 10, 2024
1 parent 3e8fa41 commit 3ad944f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ softbuffer = { version = "0.4.0", default-features = false, features = [
[target.'cfg(target_os = "android")'.dependencies]
android-activity = "0.6.0"
ndk = { version = "0.9.0", default-features = false }
jni = "0.21"

[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
core-foundation = "0.9.3"
Expand Down
4 changes: 4 additions & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ changelog entry.
### Fixed

- On macOS, fix panic on exit when dropping windows outside the event loop.

### Changed

- On Android with native-activity, summon and dismiss the soft keyboard with `set_ime_allowed`
55 changes: 53 additions & 2 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ impl<T: 'static> EventLoop<T> {
&redraw_flag,
android_app.create_waker(),
),
show_keyboard_on_resume: Arc::new(AtomicBool::new(false)),
},
_marker: PhantomData,
},
Expand Down Expand Up @@ -267,6 +268,11 @@ impl<T: 'static> EventLoop<T> {
MainEvent::Resume { .. } => {
debug!("App Resumed - is running");
self.running = true;
#[cfg(feature = "android-native-activity")]
show_hide_keyboard(
self.window_target.p.app.clone(),
self.window_target.p.show_keyboard_on_resume.load(Ordering::SeqCst),
);
},
MainEvent::SaveState { .. } => {
// XXX: how to forward this state to applications?
Expand Down Expand Up @@ -635,6 +641,7 @@ pub struct ActiveEventLoop {
control_flow: Cell<ControlFlow>,
exit: Cell<bool>,
redraw_requester: RedrawRequester,
show_keyboard_on_resume: Arc<AtomicBool>,
}

impl ActiveEventLoop {
Expand Down Expand Up @@ -747,9 +754,45 @@ impl DeviceId {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PlatformSpecificWindowAttributes;

#[cfg(feature = "android-native-activity")]
fn show_hide_keyboard(app: AndroidApp, show: bool) {
use jni::{objects::JObject, JavaVM};
let vm = unsafe { JavaVM::from_raw(app.vm_as_ptr() as _).unwrap() };
let activity = unsafe { JObject::from_raw(app.activity_as_ptr() as _) };
let mut env = vm.attach_current_thread().unwrap();
let view = env
.get_field(
&activity,
"mNativeContentView",
"Landroid/app/NativeActivity$NativeContentView;",
)
.unwrap()
.l()
.unwrap();
let wic = env
.call_method(
&view,
"getWindowInsetsController",
"()Landroid/view/WindowInsetsController;",
&[],
)
.unwrap()
.l()
.unwrap();
let window_insets_types = env.find_class("android/view/WindowInsets$Type").unwrap();
let ime_type =
env.call_static_method(&window_insets_types, "ime", "()I", &[]).unwrap().i().unwrap();
let _ = if show {
env.call_method(&wic, "show", "(I)V", &[ime_type.into()])
} else {
env.call_method(&wic, "hide", "(I)V", &[ime_type.into()])
};
}

pub(crate) struct Window {
app: AndroidApp,
redraw_requester: RedrawRequester,
show_keyboard_on_resume: Arc<AtomicBool>,
}

impl Window {
Expand All @@ -759,7 +802,11 @@ impl Window {
) -> Result<Self, error::OsError> {
// FIXME this ignores requested window attributes

Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone() })
Ok(Self {
app: el.app.clone(),
redraw_requester: el.redraw_requester.clone(),
show_keyboard_on_resume: el.show_keyboard_on_resume.clone(),
})
}

pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
Expand Down Expand Up @@ -888,7 +935,11 @@ impl Window {

pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}

pub fn set_ime_allowed(&self, _allowed: bool) {}
pub fn set_ime_allowed(&self, allowed: bool) {
self.show_keyboard_on_resume.store(allowed, Ordering::SeqCst);
#[cfg(feature = "android-native-activity")]
show_hide_keyboard(self.app.clone(), allowed);
}

pub fn set_ime_purpose(&self, _purpose: ImePurpose) {}

Expand Down
3 changes: 2 additions & 1 deletion src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,8 @@ impl Window {
///
/// - **macOS:** IME must be enabled to receive text-input where dead-key sequences are
/// combined.
/// - **iOS / Android / Web / Orbital:** Unsupported.
/// - **Android:** Enabling IME only summons the soft keyboard, does not enable IME
/// - **iOS / Web / Orbital:** Unsupported.
/// - **X11**: Enabling IME will disable dead keys reporting during compose.
///
/// [`Ime`]: crate::event::WindowEvent::Ime
Expand Down

0 comments on commit 3ad944f

Please sign in to comment.