Skip to content

fix(native): keep the composer focused when the iOS keyboard shows - #476

Merged
Makisuo merged 1 commit into
mainfrom
fix/ios-keyboard-focus-loop
Nov 12, 2026
Merged

Makisuo merged 1 commit into
mainfrom
fix/ios-keyboard-focus-loop

Conversation

@Makisuo

@Makisuo Makisuo commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

On the iOS (Rune) app, opening the keyboard made the screen glitch repeatedly.

The view wrapped the page in a keyboard-padding column only while the keyboard was up. Rune names unkeyed elements by their position, so adding the wrapper renamed every element, the focused composer included (#0/document/… became #0/#0/document/…). This made a loop:

  1. Focus dropped.
  2. The keyboard hid.
  3. The wrapper went away and the names changed back.
  4. Repeat.

Fix

  • The wrapper is always built, padded by 0 when the keyboard is down, so element names stay the same.
  • The handler that passes a paste to the composer when nothing is focused moves to that wrapper, which is now the root.

Tests

  • New the_on_screen_keyboard_leaves_the_composer_focused shows the keyboard, hides it and shows it again, and checks the composer stays focused. It failed before the fix and passes now.
  • All 147 host tests pass.
  • On the simulator the on-screen keyboard didn't appear (probably because the simulator was using the Mac's keyboard), so this needs a check on a real device.

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

Summary by CodeRabbit

  • Bug Fixes
    • Preserved composer focus as the on-screen keyboard opens and closes.
    • Paste events are routed through the app window, and page layout now accommodates keyboard coverage consistently.

The view wrapped the page in a keyboard-padding column only while the
keyboard was up. Rune derives unkeyed element ids from their position,
so the wrapper renamed every element, the focused composer included:
focus dropped, the keyboard hid, the wrapper went away, and it looped.

The wrapper is now always built, padded by 0 with the keyboard down,
and the page-level paste handler moves to it as the new root.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@maple-review-bot

maple-review-bot Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 10/10 · safe to merge. Contained to the native host's render tree; the fix rests on Rune's element naming, which only the new Rust test pins and I could not run here.
no findings · tests covered · risk medium

The native page is now always wrapped in the keyboard-padding column, so Rune's element ids stay put as the keyboard moves and the composer keeps focus; the paste handler with nothing focused moves to that wrapper, now the root.

  • view always builds the keyboard column, padded by keyboard.max(0.0)
  • Paste with no field focused is handled on the wrapper, the page's new parent

Before merge

  • Manual · Check the focus loop on a real iOS device: the simulator used the Mac's keyboard, so the on-screen keyboard never appeared

85d59ce · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The native host now keeps the page inside a full-size window as keyboard coverage changes. The window applies non-negative bottom padding and handles paste events. A test checks that keyboard coverage changes do not alter the composer’s focus path.

Changes: Native Host View

Layer / File(s) Summary
Stable window view and focus
apps/native/host/src/render/mod.rs, apps/native/host/src/tests.rs
The page no longer handles paste events directly; the window routes them to send_paste. The view always uses a full-size window and applies bottom padding of max(keyboard, 0). A test checks that composer focus remains unchanged as keyboard coverage changes.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

Merge Risk: Minimal · up to 85d59

The change keeps the composer focused when the iOS keyboard shows or hides by keeping the view structure stable. No concrete merge-blocking risk was found. The author notes that the behavior should still be checked on a real device.

Pre-merge checks: Passed 4

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the main change: keeping the composer focused when the iOS keyboard shows. The raw summary and objectives confirm the change keeps the keyboard-padding wrapper always present (zero pad…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: keeping the composer focused when the iOS keyboard shows. The raw summary and objectives confirm the change keeps the keyboard-padding wrapper always present (zero padding when the keyboard is down) to stop unkeyed element names from changing and dropping focus. The title is specific and matches the changeset, and it follows the conventional commit style.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

Clippy (1.99.1)

Clippy execution failed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2f66b43b-0973-471f-ba4d-c8e58e4e4c60
Commits

Reviewing files that changed from the base of the PR and between 16aa83e and 85d59ce.

Files selected for processing: 2

  • apps/native/host/src/render/mod.rs
  • apps/native/host/src/tests.rs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 73.43% 36182 / 49273
🔵 Statements 72.43% 41144 / 56804
🔵 Functions 61.22% 12995 / 21226
🔵 Branches 60.77% 20505 / 33740
File CoverageNo changed files found.
Generated in workflow #2307 for commit 85d59ce by the Vitest Coverage Report Action

@Makisuo
Makisuo merged commit c585ca8 into main Nov 12, 2026
6 of 8 checks passed
@Makisuo
Makisuo deleted the fix/ios-keyboard-focus-loop branch November 12, 2026 15:31
@maple-review-bot

Copy link
Copy Markdown

Merged with 1 step from "Before merge" still open. If it is done, tick it on the review comment; if not, now is the time.

  • Manual · Check the focus loop on a real iOS device: the simulator used the Mac's keyboard, so the on-screen keyboard never appeared

Thegreatsura pushed a commit to Thegreatsura/hazel that referenced this pull request Nov 13, 2026
Main's HTML renders on iOS (MapleTechLabs#477) and keyboard focus (MapleTechLabs#476) meet the native
islands: frames keep main's own covers, islands their layer-aware placement,
and the iOS shell places both after every frame. Also clears the lint: the
swipe back reads where the chevron leads from the element itself, the shell
installs its controls on a global as the desktop shells install __TAURI__, and
the menus' symbol tables keep their inferred types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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