Add soft-keyboard visibility signal for Android NativeActivity#28
Merged
Merged
Conversation
On a NativeActivity the OS never reports a user-initiated soft-keyboard dismissal (back button, swipe-down gesture, keyboard hide key), and the surface is not resized — so winit fires no event, `ime_active` went stale, and the bottom safe area stayed reserved for a keyboard that was gone. Close the gap with a real Android inset callback: - loki-file-access: `ImeInsetsListener` Java shim + `jni_ime.rs`. It installs a decor-view `OnApplyWindowInsetsListener` (loaded via the app class loader; native callback bound with `RegisterNatives`, so it is independent of the host `.so` name) that reports every IME visibility change. Exposes `install_ime_listener` + `set_ime_visibility_listener`. - blitz-shell: `ime_android` bridge. `notify_ime_visibility_changed` records the new visibility and wakes the event loop; `WindowState::poll` drains it, mirrors `ime_active`, and reuses the existing IME-settle re-sync so the bottom safe area converges to the settled keyboard height (0 on a collapse). - loki-text `android_main`: wires the listener to the bridge. - Build: dex `ImeInsetsListener.java` alongside `FilePickerActivity.java` (build.rs, build-android.sh, build-aab.sh, build-android.ps1). - Docs: patches.md updated (the former "swipe-down not reported" limitation is now closed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9fnSNP4c5E9xNhG7T8jrf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the gap where a
NativeActivityon Android never receives notification when the user dismisses or re-summons the soft keyboard (via back button, swipe-down gesture, or the keyboard's hide key). This leaves the bottom safe area reserved for a keyboard that is gone, and stales theime_activemirror so the next caret tap needlessly re-summons an already-visible keyboard.The fix installs a real Android inset callback (
ImeInsetsListener, a Java shim) on the decor view that fires on every IME visibility transition, readsWindowInsets.Type.ime()visibility (API 30+), and bridges the signal back to the Rust event loop via JNI. The event loop then re-queries the safe area and re-syncsime_active, reusing the existing IME-settle path so the bottom padding converges to the settled keyboard height (0 on a collapse).Key Changes
New Java shim (
patches/loki-file-access/android/ImeInsetsListener.java): ImplementsView.OnApplyWindowInsetsListenerto observe decor-view inset changes and call back into native code on every IME visibility transition (API 30+, no-op below).New JNI module (
patches/loki-file-access/src/platform/android/jni_ime.rs):install_ime_listener(activity_ptr)— loads the shim through the application class loader (native threads see only framework classes), binds the native callback viaRegisterNatives(independent of host.soname), and installs the listener on the UI thread.set_ime_visibility_listener(callback)— registers the closure invoked on every visibility change.ime_insets_changed— JNI callback that fires on the Android UI thread and invokes the registered closure.New blitz-shell bridge (
patches/blitz-shell/src/ime_android.rs):notify_ime_visibility_changed(visible)— called from JNI, records the new visibility and wakes the event loop with aPoll.take_pending()— drained inWindowState::poll, returns the pending visibility change.register(proxy, window_id)— called during window init to record the event-loop target.Integration in blitz-shell (
patches/blitz-shell/src/window.rs):View::init.poll(), mirror intoime_active, and callarm_ime_settle()to re-query the safe area across the keyboard animation.Integration in loki-text (
loki-text/src/lib.rs):loki_file_access::set_ime_visibility_listenertoblitz_shell::notify_ime_visibility_changed.Build system updates (
build.rs,build-android.sh,build-android.ps1,build-aab.sh):FilePickerActivity.javaandImeInsetsListener.javainto a singleclasses.dex.collect_class_files()to handle inner classes (e.g., the anonymousRunnableinImeInsetsListener).Minification config (
android/app/build.gradle.kts): Updated comment to note that both shims are JNI-referenced and must not be minified.Documentation (
docs/patches.md): Added detailed explanation of the user-driven soft-keyboard collapse signal, including the API 30+ requirement and the re-sync path.Implementation Details
v.onApplyWindowInsets), so it does not consume or alter the system's inset handling.FilePickerActivityand, being JNI-referenced, requires minification to stay off (https://claude.ai/code/session_01V9fnSNP4c5E9xNhG7T8jrf