Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
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
1 change: 1 addition & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ changelog entry.
### Added

- Reexport `raw-window-handle` versions 0.4 and 0.5 as `raw_window_handle_04` and `raw_window_handle_05`.
- On Android, `set_ime_allowed` now opens and closes the soft keyboard.

### Removed

Expand Down
41 changes: 39 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,10 @@ impl<T: 'static> EventLoop<T> {
MainEvent::Resume { .. } => {
debug!("App Resumed - is running");
self.running = true;
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 +640,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 +753,33 @@ impl DeviceId {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PlatformSpecificWindowAttributes;

fn show_hide_keyboard_fallible(app: AndroidApp, show: bool) -> Result<(), jni::errors::Error> {
// After Android R, it is no longer possible to show the soft keyboard
// with `showSoftInput` alone.
// Here we use `WindowInsetsController`, which is the other way.
use jni::{objects::JObject, JavaVM};
let vm = unsafe { JavaVM::from_raw(app.vm_as_ptr() as _)? };
let activity = unsafe { JObject::from_raw(app.activity_as_ptr() as _) };
let mut env = vm.attach_current_thread()?;
let window = env.call_method(&activity, "getWindow", "()Landroid/view/Window;", &[])?.l()?;
let wic = env
.call_method(window, "getInsetsController", "()Landroid/view/WindowInsetsController;", &[])?
.l()?;
let window_insets_types = env.find_class("android/view/WindowInsets$Type")?;
let ime_type = env.call_static_method(&window_insets_types, "ime", "()I", &[])?.i()?;
env.call_method(&wic, if show { "show" } else { "hide" }, "(I)V", &[ime_type.into()])?.v()
}

fn show_hide_keyboard(app: AndroidApp, show: bool) {
if let Err(e) = show_hide_keyboard_fallible(app, show) {
tracing::error!("Showing or hiding the soft keyboard failed: {e:?}");
};
}

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

impl Window {
Expand All @@ -759,7 +789,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 +922,10 @@ 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);
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