Skip to content

AnimatedVisualPlayer: Port WinUI implementation - #23889

Open
morning4coffe-dev wants to merge 246 commits into
feature/breakingchangesfrom
agents/animated-visual-player-port
Open

AnimatedVisualPlayer: Port WinUI implementation#23889
morning4coffe-dev wants to merge 246 commits into
feature/breakingchangesfrom
agents/animated-visual-player-port

Conversation

@morning4coffe-dev

Copy link
Copy Markdown
Member

GitHub Issue: closes #23881

PR Type:

✨ Feature

What changed? 🚀

Ports AnimatedVisualPlayer directly from Microsoft WinUI commit 3cae15f0 for the Skia renderer.

  • Aligns playback, lifecycle, fallback content, diagnostics, dynamic sources, animation optimization, and reverse playback with WinUI.
  • Implements the required Composition AnimationController playback-rate, progress, seeking, and commit behavior.
  • Migrates Uno.UI.Lottie to IAnimatedVisualSource3/IAnimatedVisual2 and Composition-driven rendering.
  • Removes the legacy player-driven animated visual path.
  • Adds AVP, Composition, and production Lottie regression coverage.

This targets feature/breakingchanges. The public Uno-only members previously added to IAnimatedVisualSource are removed in favor of the WinUI contract.

PR Checklist ✅

Validation

  • Uno.UI.Composition.Skia build
  • Uno.UI.Skia build
  • Uno.UI.Lottie.Skia build
  • Uno.UI.UnitTests build
  • AnimatedVisualPlayer runtime tests: 27/27 passed
  • Focused Composition/Lottie unit tests: 3/3 passed
  • git diff --check

morning4coffe-dev and others added 30 commits July 8, 2026 19:49
Fixes NoClickablePointException / 0x80070002 (FileNotFound) raised to
out-of-proc UIA clients (FlaUI, WinAppDriver, Narrator) when calling
into an element whose subtree was removed.

- Port CUIAWrapper::Invalidate: providers now expose Invalidate(), which
  disconnects from UIA, cascades to virtual (DataGrid) children, and makes
  every entry point return UIA_E_ELEMENTNOTAVAILABLE via ThrowIfDisconnected,
  instead of the COM-callable wrapper being GC'd out from under a cached
  client proxy. A short-lived strong tombstone keeps the wrapper alive until
  UIA processes the disconnect.
- Wire UIA_ClickablePointPropertyId to AutomationPeer.GetClickablePoint,
  matching CUIAWrapper (VT_EMPTY when (0,0), else client-to-screen).

Fixes #494
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Shift + vertical mouse wheel is repurposed as horizontal scrolling, but
the horizontal branch in ScrollContentPresenter.PointerWheelScroll used
the raw vertical wheel delta without the sign inversion that the vertical
branch applies. As a result wheel-down + Shift scrolled left instead of
right (and wheel-up scrolled right instead of left).

Negate the delta for the Shift case (IsHorizontalMouseWheel == false) so
wheel-down scrolls right and wheel-up scrolls left, matching WinUI and
standard desktop behavior. A genuine horizontal wheel already carries the
correct horizontal sign and is left unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 99c2bedc-ec77-464f-9ccc-33fee5a3a211
AttachSubWindow marshalled an XWindowAttributes buffer into
XChangeWindowAttributes, which expects the differently-laid-out
XSetWindowAttributes. The override_redirect value actually applied came
from whatever bytes were at offset 88 (map_installed), so the intended
override-redirect was never reliably set. Without it, Weston's XWM
(WSLg) reparents the WebView2 GTK toplevel into its own frame window
and never lets it go, leaving the webview invisible.

- Pass a properly-constructed XSetWindowAttributes.
- Set override-redirect on the GTK window right after realization,
  before it is first mapped, so the WM never starts managing it
  (once Weston's XWM manages a window, reparenting it away is not
  reliably possible).
- Warn when the reparent doesn't stick instead of failing silently.

Validated at runtime on WSLg (Ubuntu 24.04): WebView2 samples now
render embedded in the app window; previously the webview window was
held under the "Weston WM" window and never displayed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RunOnGtkThread now propagates exceptions from the GTK idle callback
through the TaskCompletionSource instead of leaving the calling thread
blocked forever, and the post-reparent diagnostic checks XQueryTree's
status (avoiding a spurious warning and XFree on garbage when the
window dies mid-attach) and names the window that kept the native
element.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Use SetWindowValuemask.OverrideRedirect for XChangeWindowAttributes and
GetAwaiter().GetResult() to rethrow original GTK-thread exceptions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Ctrl+Wheel and Ctrl+Plus/Minus now keep the viewport center fixed, using
  the same formula as the pinch gesture.
- Apply the target zoom before validating offsets in Set(), so an offset that
  is only reachable at the new zoom is no longer clamped against the old one.
- Remove the centering offset when reading AnchorPoint back in the scroll
  animation callbacks.
- Keep the zoom range pinned to 1 while ZoomMode is Disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKBgQoAmRmaFoXXZr93iLB
Also covers an offset that is only reachable at the target zoom factor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKBgQoAmRmaFoXXZr93iLB
Keep providers callable until UiaDisconnectProvider returns, check its
HRESULT, and report native disconnect failures without interrupting cleanup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7de737fe-af1e-42b9-ab99-19c5b03d8d96
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7de737fe-af1e-42b9-ab99-19c5b03d8d96
Keep root-level structure changes coarse until UIA has materialized a specific accessible ancestor, avoiding eager automation peer creation across the app.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7de737fe-af1e-42b9-ab99-19c5b03d8d96
- Forward empty-content writes (skip only the null delete sentinel) so a
  truncate-to-empty request is applied instead of being dropped under a
  Success ack.
- Serialize batch finalizations on a per-updater JoinableTask chain so a
  later batch's Debug.ApplyCodeChanges cannot overtake an earlier batch
  still polling workspace readiness.
- Defer the encoding-upgrade close/re-encode/reopen (and drop the redundant
  pre-Save) into finalization; keep an in-memory-only path when
  ForceSaveOnDisk is false. ApplyFileContentAsync now returns the persist
  step for the caller to run inline (single-file) or defer (batched).
@nventive-devops

Copy link
Copy Markdown
Contributor

The build 224270 found UI Test snapshots differences: skia-linux-screenshots: 67, skia-windows-screenshots: 103

Details
  • skia-linux-screenshots: 67 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ClipboardTests.png-dark
    • Examples.png-dark
    • Examples.png
    • BitmapIcon_Foreground.png
    • DisplayInformation.png-dark
    • ElementLevelTheme.png-dark
    • Buttons.png-dark
    • Buttons.png
    • Gamepad_Enumeration.png-dark
    • Image_AnimatedWebP.png
    • ContextRequested.png-dark
    • ContextRequested.png
    • DynamicFont.png
    • Focus_FocusVisual_Properties.png-dark
    • Focus_FocusVisual_Properties.png
    • EllipsemaskingEllipseGrid.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • ButtonClippingTestsControl.png-dark
    • CalendarView_Theming.png-dark
  • skia-windows-screenshots: 103 changed over 2392

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Gamepad_CurrentReading.png-dark
    • ColorPickerSample.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • Image_AnimatedWebP.png-dark
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • DropDownButtonPage.png-dark
    • DropDownButtonPage.png
    • Examples.png
    • ExpanderColorValidationPage.png-dark
    • Gamepad_Enumeration.png-dark
    • Image_Stretch_None.png-dark
    • Image_UseTargetSize.png-dark
    • Buttons.png-dark
    • Buttons.png
    • DisplayInformation.png-dark
    • ImageBrushInList.png
    • Image_UseTargetSizeLate.png-dark

ajpinedam and others added 19 commits July 27, 2026 14:12
- Apply the in-memory content immediately on the encoding-change path and defer
  only the close/re-encode/reopen, so neither VS nor the dev-server ack observes
  stale content during the readiness wait.
- Trigger hot reload for delete-only batches: FinalizeAsync now falls back to the
  base finalization (standalone ForceHotReloadIdeMessage), since no
  UpdateFileRequestIdeMessage carries the trigger and the NoChanges auto-retry only
  re-fires after an EnC attempt reports NoChanges.
- Wait for workspace readiness before the deferred persists even when the explicit
  hot-reload trigger is disabled: a deferred save / encoding rewrite can itself kick
  off "hot reload on save", which must not evaluate an intermediate snapshot when the
  batch created files.
- Persist the hot-reload info file eagerly only for write batches; delete-only batches
  persist and trigger through base.FinalizeAsync, removing a double-persist and a
  now-inaccurate comment.
- Use the vsEPReplaceTextOptions enum instead of a magic flags literal; reword the
  readiness log (no compilation happens there); grammar fix.
- Marshal ApplyFileContentAsync to the VS UI thread before touching DTE: the IDE-channel
  message pump dispatches on a background thread, so the synchronous DTE access could hit
  COM thread-affinity failures.
- Log (instead of silently swallow) an unexpected fault on the finalization chain.
- ApplyFileContentAsync is now internal (matches the internal sealed type); name the 250 ms
  file-system settle delay; replace the lingering TODO with the full-content contract; annotate
  the completed-sentinel finalization head.
- Docs: base FileUpdater.ApplyEditsAsync no longer implies ordered application (it is Task.WhenAll);
  spec now states empty content is valid (truncate) and only null is the delete sentinel.
feat(devserver): Add Kimi Code as MCP setup client
fix: re-create unmaterialized Frame content on hr element update
fix(GLCanvasElement): blank canvas on physical iOS devices — probe GLES BGRA readback support
…age-writes

fix(wasm): Stop buffering whole files in tab memory on StorageFile writes
…tefile

feat(hr): batch IDE file updates and gate EnC on workspace readiness
…scope

fix(hr): scope the blocked-compilation audit to the pass change-set (spec 054)
@github-actions github-actions Bot added platform/wasm 🌐 Categorizes an issue or PR as relevant to the WebAssembly platform platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform platform/ios 🍎 Categorizes an issue or PR as relevant to the iOS platform area/code-generation Categorizes an issue or PR as relevant to code generation kind/documentation area/sdk Categorizes an issue or PR as relevant to the Uno.Sdk platform/x11 🐧 Categorizes an issue or PR as relevant to X11 labels Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 224644 found UI Test snapshots differences: skia-linux-screenshots: 88, skia-windows-screenshots: 99

Details
  • skia-linux-screenshots: 88 changed over 2392

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • Examples.png
    • ExpanderColorValidationPage.png-dark
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
    • ImageSourceUrlMsAppDataScheme.png
    • Image_UseTargetSizeLate.png-dark
    • Image_UseTargetSizeLate.png
    • Image_Margin_Large.png-dark
    • Image_AnimatedWebP.png-dark
    • Basics Pivot Test.png
    • Buttons.png-dark
    • ButtonClippingTestsControl.png-dark
    • Buttons.png
    • ButtonClippingTestsControl.png
    • DisplayInformation.png-dark
    • ColorPickerSample.png
    • DataTransferManager.png
    • Gamepad_Enumeration.png-dark
  • skia-windows-screenshots: 99 changed over 2392

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • Gamepad_CurrentReading.png-dark
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • Focus_FocusVisual_Properties.png-dark
    • Buttons.png-dark
    • Buttons.png
    • ClipboardTests.png
    • Examples.png
    • ExpanderColorValidationPage.png-dark
    • ClipboardTests.png-dark
    • Image_UseTargetSize.png-dark
    • ContextRequested.png-dark
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
    • ImageIconPage.png-dark
    • ImageIconPage.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/automation Categorizes an issue or PR as relevant to project automation area/build Categorizes an issue or PR as relevant to build infrastructure area/code-generation Categorizes an issue or PR as relevant to code generation area/sdk Categorizes an issue or PR as relevant to the Uno.Sdk area/skia ✏️ Categorizes an issue or PR as relevant to Skia kind/documentation platform/android 🤖 Categorizes an issue or PR as relevant to the Android platform platform/ios 🍎 Categorizes an issue or PR as relevant to the iOS platform platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform platform/wasm 🌐 Categorizes an issue or PR as relevant to the WebAssembly platform platform/x11 🐧 Categorizes an issue or PR as relevant to X11

Projects

None yet

Development

Successfully merging this pull request may close these issues.