From 263eeabbc5556bc8ecca1990cfd02846c8e51e5d Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 23 Feb 2026 12:41:03 +0500 Subject: [PATCH] Make automation to target FocusRoot --- src/Avalonia.Base/Input/IInputRoot.cs | 4 +++- src/Avalonia.Native/TopLevelImpl.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Input/IInputRoot.cs b/src/Avalonia.Base/Input/IInputRoot.cs index 08c9ec5fad..513ecb0fae 100644 --- a/src/Avalonia.Base/Input/IInputRoot.cs +++ b/src/Avalonia.Base/Input/IInputRoot.cs @@ -30,6 +30,8 @@ namespace Avalonia.Input // HACK: This is a temporary hack for "default focus" concept. // If nothing is focused we send keyboard events to Window. Since for now we always // control PresentationSource, we simply pass the TopLevel as a separate parameter there. - internal InputElement FocusRoot { get; } + // It's also currently used by automation since we have special WindowAutomationPeer which needs to target the + // window itself + public InputElement FocusRoot { get; } } } diff --git a/src/Avalonia.Native/TopLevelImpl.cs b/src/Avalonia.Native/TopLevelImpl.cs index b1dd6122f6..925c00c3dd 100644 --- a/src/Avalonia.Native/TopLevelImpl.cs +++ b/src/Avalonia.Native/TopLevelImpl.cs @@ -169,7 +169,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface public AutomationPeer? GetAutomationPeer() { - return _inputRoot?.RootElement is Control c ? ControlAutomationPeer.CreatePeerForElement(c) : null; + return _inputRoot?.FocusRoot is Control c ? ControlAutomationPeer.CreatePeerForElement(c) : null; } public bool RawTextInputEvent(ulong timeStamp, string text) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 6beffe1313..b8d3515ce3 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -937,7 +937,7 @@ namespace Avalonia.Win32 return IntPtr.Zero; } case WindowsMessage.WM_GETOBJECT: - if ((long)lParam == uiaRootObjectId && UiaCoreTypesApi.IsNetComInteropAvailable && _owner?.RootElement is Control control) + if ((long)lParam == uiaRootObjectId && UiaCoreTypesApi.IsNetComInteropAvailable && _owner?.FocusRoot is Control control) { var peer = ControlAutomationPeer.CreatePeerForElement(control); var node = AutomationNode.GetOrCreate(peer);