Skip to content

Restore native input focus after attaching a file - #9544

Open
malmstein wants to merge 1 commit into
developfrom
fix/david/native-input-focus-after-attachment
Open

Restore native input focus after attaching a file#9544
malmstein wants to merge 1 commit into
developfrom
fix/david/native-input-focus-after-attachment

Conversation

@malmstein

@malmstein malmstein commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Task/Issue URL: https://app.asana.com/1/137249556945/project/1157893581871903/task/1217314046325775
Tech Design URL (if applicable):
API Proposals URL(s) (if applicable): None

Description

Attaching an image or a file to the native input left the input field unfocused, so the user had to tap it again before they could send the message.

The attachment menu hands control to the camera or the file picker and the result comes back through the ValueCallback built in AttachmentView. That callback added the attachment to state and stopped there, so nothing ever returned focus or the keyboard to the input field. Cancelling the picker left the same state.

This adds restoreInputFocus() to NativeInputHost and calls it from both picker callbacks, so it covers image attachments, camera capture, file attachments, and the cancelled-picker case. NativeInputModeWidget implements it by posting requestInputFocus() and showKeyboard(): picker results are delivered in onActivityResult, which runs before the host activity resumes, and the IME ignores a show request until then, so the post is what makes the keyboard actually come back.

Both attachment entry points route through AttachmentView, so the browser omnibar and the contextual sheet are both fixed by the same two call sites. Edit mode is unaffected, the attach button is hidden there.

No unit test: the existing tests around this widget cover pure functions extracted out of the views, and there is no branching logic here to extract. The behaviour worth testing is IME timing, which a JVM test cannot exercise.

Steps to test this PR

Attaching an image from the omnibar

  • Open the browser and tap the omnibar so the native input is focused and the keyboard is up
  • Tap the attach button, choose Attach photo, and pick an image
  • Check the thumbnail appears AND the input field is still focused with the keyboard up
  • Type a prompt without tapping the field first and send it

Camera capture

  • Repeat the above choosing Take photo instead, and confirm focus returns after the capture

Cancelling the picker

  • Tap the attach button, open the picker, then press back without picking anything
  • Check the input field is focused again with the keyboard up

Contextual sheet

  • Open Duck.ai from a page so the contextual input is shown
  • Attach an image and confirm focus and the keyboard return the same way

UI changes

Before After
No UI changes No UI changes

Note

Low Risk
Small UI-focus change on the native input host after pickers; no auth, data, or attachment-handling logic changes. IME timing is the main behavioral risk and is not unit-tested.

Overview
After attaching (or cancelling) a photo, camera capture, or file, the native chat input now gets focus and the keyboard back so users can type and send without tapping the field again.

Adds restoreInputFocus() on NativeInputHost. Image and file picker callbacks in AttachmentView always call it. NativeInputModeWidget posts requestInputFocus() plus showKeyboard() so the IME show runs after onActivityResult and the activity resume. Same path covers omnibar and contextual sheet.

Reviewed by Cursor Bugbot for commit ec34207. Bugbot is set up for automated code reviews on this repo. Configure here.

The attachment picker callbacks added the attachment to state but never
returned focus or the keyboard to the input field, so the user had to
tap the field again before they could send the message. Cancelling the
picker left the same dead-focus state.

Add restoreInputFocus() to NativeInputHost and call it from both picker
callbacks in AttachmentView. The widget posts the request because picker
results are delivered in onActivityResult, before the host activity
resumes, and the IME ignores a show request until then.

https://app.asana.com/1/137249556945/project/1157893581871903/task/1217314046325775

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@malmstein
malmstein marked this pull request as ready for review August 20, 2026 16:54
@malmstein malmstein assigned malmstein and unassigned malmstein Aug 20, 2026
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.

1 participant