Skip to content

feat: overlay cols/rows sizing, anchor positioning, and canvas read-back#281

Closed
umputun wants to merge 20 commits into
masterfrom
overlay-anchor-sizing
Closed

feat: overlay cols/rows sizing, anchor positioning, and canvas read-back#281
umputun wants to merge 20 commits into
masterfrom
overlay-anchor-sizing

Conversation

@umputun

@umputun umputun commented Jul 23, 2026

Copy link
Copy Markdown
Owner

adds precise sizing and positioning to floating session overlays, driven over the control channel.

Sizing. session overlay open/resize gain --cols N --rows M to size an overlay to an exact terminal grid (from the surface cell metrics, with a px-to-point conversion for Retina), as an alternative to the uniform --size-percent. An oversized request clamps to the whole cells that fit.

Positioning. --anchor <pos> places a floating overlay at one of nine spots (top-left through bottom-right, default center). Every floating overlay is inset by a uniform one-line-height safe-area margin on all four sides, so a full-width band is inset left/right the same as top/bottom.

Read-back on tree. The session node now reports the overlay's requested grid (overlayCols/overlayRows), the realized grid after clamping (overlayColsApplied/overlayRowsApplied), the overlayAnchor, and the terminal content area (canvasCols/canvasRows) so a script can size an overlay as a fraction of the canvas. For a top band at 30% height: read canvasCols/canvasRows, then overlay open <cmd> --cols $canvasCols --rows $((canvasRows*30/100)) --anchor top.

Behavior change. overlay open --size-percent now errors on an out-of-range value instead of silently clamping, matching resize.

no new control commands (both capabilities ride the existing session.overlay.open/resize), so the command count is unchanged, and overlay state stays live-only. The host-free sizing, anchor, and validation logic lives in agtermCore (OverlayLayout, OverlayArgs) with the app target as a thin adapter; the agent skill, site/commands.html, site/docs.html, README.md, and .claude/rules/control-api.md are updated to match.

covered by host-free unit tests and XCUITest e2e, including an in-overlay stty size grid check and panel-frame margin assertions.

umputun added 20 commits July 23, 2026 00:04
Copilot AI review requested due to automatic review settings July 23, 2026 15:58
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying agterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8729b28
Status: ✅  Deploy successful!
Preview URL: https://03d980f1.agterm.pages.dev
Branch Preview URL: https://overlay-anchor-sizing.agterm.pages.dev

View logs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@umputun umputun left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

found 4 blocking issues and 2 nits.

blocking

  1. agterm/Control/ControlServer.swift:574 reads canvasCols/canvasRows from the currently hosted Ghostty surface. Dashboard and terminal zoom reparent that surface and can change its frame or font, while a control-opened overlay still targets the normal detail pane. tree can report dashboard-cell or zoom-layer dimensions instead of the overlay canvas. Keep the normal detail canvas measurement separately and use it for read-back; add dashboard and zoom regression cases.

  2. agtermCore/Sources/agtermCore/OverlayLayout.swift:144 sums two complete split-surface widths and divides by one cell width. Both widths include terminal padding, but a hypothetical full-width overlay has only one padding allocation, so the extra padding can turn into one or more columns and violate the documented "never over-reports" contract. Subtract one primary-derived horizontal remainder before flooring and add a nonzero-padding boundary test.

  3. agtermUITests/ControlOverlaySplitUITests.swift:925 waits only for requested overlayCols/overlayRows after a percent-to-cells resize. Those fields update synchronously, so the test can pass while overlayColsApplied/overlayRowsApplied remain stale. Poll until the applied grid converges after resize and compare it with a new stty size observation.

  4. agtermUITests/ControlOverlaySplitUITests.swift:783 exercises canvas read-back only without a split. The visible-split and secondary-pane-maximized branches in sessionCanvasGrid have no end-to-end coverage, and the unit tests cannot verify surface selection or live libghostty widths. Add UI cases for both branches and assert the reported canvas against an overlay realized from that grid.

nits

  1. agtermCore/Sources/agtermCore/OverlayLayout.swift:14 still says OverlayAnchor maps to SwiftUI Alignment. The implementation now computes an origin in panelRect and uses a constant top-leading container with padding. Update the comment.

  2. agtermCore/Sources/agtermCore/OverlayArgs.swift:6 exports OverlaySizeParse, OverlayAnchorParse, OverlayArgs.Command, parseSize, and parseAnchor, but production code uses only the public resolvers. Keep the intermediate parser surface internal or private; the tests already use @testable import.

@umputun

umputun commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

after careful consideration, I decided to drop this experiment and won't merge it.

the functionality has real but very narrow use cases. I wanted exact overlay sizing based on the actual terminal content size instead of a percentage. The implementation adds too much complexity for that benefit, especially around cell metrics, split and reparented layouts, state read-back, and UI testing.

@umputun umputun closed this Jul 23, 2026
@umputun
umputun deleted the overlay-anchor-sizing branch July 23, 2026 19:46
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.

2 participants