feat(windows): grid and recursive-grid transition animation - #1583
Conversation
The smoothstep easing, the per-cell interpolation and the geometry that decides where a depth change zooms from lived in the Linux cgo backend. Move them into an untagged render/motion package so the Windows backend can drive the same transition from the same arithmetic rather than a copy, and have the Linux backend delegate to it. No behaviour changes.
A recursive-grid depth change on Windows now zooms the cells from where the previous depth left them to where the new one puts them, over recursive_grid.animation.duration_ms and on the same smoothstep curve macOS and Linux use. A goroutine paces the frames and each one is handed to the overlay UI thread through the existing flush path, so painting and presenting stay on that thread and frames the thread has not reached coalesce. A zero duration, or the animation switched off, paints the new depth immediately; any other draw that takes the surface cancels a running transition first. Closes #1562
Greptile SummaryThis PR adds recursive-grid depth-transition animation to the Windows overlay and extracts common easing and geometry calculations for Linux and Windows.
Confidence Score: 4/5The implementation appears safe to merge, with a non-blocking documentation correction needed for the plain Grid capability row. The recursive-grid transition is serialized, cancellable, and coalesces complete frames correctly; the only accepted issue is that the support table claims animation for Windows plain-grid rendering even though that path remains immediate. Files Needing Attention: docs/CROSS_PLATFORM.md
|
| Filename | Overview |
|---|---|
| internal/adapter/overlay/windows/transition.go | Adds a lock-serialized, cancellable frame loop that hands recursive-grid transitions to the Windows UI-thread presentation path. |
| internal/adapter/overlay/windows/features.go | Detects recursive-grid depth changes, builds transition geometry, and shares the complete-frame painter between animated and immediate draws. |
| internal/adapter/overlay/windows/overlay.go | Stores recursive-grid transition history and clears it across surface ownership and lifecycle changes. |
| internal/adapter/overlay/render/motion/motion.go | Extracts platform-neutral easing, rectangle interpolation, and transition-origin calculations without changing reachable Linux behavior. |
| internal/adapter/overlay/linux/overlay_shared_cgo.go | Replaces local transition arithmetic with the shared motion package. |
| internal/adapter/overlay/windows/transition_integration_windows_test.go | Covers duration, settling, disabled and zero-duration behavior, and cancellation by a replacing draw on a real Windows overlay. |
| docs/CROSS_PLATFORM.md | Documents Windows recursive-grid animation support but also incorrectly marks plain Grid transition animation as supported. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Recursive-grid depth changes] --> B[Compute target cells]
B --> C[Resolve origins from prior frame]
C --> D[Windows transition goroutine]
D --> E[Interpolate with shared smoothstep]
E --> F[Queue complete overlay frame]
F --> G[Flush to Windows UI thread]
G --> H[Present newest coalesced frame]
I[Clear, resize, teardown, or another mode draw] --> J[Cancel or forget transition]
J --> D
Prompt To Fix All With AI
### Issue 1
docs/CROSS_PLATFORM.md:949
**Grid support is overstated**
This row now says Windows supports plain-grid transition animation, but the Windows `DrawGrid` path still redraws immediately and clears transition state. Only `DrawRecursiveGrid` gained animation, so this documentation gives users an inaccurate view of plain-grid support.
```suggestion
| **Grid** | Transition animation | ✅ | ✅ | ❌ |
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(windows): grid and recursive-grid t..." | Re-trigger Greptile
| | **Hints** | Label arrow / tail | ✅ NSBezierPath | ✅ Cairo triangle | ✅ sampled triangle, see below | | ||
| | **Hints** | Label placement | ✅ top / center / bottom | ✅ top / center / bottom | ✅ top / center / bottom | | ||
| | **Grid** | Transition animation | ✅ | ✅ | ❌ | | ||
| | **Grid** | Transition animation | ✅ | ✅ | ✅ | |
There was a problem hiding this comment.
This row now says Windows supports plain-grid transition animation, but the Windows DrawGrid path still redraws immediately and clears transition state. Only DrawRecursiveGrid gained animation, so this documentation gives users an inaccurate view of plain-grid support.
| | **Grid** | Transition animation | ✅ | ✅ | ✅ | | |
| | **Grid** | Transition animation | ✅ | ✅ | ❌ | |
Knowledge Base Used: Overlay rendering and presentation
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/CROSS_PLATFORM.md
Line: 949
Comment:
**Grid support is overstated**
This row now says Windows supports plain-grid transition animation, but the Windows `DrawGrid` path still redraws immediately and clears transition state. Only `DrawRecursiveGrid` gained animation, so this documentation gives users an inaccurate view of plain-grid support.
```suggestion
| **Grid** | Transition animation | ✅ | ✅ | ❌ |
```
**Knowledge Base Used:** [Overlay rendering and presentation](https://app.greptile.com/y3owk1n/-/custom-context/knowledge-base/y3owk1n/neru/-/docs/overlay-rendering.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Agreed, and it goes further than Windows: no platform animates plain grid mode, the only depth transition anywhere is recursive grid. The row is removed rather than set to ❌ in 2764816, and the mode coverage table now lists transition animation under recursive grid only.
…indows The macOS zoom is a 120Hz timer and a full redraw like the software paths, so what set it apart was four choices, not the compositor: interpolated edges land on the nearest pixel rather than truncating towards the origin, a keystroke that interrupts a running zoom continues it on a linear curve instead of easing in again, the virtual pointer rides the zoom from where it was to where the new depth puts it, and the progress a frame paints is read once the frame holds the lock. All four now live beside the shared arithmetic and both backends use them. The plain-grid row leaves the transition table: no platform animates a subgrid opening, so the row described nothing.
Description
This PR adds the recursive-grid depth transition animation to Windows. Zooming into a cell, or backing out of one, now animates the cells from where the previous depth left them to where the new depth puts them, on the same ease-in-out curve macOS and Linux use and for the duration the config names. A zero duration, or the animation switched off, paints the new depth immediately, and any other draw that takes the surface (a hints frame, grid mode, a clear, a screen change) stops a running transition first.
The frames are paced by a goroutine and each one is handed to the overlay's UI thread through the existing flush path, so nothing on the keyboard hook's thread waits for pixels and frames that pile up coalesce, the same shape the mouse-action indicator already takes on Windows.
The third commit brings the feel of the Linux and Windows zoom up to macOS. The macOS zoom is also a 120Hz timer with a full redraw, so what set it apart was four choices, and both software backends now make them too: interpolated edges land on the nearest pixel instead of truncating towards the origin, a keystroke that interrupts a running zoom continues it on a linear curve instead of easing in again, the virtual pointer rides the zoom from where it was instead of jumping, and each frame reads its progress once it holds the lock.
Plain grid mode has no depth transition on any platform, so the mode coverage table lists transition animation under recursive grid only. The first commit is a prefactor: the easing and origin geometry move out of the Linux cgo backend into a shared untagged package that both backends now use, with no behaviour change on Linux.
Related Issues
Closes #1562
Config
No options added or changed.
recursive_grid.animation.enabledandrecursive_grid.animation.duration_msnow do on Windows what they do on macOS and Linux, so their platform-support rows read ✅ for Windows and a Windows config that sets them no longer warns at load. Existing configs keep working.Target Platform
Type of Change
feat— New featurefix— Bug fixrefactor— Code restructuring (no behavior change)perf— Performance improvementdocs— Documentation onlytest— Adding or updating testschore— Build, CI, dependencies, toolingCross-Platform Checklist
//go:build darwin)CodeNotSupported) — N/A, this replaces a gap rather than adding a port methodGeneral Checklist
just fmt)just cipasses — N/A, ran the targeted subset instead:just fmt-check,golangci-linton the touched packages,just lint-cross(the Linux container, which also lints the Windows-tagged files),go vetfor windows/amd64 with and without the integration tag,go vetfor linux/amd64 CGO off, andgo testfor config, supportref, architecture and the overlay tree on this hostScreenshots / Recordings
None, no Windows desktop on this host. The behaviour is pinned by an integration test that runs on the windows-latest CI leg with a real overlay window: a depth change animates for at least the configured duration and settles on the new cells, a zero duration or a disabled animation paints immediately, and another draw taking the surface stops the transition.
Additional Context
The Linux backend treats a zero duration as its 50ms default; this backend follows the ticket and paints immediately. The manager resizes the window before every recursive-grid draw, so a resize only forgets the last depth when the window's bounds actually changed, otherwise the first zoom would never happen.