A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

106 lines
3.5 KiB

using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Avalonia.Automation.Peers;
using Avalonia.Automation.Provider;
using Avalonia.Platform;
using Avalonia.Win32.Interop.Automation;
namespace Avalonia.Win32.Automation
{
[RequiresUnreferencedCode("Requires .NET COM interop")]
internal class RootAutomationNode : AutomationNode,
IRawElementProviderFragmentRoot,
IRawElementProviderAdviseEvents
{
private int _raiseFocusChanged;
public RootAutomationNode(AutomationPeer peer)
: base(peer)
{
Peer = base.Peer.GetProvider<IRootProvider>() ?? throw new AvaloniaInternalException(
"Attempt to create RootAutomationNode from peer which does not implement IRootProvider.");
Peer.FocusChanged += FocusChanged;
}
public override IRawElementProviderFragmentRoot? FragmentRoot => this;
public new IRootProvider Peer { get; }
public IWindowBaseImpl? WindowImpl => Peer.PlatformImpl as IWindowBaseImpl;
public IRawElementProviderFragment? ElementProviderFromPoint(double x, double y)
{
if (WindowImpl is null)
return null;
var p = WindowImpl.PointToClient(new PixelPoint((int)x, (int)y));
var peer = (WindowBaseAutomationPeer)Peer;
var found = InvokeSync(() => peer.GetPeerFromPoint(p));
var result = GetOrCreate(found) as IRawElementProviderFragment;
return result;
}
public IRawElementProviderFragment? GetFocus()
{
var focus = InvokeSync(() => Peer.GetFocus());
return GetOrCreate(focus);
}
void IRawElementProviderAdviseEvents.AdviseEventAdded(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationFocusChanged:
++_raiseFocusChanged;
break;
}
}
void IRawElementProviderAdviseEvents.AdviseEventRemoved(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationFocusChanged:
--_raiseFocusChanged;
break;
}
}
protected void RaiseFocusChanged(AutomationNode? focused)
{
if (_raiseFocusChanged > 0)
{
UiaCoreProviderApi.UiaRaiseAutomationEvent(
focused,
(int)UiaEventId.AutomationFocusChanged);
}
}
public void FocusChanged(object? sender, EventArgs e)
{
RaiseFocusChanged(GetOrCreate(Peer.GetFocus()));
}
public Rect ToScreen(Rect rect)
{
if (WindowImpl is null)
return default;
return new PixelRect(
WindowImpl.PointToScreen(rect.TopLeft),
WindowImpl.PointToScreen(rect.BottomRight))
.ToRect(1);
}
public override IRawElementProviderSimple? HostRawElementProvider
{
get
{
var handle = WindowImpl?.Handle.Handle ?? IntPtr.Zero;
if (handle == IntPtr.Zero)
return null;
var hr = UiaCoreProviderApi.UiaHostProviderFromHwnd(handle, out var result);
Marshal.ThrowExceptionForHR(hr);
return result;
}
}
}
}