1
0
Fork 0
forked from wry/wry
wry/docs/window-animations-testing.md

14 KiB

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

Enabling Multiphase Tests

There is currently no separate user-facing multiphase toggle. To exercise the multiphase planner:

  1. Enable animations with SetAnimationsEnabled.
  2. Set a slow duration with SetAnimationDurationMs, around 400-700ms.
  3. Use tiled layout commands that are wired through State::with_layout_animations.
  4. Use layouts where at least two tiled windows change geometry in the same container layout batch.

The compositor then attempts multiphase planning automatically when the batched layout pass completes. If the planner proves a legal no-overlap sequence, that group uses phased animation. If it cannot prove one, only that motion group falls back to ordinary linear animation.

Good command families for multiphase testing:

  • seat/window move in a tiled direction
  • split changes
  • tab/group operations
  • group-opposite changes
  • equalize
  • move-tab
  • mono enter/exit
  • command-driven window resize

These paths should not be used as evidence of multiphase behavior:

  • tile-to-float and float-to-tile, which deliberately use linear animation
  • command-driven floating move/resize, which may animate but can overlap
  • pointer or tablet drag/resize, which should not animate
  • spawn-in and spawn-out, which are always linear
  • cross-output or cross-scale movement, which should snap
  • layer-shell, overlay, override-redirect, and fullscreen map/unmap paths

Useful debug signal:

  • falling back to linear layout animation for group ... means the group entered the multiphase gate but the planner rejected it. That is acceptable for unsupported patterns, but unexpected for the supported swap/extraction cases below.

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:

[ A | [ B
        C ] ]

Then move B out so the target is:

[ 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

This case is easiest to prove with the planner tests because Wry currently has few user commands that create a same-batch move for one tiled window and an independent resize for another. The canonical geometry is:

start:  A = (0,0)-(80,80)      B = (200,0)-(280,80)
target: A = (40,0)-(120,80)    B = (200,0)-(280,120)

A moves horizontally while B scales vertically. The windows are far enough apart that the mixed phase is provably non-overlapping.

To exercise the current proof directly, run:

cargo test animation::multiphase::tests::mixed_single_phase_accepts_move_and_scale_when_proven

For visual/manual testing, use any command sequence that can produce the same shape in one layout batch: one window changes only x-position, and a separate, non-overlapping window changes only height.

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

A fallback here is acceptable if no normal user command can create this geometry; the planner test above is the authority for the mixed-action rule.

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

Commit:
Build:
Outputs/scales:
GPU/session:
Animation config:

Passed:
- 

Known-limit observations:
- 

Failures:
- case:
  app:
  layout:
  expected:
  actual:
  reproducible:
  logs: