Skip to content

web: don't read a desktop window resize as a keyboard inset - #1217

Open
MichaelBelousov wants to merge 1 commit into
fizzyedit:mainfrom
MichaelBelousov:web/desktop-keyboard-inset
Open

MichaelBelousov wants to merge 1 commit into
fizzyedit:mainfrom
MichaelBelousov:web/desktop-keyboard-inset

Conversation

@MichaelBelousov

Copy link
Copy Markdown
Contributor

keyboardInset() captured the canvas's rect on every focusin and only cleared it when a keyboard closed. On a desktop no keyboard ever opens, so the rect went permanently stale. A window that shrank after that read as a keyboard covering the space between rest.bottom and the smaller viewport: the app got a phantom inset to lay out above, and the canvas's CSS height got pinned to the focusin-time pixel height. The page could then resize around it forever without the editor noticing the new space, until a resize that grew the window back past the stale rect.

Gate the inset on a device that actually has a soft keyboard: the primary pointer is coarse and never hovers (a phone or tablet). There the behavior is unchanged -- Android's resizes-content pages, the VirtualKeyboard API path and iOS's visual viewport all still satisfy it. One edge: a touch device with a mouse connected has a fine primary pointer, so it loses the inset optimization; its canvas then shrinks with the keyboard as resizes-content intends, and the app lays out in the smaller canvas, which is what the inset path exists to avoid.

Found in an embedder (the graphl IDE in an electron window): focus the editor, shrink the window vertically, then resize the embedder's panel -- the editor stayed at the focusin-time height. Verified fixed there; the same page on a touch profile still gets insets.

Part of #

In plain words

What changes

What you will notice

How we know it works

How this serves fizzy

For agents: technical summary

Goal

What changed and why

How it was verified

  • macOS:
  • Windows:
  • Linux:
  • Web:

SDK impact

  • None
  • Core-only or additive: reaches plugins at the next SDK release
  • Fingerprint moved: recorded in sdk/src/version.zig, sdk_version untouched, PR labelled sdk
  • SDK release: bumps sdk_version, lists the sdk PRs since the last sdk-v* tag

Not done / follow-ups

keyboardInset() captured the canvas's rect on every focusin and only
cleared it when a keyboard closed. On a desktop no keyboard ever opens,
so the rect went permanently stale. A window that shrank after that read
as a keyboard covering the space between rest.bottom and the smaller
viewport: the app got a phantom inset to lay out above, and the canvas's
CSS height got pinned to the focusin-time pixel height. The page could
then resize around it forever without the editor noticing the new space,
until a resize that grew the window back past the stale rect.

Gate the inset on a device that actually has a soft keyboard: the
primary pointer is coarse and never hovers (a phone or tablet). There
the behavior is unchanged -- Android's resizes-content pages, the
VirtualKeyboard API path and iOS's visual viewport all still satisfy
it. One edge: a touch device with a mouse connected has a fine primary
pointer, so it loses the inset optimization; its canvas then shrinks
with the keyboard as resizes-content intends, and the app lays out in
the smaller canvas, which is what the inset path exists to avoid.

Found in an embedder (the graphl IDE in an electron window): focus the
editor, shrink the window vertically, then resize the embedder's panel
-- the editor stayed at the focusin-time height. Verified fixed there;
the same page on a touch profile still gets insets.

This branch was successfully deployed

1 active deployment
bridge — c82280b1 Deployed Nov 15, 2026 by MichaelBelousov via bridge #4909
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