Skip to content

Stop toolbar taps from resummoning the dismissed keyboard (#200) - #206

Merged
Renakoni merged 2 commits into
mainfrom
fix/toolbar-ime-200
Aug 13, 2026
Merged

Stop toolbar taps from resummoning the dismissed keyboard (#200)#206
Renakoni merged 2 commits into
mainfrom
fix/toolbar-ime-200

Conversation

@Renakoni

@Renakoni Renakoni commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes #200 — toolbar taps no longer resummon a keyboard the user just dismissed.

The chain, established on API 35

  1. Dismissing the IME with Back does not blur Muya: CDP still reports the editor as document.activeElement.
  2. Toolbar controls deliberately prevent pointer/mouse defaults so formatting taps do not steal focus while typing.
  3. Android Chromium re-shows the IME after a page-consumed tap when an editable still owns focus.
  4. The panel-menu selection replay can also focus the editable through Selection.addRange().

Before this PR, expand, collapse, the panel switcher, and its options all reproduced the unwanted keyboard return. The API 35 device matrix verified that those navigation taps stay keyboard-free after the guard, while expanding with the IME already open preserves focus and the keyboard.

Implementation

  • A capture-phase toolbar pointerdown guard blurs editor-owned focus only when the IME is explicitly known to be hidden. Navigation taps then have no focused editable to resummon the keyboard for; edit commands restore their caret/focus through their existing Muya paths.
  • Android now provides the authoritative state from WindowInsetsCompat.Type.ime() through the existing AndroidSelection bridge. It publishes retained imeVisibilityChanged events and an initial getImeVisibility() snapshot. Listener-first installation plus an event-version gate prevents a late snapshot from overwriting a newer event.
  • Floating keyboards and rotation no longer depend on viewport geometry: native IME insets remain authoritative even without adjustResize.
  • Non-native/browser environments keep the viewport estimator as a fallback, now with unknown | hidden | visible states. Its first sample and every post-rotation sample are unknown; unknown means no intervention, never blur.
  • The panel-menu selection replay runs only while the editor already owns focus, so it cannot undo the guard.

Verification

  • Web unit suite: 83 files / 699 tests green; estimator coverage includes first-sample uncertainty, keyboard-sized shrink/recovery, sub-threshold changes, rotation with the IME already open, in-place baseline growth, and no-resize floating-keyboard behavior.
  • Mobile toolbar WebView e2e: 40/40 green. New native-bridge cases verify:
    • a visible no-resize floating keyboard preserves editor focus;
    • hidden-IME formatting and undo/redo each execute the capture blur and then restore editor focus from a collapsed caret;
    • a hidden-IME table structure command follows the same blur/restore contract.
  • vue-tsc -b, production build, focused ESLint, Android JVM tests, Java compilation, and assembleDebug all pass locally.
  • The previous API 35 device matrix covered the real soft-keyboard navigation behavior. No ADB device was attached for the final d131e7e follow-up; current-head GitHub Web Quality, Android Connected Tests, and Android Debug Build were triggered on push.

Chain, established on device: dismissing the IME with Back leaves the
Muya host FOCUSED; every toolbar control prevents pointer defaults so
taps never move focus; and Android Chromium re-shows the keyboard for
any page-consumed tap while an editable holds focus. Expand/collapse,
the panel switcher, its menu options - every navigational tap brought
the keyboard back.

- One capture-phase pointerdown hook on the toolbar root: when the IME
  reads hidden, strip editor-owned focus before the tap completes -
  Chromium then has nothing to resummon the keyboard for. Edit commands
  restore focus themselves through the restore-range machinery, so
  their keyboard behavior is unchanged; with the keyboard up the guard
  stands down and typing workflows keep focus exactly as before.
- The panel-menu selection re-apply now runs only while the editor owns
  focus: addRange() into an editable FOCUSES it on Chromium, which
  resummoned the keyboard right after the guard had avoided it (device-
  proven); the caret handle it hides only exists for a focused editable
  anyway.
- IME visibility is estimated from adjustResize window geometry: height
  notably below the tallest seen for the orientation reads as visible,
  baselines reset on rotation. Estimation errors lean conservative -
  "visible" means "do not interfere" - so split-screen or a floating
  keyboard degrade to today's behavior, never to closing a keyboard
  mid-typing.
- The panel-menu e2e contract test now covers both states: keyboard up
  (viewport shrunk) keeps focus and selection; keyboard down drops
  focus while the selection survives for stats and restore-ranges.

Device matrix (API 35 emulator, real soft keyboard enabled): expand,
collapse, panel switcher, and menu options all keep a dismissed
keyboard dismissed; with the keyboard up, expanding keeps it up, the
panel opens, and focus stays in the editor. The earlier false regression
came from the emulator hardware-keyboard accessory bar (mInputShown=true
with no panel); show_ime_with_hard_keyboard=1 restored real geometry.
@Renakoni
Renakoni merged commit 0346552 into main Aug 13, 2026
7 checks passed
@Renakoni
Renakoni deleted the fix/toolbar-ime-200 branch August 13, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Toolbar expand/collapse taps resummon the dismissed soft keyboard

1 participant