csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
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
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|