Skip to content

fix(atspi): report removed and added children in children-changed signals - #22398

Merged
MrJul merged 3 commits into
AvaloniaUI:mainfrom
glennawatson:fix/atspi-children-changed-signals
Oct 16, 2026
Merged

MrJul merged 3 commits into
AvaloniaUI:mainfrom
glennawatson:fix/atspi-children-changed-signals

Conversation

@glennawatson

@glennawatson glennawatson commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What does the pull request do?

Sends correct AT-SPI children-changed signals when a control's children change inside a window. See #22397.

Credit for this PR goes out to @cybik -- they reached out to me on LinkedIn after seeing the other AT-SPI based work I been doing in Avalonia and asked me to confirm if I saw the same issue.

What is the current behavior?

When a template selector swaps a pane, the bridge sends children-changed:add twice at index 0, and each names the parent as its own child. It never sends remove for the old pane and never names the new one. Screen readers such as Orca are left with a wrong view of the tree.

What is the updated/expected behavior with this PR?

Each child that leaves gets one remove with its old index and reference. Each child that arrives gets one add with its new index and reference.

Run the single-file app in #22397 against this branch. Each switch now reports:

children-changed:remove index=0 source='ContentPresenter' child='Pane A'
children-changed:add index=0 source='ContentPresenter' child='Pane B'

How was the solution implemented (if it's not obvious)?

OnPeerChildrenChanged rebuilds the child list and compares it with the old one. EnsureChildren uses the same code without sending signals.

  • Removals are sent highest index first, so each index is still valid as a client applies them in order. Additions follow, lowest index first.
  • Each remove is sent before the child is detached. After that, its reference becomes the null reference.
  • A child that changes position is reported as removed and added. The comparison keeps the longest run of children that stay in order, so it reports the fewest moves.
  • A node whose children no client has read sends nothing. The next read builds them. Before, it sent the self-referencing add.

Unit tests cover the comparison: replace, add, remove, move, and that applying the reported changes in order produces the new list. The D-Bus path needs a real accessibility bus, so I checked it with the repro in #22397 on a private Xvfb display and accessibility bus. The test project gets the same InternalsVisibleTo and project reference as #22383.

Checklist

Breaking changes

None.

Obsoletions / Deprecations

None.

Fixed issues

Fixes #22397

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

NuGet packages

The packages for this pull request have been published (workflow run):

@MrJul MrJul added bug os-linux area-accessibility backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Oct 7, 2026
…nals

- Send one remove per child that leaves, with its old index, before detaching it.
- Send one add per child that arrives, with its new index.
- Stop sending an add that names the parent as its own child.
- Send nothing for nodes whose children no client has read.
- Add unit tests for the child list comparison.

Fixes AvaloniaUI#22397

Co-authored-by: Renaud Lepage <387759+cybik@users.noreply.github.com>
@glennawatson
glennawatson force-pushed the fix/atspi-children-changed-signals branch from b387bc8 to c8f728e Compare October 7, 2026 14:01
@jmacato
jmacato requested a balanced review from Copilot October 8, 2026 11:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation matches the AT-SPI change contract and includes focused regression coverage.

0 open findings

What changed in this PR

Fixes AT-SPI child-change notifications so accessibility clients receive accurate removals, additions, indices, and child references.

Changes:

  • Adds ordered child-list diffing and correct AT-SPI signal emission.
  • Preserves lazy initialization when children have not been queried.
  • Adds regression tests and required test-project access.
File Description
src/​Avalonia.FreeDesktop.AtSpi/​AtSpiNode.cs Implements child diffing and signal emission.
src/​Avalonia.FreeDesktop.AtSpi/​Avalonia.FreeDesktop.AtSpi.csproj Exposes internals to the test assembly.
tests/​Avalonia.Controls.UnitTests/​Automation/​AtSpiChildrenDiffTests.cs Tests replacements, insertions, removals, moves, and ordering.
tests/​Avalonia.Controls.UnitTests/​Avalonia.Controls.UnitTests.csproj References the AT-SPI project for testing.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@jmacato
jmacato added this pull request to the merge queue Oct 14, 2026
@jmacato

jmacato commented Oct 14, 2026

Copy link
Copy Markdown
Member

@glennawatson Sorry this took a while, had a lot at hand atm 😓 Thanks for the contribution!

@cla-avalonia

cla-avalonia commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator
  • All contributors have signed the CLA.

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 14, 2026
@glennawatson

Copy link
Copy Markdown
Contributor Author

@cla-avalonia agree

@glennawatson

Copy link
Copy Markdown
Contributor Author

@jmacato all good. Just glad to help you guys out.

@glennawatson

Copy link
Copy Markdown
Contributor Author

@jmacato not sure why the build queue failed. Merge issue?

@jmacato

jmacato commented Oct 14, 2026

Copy link
Copy Markdown
Member

@glennawatson seems to be flakey test, will add again

@jmacato
jmacato added this pull request to the merge queue Oct 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 14, 2026
@MrJul
MrJul enabled auto-merge October 16, 2026 17:08
@MrJul
MrJul added this pull request to the merge queue Oct 16, 2026
Merged via the queue into AvaloniaUI:main with commit 66b7273 Oct 16, 2026
11 checks passed
@glennawatson
glennawatson deleted the fix/atspi-children-changed-signals branch October 19, 2026 06:33
MrJul added a commit that referenced this pull request Nov 2, 2026
…nals (#22398)

- Send one remove per child that leaves, with its old index, before detaching it.
- Send one add per child that arrives, with its new index.
- Stop sending an add that names the parent as its own child.
- Send nothing for nodes whose children no client has read.
- Add unit tests for the child list comparison.

Fixes #22397

Co-authored-by: Renaud Lepage <387759+cybik@users.noreply.github.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux AT-SPI sends malformed children-changed signals when a pane is swapped

5 participants