Sitelet https://github.com/unoplatform/uno/pull/25028
Skip to content

perf(macos): build the accessibility tree when a client first asks for it - #25028

Open
ramezgerges wants to merge 1 commit into
unoplatform:masterfrom
ramezgerges:dev/rara/macos-a11y-on-demand
Open

ramezgerges wants to merge 1 commit into
unoplatform:masterfrom
ramezgerges:dev/rara/macos-a11y-on-demand

Conversation

@ramezgerges

Copy link
Copy Markdown
Contributor

GitHub Issue: closes #25027

PR Type:

🔄 Refactoring (performance; no API changes)

What changed? 🚀

On macOS, a window's native accessibility tree is now built the first time an accessibility client queries the window, instead of at startup. Until then the bridge stays idle.

  • Native (UnoNativeMac): the window's accessibilityChildren, accessibilityFocusedUIElement and accessibilityHitTest first call uno_accessibility_ensure_tree. The first time, that invokes a new "tree requested" callback; a treeRequested flag on the per-window context makes it once per window. These are the entry points every client uses first: VoiceOver, Switch Control, Accessibility Inspector, UI automation.
  • Managed (MacOSAccessibility): IsAccessibilityEnabled is false until a client has asked. All existing guards in the bridge and in SkiaAccessibilityBase therefore skip their work: no tree, no uno_accessibility_update_frame or _visibility per moved visual, no structure notifications. The callback marks the window as requested and builds the tree synchronously, so the client's first query already gets the root element. The host provides the root element through RootElementProvider.
  • If the window isn't activated yet when the client asks, the existing activation path builds the tree, now that the bridge is enabled.

Once built, the tree is kept up to date as before.

Measurements

Apple M2, macOS 15.7.1, Skia desktop, Release, fully optimized (DOTNET_TieredCompilation=0). This uses the Perf_TreeGridParity sample from #24972: a virtualizing 10,000 × 64 text grid, timed as the operation plus UpdateLayout. Builds were interleaved over 3 rounds, swapping only Uno.UI.Runtime.Skia.MacOS.dll and libUnoNativeMac.dylib. "Bridge disabled" skips creating the bridge at all and is shown as the floor.

Operation before this PR bridge disabled change
Visible-column resize 2.73 ms 1.45 ms 1.66 ms −46%
Distant diagonal scroll 3.78 ms 2.82 ms 2.95 ms −25%
Vertical scroll 1.34 ms 1.07 ms 1.12 ms −20%
Horizontal scroll 0.59 ms 0.48 ms 0.49 ms −16%
Visible-row replacement 0.53 ms 0.44 ms 0.43 ms −13%
Sort 3.10 ms 3.12 ms 2.62 ms ~ (noisy)

The "Accessibility tree initialized" log line appears in every run before this change and in none after it, since no client was running.

Tests

  • New Given_MacOSAccessibilityOnDemand.When_No_Client_Queried_Then_Tree_Is_Built_On_First_Query. A new window's bridge is idle: not enabled, no tree. Sending accessibilityChildren to its NSWindow, as a client would, enables it, builds the tree, and already returns the root element.
  • Given_MultiWindowAccessibility asserted that each window's accessibility is enabled from the start. On macOS it now makes the same client query first (a no-op on Win32).
  • On the Mac, all 173 Windows_UI_Xaml_Automation runtime tests pass; the 102 skipped are for other platforms.
  • Not covered here: a real external client. macOS refuses accessibility queries from a process without the Accessibility permission, which an ssh-launched test runner doesn't have. A manual VoiceOver check is welcome.

PR Checklist ✅

🤖 Generated with Claude Code

…r it

The macOS accessibility bridge built the native tree for every window at
startup and kept it in sync on every change, including two native calls and
an ancestor walk for every moved or resized visual, whether or not any
accessibility client was running. The window now asks managed code to build
the tree the first time a client queries its children, focused element or
hit test; until then the bridge stays idle. The first query already sees the
tree, which is built synchronously before the native side answers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform label Oct 5, 2026
@unodevops

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-25028/wasm-skia-net9/index.html

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 237489 found UI Test snapshots differences: skia-linux-screenshots: 120, skia-windows-screenshots: 185

Details
  • skia-linux-screenshots: 120 changed over 2458

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • CalendarView_Theming.png-dark
    • CompositionEffectBrush.png-dark
    • CompositionEffectBrush.png
    • CompositionNineGridBrush_Source_Changes.png-dark
    • CompositionNineGridBrush_Source_Changes.png
    • AutomationProperties_AutomationId.png-dark
    • ButtonClippingTestsControl.png-dark
    • AutomationProperties_AutomationId.png
    • ButtonClippingTestsControl.png
    • Buttons.png-dark
    • ClipboardTests.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • DropDownButtonPage.png-dark
    • Examples.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_Enumeration.png-dark
    • ImageSourceUrlMsAppDataScheme.png-dark
    • ImageSourceUrlMsAppDataScheme.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
  • skia-windows-screenshots: 185 changed over 2458

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • Buttons.png-dark
    • Buttons.png
    • ColorPickerSample.png-dark
    • ColorPickerSample.png
    • CalendarView_Theming.png-dark
    • ClipboardTests.png-dark
    • DeferLoadStrategyWithTemplateBinding.png-dark
    • DeferLoadStrategyWithTemplateBinding.png
    • DisplayInformation.png-dark
    • DoubleImageBrushInList.png-dark
    • DoubleImageBrushInList.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • Focus_FocusVisual_Properties.png-dark
    • Focus_FocusVisual_Properties.png
    • Grid_Multi_Column_Span.png-dark
    • Grid_Multi_Column_Span.png
    • Grid_RowSpan_Auto_WithText.png-dark

@mergify

mergify Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

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

Labels

platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[macOS] Build the accessibility tree only once an accessibility client uses the app

4 participants