Skip to content

popout: a demo's pointer shows over float, menu and dialog windows - #330

Merged
foxnne merged 1 commit into
backend/viewport-picturefrom
popout/pointer-over-windows
Oct 10, 2026
Merged

foxnne merged 1 commit into
backend/viewport-picturefrom
popout/pointer-over-windows

Conversation

@foxnne

@foxnne foxnne commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #326 (on #324); review those first.

A demo or live tape's pointer was drawn only in the main window. Over a float's OS window, a menu or a dialog, it vanished, so a viewer couldn't see it reach a float's close button, a menu row or a dialog's buttons. Reported by @foxnne.

Why

  • The pointer's layer was the size of the main window. replay.overlay made it a subwindow covering the whole window. Popout gives each OS window the subwindows whose middle is in its part of the frame, so the pointer layer always counted as the main window's.
  • Even placed right, a float's window would have claimed it before a menu or dialog over the float could. Floats are drawn first (windowFrame before menuFrame). Dialogs are made in drawRetained, after the pointer was raised, so they stack above it.

Changes

  • sdk/replay/overlay.zig: the pointer's layer is a small rect round its tip, so its middle is where the pointer is. Drawing is still clipped to the screen the pointer is on (dvui.screenFor), not to that rect. Any dvui app that splits its frame across windows by subwindow middle gets the same behaviour.
  • Popout.overlaysFrame, new, last in endFrame: each subwindow that takes no input (mouse_events false: the pointer and its click ripple, a tooltip) is drawn into the topmost window over its middle. That's a menu's or dialog's window, else a float's. Over none of them, it's left to the main window.
    • windowFrame now leaves such subwindows for this pass, unless they are drawn everywhere (a drag's layer).
    • Carried layers stay the carry window's.
  • viewports.Picture.again (and its stand-in): draws more into a picture already handed over this frame, keeping what's there. present only names the target; the window copies it when the frame ends. begin is now clear plus again.

Verification

  • zig build, test (514/515, 1 skipped), test-integration (358/358), check-web, test-sdk-version and the Windows cross-build pass on macOS.
  • Sandbox, macOS:
    • Pointer in a float: a tape floated the explorer out and moved the pointer onto a file in it. A temporary trace in overlaysFrame (removed before the commit) showed the pointer layer going into the float's window while over it (middle at 200354,388, the float's band). The other input-less layer stayed with the main window.
    • Soak: the soak tape still ends in a passing verdict, with no leaks and nothing logged as an error.
  • Not seen:
    • The menu and dialog windows. The sandbox's menus close on the next frame because it isn't the active app, and this session has no screen-recording permission for screenshots.
    • The drawing itself. The routing is what's verified, not what it looks like.

🤖 Generated with Claude Code

The pointer's layer sits round its tip (replay.overlay), and what takes no input is drawn last into
the topmost window over its middle (Popout.overlaysFrame, viewports.Picture.again).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@foxnne
foxnne merged commit 40d9ffe into backend/viewport-picture Oct 10, 2026
10 checks passed
@foxnne
foxnne deleted the popout/pointer-over-windows branch October 10, 2026 13:04
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