Repository navigation
Conversation
| host.requestFocus(); | ||
| } | ||
| InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); | ||
| imm.hideSoftInputFromWindow(f != null ? f.getWindowToken() : host.getWindowToken(), 0); |
There was a problem hiding this comment.
[P2] Preserve keyboard ownership when falling back to the host token
If a sibling native EditText or another NshView owns focus in the same Activity, host.findFocus() is null but both share the window token, so this fallback dismisses that other editor's keyboard. Check for a focused editor outside this surface before using the fallback, and cover that embedding case alongside removal of this surface's input.
Reviewed by ChatGPT on behalf of @huacnlee.
There was a problem hiding this comment.
Right: hideSoftInputFromWindow hides the keyboard of whichever view the input method serves in that window, so a native EditText next to the NshView lost its keyboard too. Fixed in febe40e: when nothing in the host has focus, the keyboard is hidden only if the window's focused view isn't an editor outside the host that the input method serves (onCheckIsTextEditor() and imm.isActive()). This matches iOS, which ends editing in the root view and its modals, not in the window.
Tested on an Android 15 arm64 emulator with a local change to DevActivity that puts a focused native EditText above the NshView, plus a fixture that calls Keyboard.dismiss() once that keyboard is up. Before the fix, the keyboard goes down. With the fix, it stays up. keyboard-dismiss.test.tsx still passes on Android and headless. I didn't commit that case as a gallery test because the test host's window holds only the NshView, and a fixture can't add a native view outside it. If you want it covered, I can add a test-only hook for that.
… showed it is gone
… nothing in the host has focus The fallback that hides the keyboard of a removed field used the host's window token, which an embedding app's EditText or another NshView in the same Activity shares, so it hid their keyboard too. It now leaves the keyboard alone when the window's focused view is an editor outside the host that the input method serves.
Description
On Android,
Keyboard.dismiss()leaves the keyboard up once the field that showed it has been removed. That happens whenever a screen changes after typing: a sign-in or search screen submits, the app moves to the next screen and callsKeyboard.dismiss(), and the next screen opens under the keyboard. The docs sayKeyboard.dismiss()"hides the software keyboard" (website/modules/nsh.md).The cause is in
Mounter.command, in the blur command on the root view (id 1): it hides the keyboard only whenhost.findFocus()returns a view inside the host. After the focusedEditTextis removed, nothing in the host has focus, so the call does nothing, while Android keeps the keyboard shown for the window.The fix hides it with the focused view's window token, or the host's when nothing in the host is focused. In that second case it leaves the keyboard up when the window's focused view is an editor outside the host that the input method serves (an embedding app's
EditText, anotherNshView's input), since they share the window token; iOS likewise ends editing only in the root view and its modals, not in the window (nsh-platform-ios/src/mount.rs, read, not run). It still moves focus back to the host, and only when a child had it. The change is 14 lines inMounter.java, plus a regression test (examples/gallery/tests/keyboard-dismiss.test.tsxand its fixture). No API change, no new dependency.How to Test
The fixture has an
Inputand a "Next" button. "Next" removes theInput, as a screen change does, and callsKeyboard.dismiss()100 ms later; a line showskeyboardFrame(). The test types into the field, presses "Next" and waits for "keyboard: down":--target android(Android 15 arm64 emulator)`text:keyboard: down` showing never happened in 5000 ms; on screen: ["Next screen", "Next", "keyboard: up"]The embedding case, a native
EditTextabove theNshViewin the same Activity that has the keyboard when the app callsKeyboard.dismiss(), was checked on the same emulator with a local-only change toDevActivity(not in this PR: the test host's window holds only theNshView, and a fixture cannot add a native view outside it). Without the fix in the second commit the keyboard goes down (logcat: a clientHIDE_SOFT_INPUTat the dismiss); with it the keyboard stays up.CI runs no
--target androidjob, so the Android row is a command for the reviewer to run. The runtime was built withcargo xtask android --release --dev --abi arm64-v8a.Not tested: iOS, which takes a separate path; two
NshViews in one Activity; a physical device; armeabi-v7a and x86_64.Checklist
cargo test --workspace,cargo +nightly fmt --alland clippy (including the Catalyst and Android runs for platform code). (cargo test --workspaceon dde7f77 with this commit and the four other Android fixes of this series: 3260 passed, 0 failed, 43 ignored.cargo xtask clippy-androidpasses on main at 201d780, and this PR changes no Rust. The Java is compiled bycargo xtask android, and there is no Rust forfmtto check)tests/compat/(cargo xtask compat). (No API change.)examples/gallerydemos on iOS and Android (if the change is visible or platform-specific). (The test above, on Android.)