From b1717e2dd822fc7723d4862bd6b0a61255fd91b0 Mon Sep 17 00:00:00 2001 From: atagen Date: Thu, 21 May 2026 21:45:07 +1000 Subject: [PATCH] Add animation manual test plan --- docs/window-animations-plan.md | 2 + docs/window-animations-testing.md | 404 ++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 docs/window-animations-testing.md diff --git a/docs/window-animations-plan.md b/docs/window-animations-plan.md index 16c5a7b6..2a051bec 100644 --- a/docs/window-animations-plan.md +++ b/docs/window-animations-plan.md @@ -165,6 +165,8 @@ Deferred/future polish: Goal: implement Wry's staged no-overlap planner while preserving the rule that windows never overlap. +Manual verification checklist: `docs/window-animations-testing.md`. + Core rules: - Each phase is a discrete animation using the full curve. diff --git a/docs/window-animations-testing.md b/docs/window-animations-testing.md new file mode 100644 index 00000000..2484a71f --- /dev/null +++ b/docs/window-animations-testing.md @@ -0,0 +1,404 @@ +# Window Animations Manual Test Plan + +This is the manual verification checklist for Wry's animation work. Use it after +building a test compositor and booting into a normal graphical session. + +The goal is to catch visual, synchronization, damage, and retained-content +problems that unit tests cannot prove from geometry alone. + +## Setup + +- Build and install the `codex-anims-next` branch. +- Start with animations enabled and a deliberately slow duration, around + `400-700ms`, so phase ordering and damage artifacts are visible. +- Test at least one normal Wayland/XDG app, one Xwayland app if available, and + one fast-updating app such as a terminal running output, a browser animation, + a video, or a GL/Vulkan demo. +- Use visible gaps, borders, titlebars, and rounding. These make clipping and + damage mistakes much easier to see. +- If available, test on both a single-output setup and a multi-output setup. +- If logging is convenient, run with debug logging and keep any multiphase + fallback messages. A fallback is useful evidence, not automatically a bug. + +Relevant internal config hooks: + +- `SetAnimationsEnabled` +- `SetAnimationDurationMs` +- `SetAnimationCurve` +- `SetAnimationCubicBezier` + +Current curve IDs in code: + +- `0`: linear +- `1`: CSS `ease` +- `2`: CSS `ease-in` +- `3` or any other unrecognized value: CSS `ease-out` +- `4`: CSS `ease-in-out` + +## Pass Criteria + +A test passes when: + +- layout, focus, hit testing, and configure behavior use the final logical + geometry immediately +- visible presentation motion is smooth and bounded by the animated frame +- no old pixels, trails, black strips, transparent holes, or stale titlebar + fragments remain after motion +- tiled multiphase movement never overlaps and never moves a single window + diagonally during a phase +- interruption starts changed windows from their current visual rect without + restarting unaffected windows +- drag-driven pointer movement remains direct and does not lag behind the cursor +- cross-output or cross-scale movements snap instead of animating + +Record a failure with: + +- the layout before and after +- whether the window was tiled, floating, mono, XDG, Xwayland, or layer-shell +- whether the app was GPU/dmabuf-backed or likely SHM, if known +- animation duration and curve +- whether the failure was visual overlap, diagonal motion, debris, clipping, + stale content, a missing retained frame, or an incorrect animation trigger + +## Known Current Limits + +These are acceptable unless they produce worse behavior than described: + +- Spawn-out is retained-content-only. If the surface cannot be retained safely, + it should snap out rather than animate an empty frame. +- Async SHM surfaces are not retained yet. GPU/dmabuf-backed app windows are the + primary retained-content path for this phase. +- A dedicated retained-tree scaling/offscreen fallback is deferred. Retained + records currently render through the normal texture and stretch/clamp paths. +- Floats may overlap. The no-overlap invariant is for tiled multiphase motion. +- Linear fallback may overlap. This should be rare for valid tiled layouts, and + the fallback should be scoped to the affected motion group. +- Cross-output and cross-scale movements should not animate yet. + +## 1. Basic Enable/Disable + +1. Disable animations. +2. Move, resize, spawn, close, and toggle floating on a few windows. +3. Confirm all affected windows snap with no delayed presentation state. +4. Enable animations at a slow duration. +5. Repeat the same operations and confirm only eligible paths animate. +6. Disable animations while an animation is in flight. + +Expected: + +- disabling animations clears any in-flight visual state +- no stale damage remains after disabling +- newly enabled animations use the configured duration and curve + +## 2. Spawn-In + +Test newly mapped windows: + +- tiled XDG window +- floating XDG window +- Xwayland window, if available +- fullscreen window +- layer-shell or overlay surface, such as a bar, launcher, menu, notification, + or lock/overlay component, if available + +Expected: + +- newly mapped tiled and floating app windows animate in +- layer-shell, overlay, override-redirect, and fullscreen surfaces do not use + the app-window spawn-in path +- contents stay clipped to the animated frame +- if contents are smaller than the frame during the animation, no empty strips + are visible + +## 3. Spawn-Out + +Close windows from these states: + +- tiled app window +- floating app window +- Xwayland app window +- fast-updating app window +- a likely SHM/simple app, if available + +Expected: + +- retained app content shrinks out after the live node is gone +- there is no black, transparent, or unfilled moving rectangle +- if content cannot be retained, the window snaps out cleanly +- neighboring tiled windows reflow without debris left in the old area + +Hard failure: + +- a destroyed window leaves a moving empty frame +- the last frame shows unrelated newer content +- screen debris remains after the animation completes + +## 4. Linear Tiled Reflow + +Use a slow duration and a non-linear curve, then repeat with linear. + +Cases: + +- open two tiled windows and change split ratio by command +- open three tiled windows and resize the active split repeatedly +- move focus and issue command-driven swaps +- interrupt a resize by issuing another resize before the first completes +- create a layout that forces a linear fallback if possible + +Expected: + +- final layout is usable immediately +- changed windows animate from their current visual rect on interruption +- unaffected windows keep their existing timeline +- linear fallback is visually smooth, even if overlap occurs +- no pointer drag path becomes animated + +## 5. Float Movement And Tile/Float Transitions + +Cases: + +- command-toggle a tiled window to floating +- command-toggle the same window back to tiled +- command-move and command-resize a floating window +- mouse-drag a floating window +- mouse-resize a floating window +- double-click/header pointer path if that is part of the local workflow + +Expected: + +- command-driven tile-to-float and float-to-tile transitions animate linearly +- command-driven floating move/resize animates +- mouse or tablet drag/resize remains direct and tracks the pointer +- pointer/header paths that are intentionally outside the command-animation gate + do not unexpectedly use delayed animation +- retained child content remains clipped during tile/float transitions + +## 6. Multiphase Horizontal And Vertical Swaps + +Horizontal: + +1. Create two horizontally adjacent tiled windows. +2. Swap their positions. +3. Reverse the swap. + +Vertical: + +1. Create two vertically adjacent tiled windows. +2. Swap their positions. +3. Reverse the swap. + +Expected: + +- first phase shrinks into lanes on the orthogonal axis +- second phase moves only horizontally or only vertically +- third phase grows out of lanes +- no phase overlaps windows +- no window moves diagonally +- reverse direction uses the same visual logic in reverse +- titlebars, borders, gaps, and rounded corners remain respected + +## 7. Stack Extraction And Return + +Build this shape: + +```text +[ A | [ B + C ] ] +``` + +Then move `B` out so the target is: + +```text +[ A | B | C ] +``` + +Reverse the operation by putting `B` back into the stack. + +Expected: + +- peer/container space opens first +- `B` waits until there is a legal horizontal or vertical lane +- `B` moves on one axis only +- `B` and the affected peer grow together in the final phase when appropriate +- reversing the operation is visually equivalent in reverse + +## 8. Nested Parent/Child Synchronization + +Create nested split layouts where a parent changes one axis and children change +the other. Use both horizontal-parent/vertical-child and +vertical-parent/horizontal-child variants. + +Expected: + +- parent/container-space axis changes happen before child-axis changes when the + hierarchy metadata gives a deterministic order +- child windows do not visually compose parent and child transforms into + diagonal motion +- any unsupported group falls back as a group rather than partially violating the + one-axis rule + +Hard failure: + +- a child visibly changes width and height in the same phase +- a child moves diagonally because parent and child animation compound +- a child clips outside its animated frame + +## 9. Mixed-Action Phases + +Look for layouts where one window can move on one axis while another window +scales on a different axis in the same proven phase. + +Expected: + +- mixed phases are allowed only when each individual window performs one legal + move or scale on one axis +- no individual window moves diagonally +- no overlap occurs at any point during the phase + +This is easier to confirm with debug fallback logs plus visual inspection. A +fallback here is acceptable if the planner cannot prove the sequence. + +## 10. Mono Mode + +Cases: + +- enter mono mode with several siblings +- exit mono mode +- switch active tabs/windows inside mono +- move a window into mono +- move a window out of mono + +Expected: + +- entering/exiting mono may animate where it clarifies hierarchy change +- active child animates to the mono geometry +- inactive siblings snap invisible +- ordinary tab switches inside mono do not animate +- no hidden inactive sibling leaves debris or stale retained content + +## 11. Interruption And Retargeting + +Use a long duration, then issue commands mid-animation: + +- swap, then reverse before completion +- resize, then resize in the other direction before completion +- move a window out of a stack, then back before completion +- start a multiphase group, then change only one window's destination if a + command sequence allows it + +Expected: + +- affected windows restart from their current visual rect +- unaffected windows do not restart if their destination is unchanged +- a new valid multiphase plan replaces the old plan cleanly +- retained content remains the same frozen content during the retarget +- damage covers old, current, and new visual regions + +## 12. Damage And Clipping Stress + +Use a high-contrast wallpaper/background and high contrast window contents. + +Cases: + +- fast repeated swaps +- repeated spawn-in/spawn-out +- rounded corners with large gaps +- titlebar-heavy layouts +- resize while a terminal is rapidly updating +- move/resize over another window's old location +- run on different output scales if available + +Expected: + +- no trails remain in gaps, borders, or titlebar strips +- rounded corners do not reveal old pixels outside the frame +- contents never draw outside the animated bounds +- final frame exactly matches the steady layout + +## 13. Texture Freezing + +Use fast-updating contents so freezing is obvious. + +Cases: + +- tiled GPU/dmabuf-backed app during reflow +- floating GPU/dmabuf-backed app during command move/resize +- tile-to-float and float-to-tile with dynamic content +- spawn-out with dynamic content +- likely SHM/simple app, if available + +Expected: + +- retained GPU/dmabuf-backed windows freeze visually during animation +- spawn-out uses the last retained content, not a blank or unrelated frame +- undersized contents stretch/clamp to avoid unfilled frame regions +- SHM/unretained surfaces either render live safely or snap where retention is + required + +Record separately: + +- content continues updating during movement +- content freezes but samples the wrong source region +- edges show empty/black strips while scaling +- spawn-out skips because capture was unavailable + +## 14. Cross-Output And Scale Boundaries + +Cases: + +- move a tiled window to another output +- move a floating window to another output +- move between outputs with different scale factors, if available +- move a workspace between outputs, if supported locally + +Expected: + +- movement snaps instead of animating +- no retained content is rendered at the wrong scale +- no stale damage remains on the source output +- destination output renders the final layout immediately + +## 15. Regression Sweep + +After visual tests, return to normal animation duration and curve. + +Repeat: + +- ordinary tiling navigation +- workspace switching +- fullscreen enter/exit +- focus changes +- app launch/close loops +- suspend/resume or VT switch if convenient + +Expected: + +- animation state does not survive across unrelated compositor state changes +- no stuck retained frames +- no persistent high CPU/GPU use after animations stop +- no obvious client throttling after many retained-content animations + +## Summary Result Template + +```text +Commit: +Build: +Outputs/scales: +GPU/session: +Animation config: + +Passed: +- + +Known-limit observations: +- + +Failures: +- case: + app: + layout: + expected: + actual: + reproducible: + logs: +```