Skip to content

[Windows][net11] Make Layout AutomationPeer public + opt-in for screen reader tree - #35909

Closed
kubaflo wants to merge 1 commit into
dotnet:net11.0from
kubaflo:net11.0-35597-public-layout-automationpeer
Closed

[Windows][net11] Make Layout AutomationPeer public + opt-in for screen reader tree#35909
kubaflo wants to merge 1 commit into
dotnet:net11.0from
kubaflo:net11.0-35597-public-layout-automationpeer

Conversation

@kubaflo

@kubaflo kubaflo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

This is the net11.0 version of #35597, rebased onto net11.0.

In addition to the Windows-only opt-in behavior from #35597, this PR actions the .NET11.0 TODO by making MauiLayoutAutomationPeer public (class and constructor) and adding the required net-windows PublicAPI entries for the type, constructor, and protected overrides.

This supersedes #35597 for net11.0.

Validation

  • Static verification on macOS: MauiLayoutAutomationPeer is public partial, its constructor is public, and the 6 protected overrides match the 6 override Microsoft.Maui.Platform.MauiLayoutAutomationPeer.* entries in src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt.
  • This change is Windows-only. Windows CI must confirm the PublicAPI analyzer results (RS0016/RS0017), since net-windows cannot be built locally on macOS.

…et11)

Net11.0 version of dotnet#35597 (follow-up to dotnet#35562). Targets net11.0 so the new
public API can land, and actions the deferred ".NET11.0" TODO by making
MauiLayoutAutomationPeer public instead of internal.

- MauiLayoutAutomationPeer is now `public` (class + constructor); the
  "TODO: Make this class public in .NET11.0" is resolved.
- Added the corresponding net-windows PublicAPI.Unshipped.txt entries
  (type, constructor, and the six protected overrides), matching the
  existing MauiButtonAutomationPeer pattern.
- LayoutPanel.OnCreateAutomationPeer + the AutomationId/screen-reader opt-in
  behavior are unchanged from dotnet#35597.

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

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35909

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35909"

@kubaflo

kubaflo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of #35597, which now targets net11.0 and contains all of these changes (the opt-in screen-reader behavior plus the public MauiLayoutAutomationPeer + net-windows PublicAPI entries). #35597's branch has been updated to this commit.

@kubaflo kubaflo closed this Jun 13, 2026
@kubaflo

kubaflo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Fleet code review — PR #35909

Reviewed head SHA: 40c06436ba09986317ab76cc5aba2f169665ae41
Verdict: NEEDS_CHANGES (if this PR continues; author notes it is being closed in favor of #35597)
Confidence: medium-high

Independent assessment

This Windows-only change adds a MauiLayoutAutomationPeer for LayoutPanel, exposes it as public API for net-windows, and makes layout peers appear in UIA Control/Content views only when there is an explicit accessibility/test signal (AutomationId, semantic Name/HelpText, or AutomationProperties.IsInAccessibleTree). The product-code approach is generally sound, and the Windows PublicAPI entries match the new type/ctor/protected overrides.

Findings by severity

❌ Errors

None found in the product implementation or PublicAPI surface.

⚠️ Warnings

  1. Windows-specific UI tests are not gated to Windowssrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue4715.cs:13-83 adds shared Appium tests for behavior that is explicitly Windows/UIA-specific (Issue4715 HostApp page is marked PlatformAffected.UWP at src/Controls/tests/TestCases.HostApp/Issues/Issue4715.cs:3). These tests will be compiled for the non-Windows UI test fixtures too, and assertions such as WaitForNoElement("OptedOutGrid") rely on Windows AccessibilityView.Raw semantics rather than Android/iOS/Mac query behavior. Please gate the tests to Windows (or otherwise make the expectations cross-platform) before relying on them in CI.
  2. Global Windows mapper now clears the native AccessibilityView local value when MAUI IsInAccessibleTree becomes nullsrc/Controls/src/Core/Element/Element.Windows.cs:21-33. The old helper was effectively a no-op for the null case unless a default was passed; this now applies ClearValue for every Windows element on runtime true/false -> null transitions. That may be intended, but it can also remove a local native AccessibilityView.Control/Content value set outside the MAUI property mapper. Please confirm this broader behavior is deliberate.

💡 Suggestions

  • AutomationId now intentionally makes named layout containers participate in UIA Control view (src/Core/src/Platform/Windows/MauiLayoutAutomationPeer.cs:45-83). This is consistent with the issue and code comments, but it is a high-impact accessibility tradeoff because many apps use AutomationId only as a test hook. I recommend explicit accessibility-owner sign-off.

Reconciliation with PR narrative

The PR description accurately describes this as the net11.0 version of the Windows layout peer work plus public API entries. It also says this PR is superseded/closing in favor of #35597; the same findings should be considered there if that PR carries the same changes.

CI note

gh pr checks 35909 is not green: maui-pr / Windows/macOS build and Helix unit-test legs are still pending on AzDO build 1463042 (shown for the same commit via #35597), and the GitHub agent job failed while pulling node:lts-alpine from Docker Hub (context deadline exceeded), which looks infrastructure-related rather than code-related. I would not call this merge-ready until the required MAUI CI completes successfully.

Automated non-approval review, not a substitute for human review.

PureWeen pushed a commit that referenced this pull request Jun 25, 2026
…n reader tree (#35597)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

Follow-up to #35562, now targeting `net11.0`. #35562 added
`MauiLayoutAutomationPeer` so `AutomationId` set on a `Layout` would be
visible to UI Automation clients (Appium / WinAppDriver, etc.), fixing
#4715. As a side effect, every `LayoutPanel` was reported as
`IsControlElement = true`, which put every `Grid` / `StackLayout` /
`VerticalStackLayout` / `ContentView` into the UIA **Control view** that
screen readers (Narrator, NVDA) walk -- noisy as soon as anyone adds an
`AutomationId` for UI testing.

This PR makes the layout peer **opt-in** for the screen-reader tree, and
-- because it targets `net11.0` -- actions the deferred `.NET11.0` TODO
by making `MauiLayoutAutomationPeer` **public** (class + constructor)
and adding the matching `net-windows` PublicAPI entries (type,
constructor, and the six protected overrides).

This PR supersedes #35909 (which was the net11.0 staging of these
changes).

**Behavior after this PR:**

| Set on a Layout / ContentView | UIA raw view (UI tests) | UIA Control
view (screen readers) | UIA Content view |
|---|---|---|---|
| Nothing | excluded | excluded | excluded |
| `AutomationId="..."` only | **included** | **included** as `Custom`
with no localized control type | excluded |
| `AutomationProperties.IsInAccessibleTree="True"` | included |
**included** | **included** |
| `SemanticProperties.Description="..."` (or `Hint`) | included |
**included** | excluded |

So:
- Pure test hook: `AutomationId` alone keeps Windows UI tests working.
It enters the Control view for Appium / WinAppDriver discoverability,
but reports `Custom` with an empty localized control type instead of a
grouping `Pane`.
- Accessibility landmark:
`AutomationProperties.IsInAccessibleTree="True"` opts the panel into the
accessibility tree. Screen readers see it.
- Accessibility content: `SemanticProperties.Description` / `Hint` is
treated as an implicit opt-in.
- Explicit `IsInAccessibleTree="False"` (Raw) always wins over any
opt-in.

`GetClassNameCore` (cross-platform layout type name) and
`IsKeyboardFocusableCore` (false) are unchanged from #35562.
`GetAutomationControlTypeCore` now reports `Custom` for anonymous /
AutomationId-only layouts and `Pane` only for explicit accessibility
semantics.

### Tests

`LayoutTests.Windows.cs` is updated to verify `AutomationId` through the
peer, keep AutomationId-only layouts out of the Content view (quieter
`Custom` role), and cover the opt-in paths (`IsInAccessibleTree`,
`Description`, `Hint`), explicit `Raw` opt-out precedence, and
whitespace-only semantic text. UI test coverage added in `Issue4715`.

### Validation

This change is Windows-only. Windows CI must confirm the PublicAPI
analyzer results (RS0016/RS0017), since `net-windows` cannot be built
locally on macOS.

### Issues Fixed

Follow-up refinement to #35562, which fixed #4715.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants