Skip to content

feat(ui-app): give web_panes the window discriminator build_window has - #456

Closed
phall1 wants to merge 2 commits into
vercel-labs:mainfrom
phall1:upstream/web-panes-window-id
Closed

phall1 wants to merge 2 commits into
vercel-labs:mainfrom
phall1:upstream/web-panes-window-id

Conversation

@phall1

@phall1 phall1 commented Sep 19, 2026

Copy link
Copy Markdown

Depends on the secondary-window chrome PR (first commit on this branch).

web_panes were not keyed by window the way build_window is, so a second window could not host its own web pane.

phall and others added 2 commits September 19, 2026 19:28
…creen verb

Two things a multi-window terminal app cannot do without.

=== A SECONDARY WINDOW CAN PAINT ITS TERMINALS ===

`rebuild` runs the app's `chrome.build` through `installChromeDisplayList`
— the path that produces every terminal cell. `rebuildWindowSlot`, the
secondary-window path, instead published the widget layout and emitted
with `WithChrome(.{})`: a chrome prefix of ZERO. So a second window
opened, laid out correctly, drew its tab strip, its split divider and
its widget bounds, and painted no cells at all. `ChromeOptions.build`
also took no window label, so even reaching it could not have helped —
it could not know which window it was painting.

- `ChromeOptions.build_window` is the per-window builder, taking a
  `ChromeContext` (canvas label, window id, that window's size, tokens,
  is_main). A struct rather than more parameters so the next thing a
  window needs to know does not break every caller again.
- `installChromeDisplayList` is parameterized by window — label, size,
  and the tree-currency flag — instead of reading the main canvas's.
- `rebuildWindowSlot` takes that branch, and so do per-window terminal
  sizing (`applyTerminalLayout`) and web panes, which were also
  main-canvas-only.
- `handleWindowSlotFrame` calls `on_frame` with the slot's own
  `gpuSurfaceFrame`, so each window has a viewport/PTY pump.

ADDITIVE: `build` is untouched and still works. The slot path is gated
on `build_window` being set, not merely on `chrome` — a builder that
cannot name a window would paint the MAIN window's content into a
secondary one, which is a different wrong answer, not a fix. An app that
does not migrate sees no change. Migration is one line:

    .build = view.buildChrome,
    // becomes
    .build_window = myBuildWindowChrome,   // (model, builder, context)

Verified by running it: a scratch `windows_fn`/`window_view` spike in the
consuming app, built against this commit, opened a second window and
BOTH windows painted live zsh prompts simultaneously — read from the two
automation screenshots. The spike was reverted.

Also fixed on the way: the install path re-emitted with a zero chrome
prefix right after `rebuildWindowSlot`, which would have erased the
chrome it had just installed.

=== THE FULLSCREEN VERB ===

`PlatformServices` had focus/close/minimize/show and no way to enter or
leave fullscreen, so an app could be told it was fullscreen and never ask
to be. Worse, `WindowState.fullscreen` existed but nothing ever filled
it — even the window-state store persisted a constant false.

- `set_window_fullscreen_fn` on `PlatformServices`, `Runtime.setWindowFullscreen`,
  `Effects.setWindowFullscreen(label, bool)` and `toggleFullscreenWindow`.
  SET rather than toggle so the call is idempotent and an app can restore
  a remembered layout without computing parity; macOS compares the style
  mask and only calls `toggleFullScreen:` when it differs.
- The READ half now exists: `WindowInfo.fullscreen`, filled from the
  window's style mask on every macOS frame emit, so a transition the USER
  started from the green button reports exactly like one the app asked
  for. `WindowInfo.state()` finally carries it into `WindowState`.

Chose (a) over (b), deliberately. (b) — appending the stock Enter Full
Screen item when an app supplies custom menus — is a real bug, but the
fix changes "you supplied a menu bar" from "you own it" to "you own it
plus items we inject", which is the wrong default for a framework whose
doctrine is explicitness, and it leaves an app still unable to drive
fullscreen from anything but a menu item it does not control. With (a)
in place a custom-menu app binds its own item in one line, and the
capability also serves shortcuts, buttons, and launch-state restore. (b)
remains worth doing as an opt-outable documented policy; it is not this
commit.

Suite: 2979 pass / 14 skip / 2993 total.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ChromeOptions.build_window` takes a `ChromeContext` naming the window it
is painting; `Options.web_panes` took only the model. But panes are
reconciled PER WINDOW -- `applyWebPanes` runs from the main rebuild, from
every secondary window slot's rebuild, and from the presented-frame
ride-along -- so a hook that could not be told which window it was being
asked about had no choice but to answer with the whole app's pane set
every time.

A webview belongs to exactly one window. Every OTHER window's rebuild
therefore resolved that pane's anchor against a widget tree that does not
contain it and logged

    webview pane '<name>': no canvas widget carries semantics label ...

Behaviour was never wrong (the pane is found and snapped in the window
that owns it), but the warning fired on every rebuild of every other
window, which is the kind of noise that trains people to stop reading the
log.

Pass the same `ChromeContext`, built the same way `installChromeDisplayList`
builds it, so an app switches on one context shape whichever per-window
hook it implements: return the panes this window owns, and 0 for a window
that hosts none.

Changed in place rather than added alongside, unlike the `build` ->
`build_window` migration: `build` is a required field that every chrome
app already implemented, while `web_panes` is optional and its every
in-repo implementor is updated here (the ui-app preview test, and the
canvas-preview, workbench, and split-collapse examples). One hook with a
context beats two hooks with a precedence rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 19, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@phall1

phall1 commented Sep 20, 2026

Copy link
Copy Markdown
Author

This is stacked on the secondary-window chrome PR, so it isn't a focused diff on its own.

Closing; will reopen once it's smaller or split.

@phall1 phall1 closed this Sep 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