Skip to content

Commit fc677b2

Browse files
committed
Implement ApiInformation checks (#14090)
* Create wrapper for IApiInformationStatics * Use ApiInformation APIs to get if WinRT types are supported * Add some docs #Conflicts: # src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs # src/Windows/Avalonia.Win32/WinRT/winrt.idl # src/Windows/Avalonia.Win32/WindowImpl.cs
1 parent 43a9aa4 commit fc677b2

File tree

3 files changed

+180
-1
lines changed

3 files changed

+180
-1
lines changed

src/Windows/Avalonia.Win32/Win32PlatformSettings.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ namespace Avalonia.Win32;
88

99
internal class Win32PlatformSettings : DefaultPlatformSettings
1010
{
11+
private static readonly Lazy<bool> s_uiSettingsSupported = new(() =>
12+
WinRTApiInformation.IsTypePresent("Windows.UI.ViewManagement.UISettings")
13+
&& WinRTApiInformation.IsTypePresent("Windows.UI.ViewManagement.AccessibilitySettings"));
14+
1115
private PlatformColorValues? _lastColorValues;
1216

1317
public override Size GetTapSize(PointerType type)
@@ -32,7 +36,7 @@ public override Size GetDoubleTapSize(PointerType type)
3236

3337
public override PlatformColorValues GetColorValues()
3438
{
35-
if (Win32Platform.WindowsVersion.Major < 10)
39+
if (!s_uiSettingsSupported.Value)
3640
{
3741
return base.GetColorValues();
3842
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
using System;
2+
using Avalonia.Logging;
3+
using MicroCom.Runtime;
4+
5+
namespace Avalonia.Win32.WinRT;
6+
7+
/// <summary>
8+
/// Any WinRT API might not be available even if Windows version is supposed to support them (Win PE, Xbox...).
9+
/// Using ApiInformation is a typical solution in UWP/WinUI apps, so we should do as well.
10+
/// </summary>
11+
internal static unsafe class WinRTApiInformation
12+
{
13+
private static readonly Lazy<IApiInformationStatics?> s_statics = new(() =>
14+
{
15+
if (Win32Platform.WindowsVersion.Major < 10)
16+
{
17+
return null;
18+
}
19+
20+
try
21+
{
22+
using var apiStatics = NativeWinRTMethods.CreateActivationFactory<IApiInformationStatics>(
23+
"Windows.Foundation.Metadata.ApiInformation");
24+
return apiStatics.CloneReference();
25+
}
26+
catch (Exception ex)
27+
{
28+
Logger.TryGet(LogEventLevel.Warning, LogArea.Win32Platform)?
29+
.Log(null, "Unable to create ApiInformation instance: {0}", ex);
30+
return null;
31+
}
32+
});
33+
34+
public static bool IsTypePresent(string typeName)
35+
{
36+
using var typeNamePtr = new HStringInterop(typeName);
37+
var result = 0;
38+
if (s_statics.Value?.IsTypePresent(typeNamePtr.Handle, &result) == 0)
39+
{
40+
return result == 1;
41+
}
42+
43+
return false;
44+
}
45+
46+
public static bool IsMethodPresent(string typeName, string methodName)
47+
{
48+
using var typeNamePtr = new HStringInterop(typeName);
49+
using var methodNamePtr = new HStringInterop(methodName);
50+
var result = 0;
51+
if (s_statics.Value?.IsMethodPresent(typeNamePtr.Handle, methodNamePtr.Handle, &result) == 0)
52+
{
53+
return result == 1;
54+
}
55+
56+
return false;
57+
}
58+
59+
public static bool IsMethodPresentWithArity(string typeName, string methodName, uint inputParameterCount)
60+
{
61+
using var typeNamePtr = new HStringInterop(typeName);
62+
using var methodNamePtr = new HStringInterop(methodName);
63+
var result = 0;
64+
if (s_statics.Value?.IsMethodPresentWithArity(typeNamePtr.Handle, methodNamePtr.Handle, inputParameterCount, &result) == 0)
65+
{
66+
return result == 1;
67+
}
68+
69+
return false;
70+
}
71+
72+
public static bool IsEventPresent(string typeName, string eventName)
73+
{
74+
using var typeNamePtr = new HStringInterop(typeName);
75+
using var eventNamePtr = new HStringInterop(eventName);
76+
var result = 0;
77+
if (s_statics.Value?.IsEventPresent(typeNamePtr.Handle, eventNamePtr.Handle, &result) == 0)
78+
{
79+
return result == 1;
80+
}
81+
82+
return false;
83+
}
84+
85+
public static bool IsPropertyPresent(string typeName, string propertyName)
86+
{
87+
using var typeNamePtr = new HStringInterop(typeName);
88+
using var propertyNamePtr = new HStringInterop(propertyName);
89+
var result = 0;
90+
if (s_statics.Value?.IsPropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
91+
{
92+
return result == 1;
93+
}
94+
95+
return false;
96+
}
97+
98+
public static bool IsReadOnlyPropertyPresent(string typeName, string propertyName)
99+
{
100+
using var typeNamePtr = new HStringInterop(typeName);
101+
using var propertyNamePtr = new HStringInterop(propertyName);
102+
var result = 0;
103+
if (s_statics.Value?.IsReadOnlyPropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
104+
{
105+
return result == 1;
106+
}
107+
108+
return false;
109+
}
110+
111+
public static bool IsWriteablePropertyPresent(string typeName, string propertyName)
112+
{
113+
using var typeNamePtr = new HStringInterop(typeName);
114+
using var propertyNamePtr = new HStringInterop(propertyName);
115+
var result = 0;
116+
if (s_statics.Value?.IsWriteablePropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
117+
{
118+
return result == 1;
119+
}
120+
121+
return false;
122+
}
123+
124+
public static bool IsEnumNamedValuePresent(string enumTypeName, string valueName)
125+
{
126+
using var enumTypeNamePtr = new HStringInterop(enumTypeName);
127+
using var valueNamePtr = new HStringInterop(valueName);
128+
var result = 0;
129+
if (s_statics.Value?.IsEnumNamedValuePresent(enumTypeNamePtr.Handle, valueNamePtr.Handle, &result) == 0)
130+
{
131+
return result == 1;
132+
}
133+
134+
return false;
135+
}
136+
137+
public static bool IsApiContractPresentByMajor(string contractName, ushort majorVersion)
138+
{
139+
using var contractNamePtr = new HStringInterop(contractName);
140+
var result = 0;
141+
if (s_statics.Value?.IsApiContractPresentByMajor(contractNamePtr.Handle, majorVersion, &result) == 0)
142+
{
143+
return result == 1;
144+
}
145+
146+
return false;
147+
}
148+
149+
public static bool IsApiContractPresentByMajorAndMinor(string contractName, ushort majorVersion, ushort minorVersion)
150+
{
151+
using var contractNamePtr = new HStringInterop(contractName);
152+
var result = 0;
153+
if (s_statics.Value?.IsApiContractPresentByMajorAndMinor(contractNamePtr.Handle, majorVersion, minorVersion, &result) == 0)
154+
{
155+
return result == 1;
156+
}
157+
158+
return false;
159+
}
160+
}

src/Windows/Avalonia.Win32/WinRT/winrt.idl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,3 +871,18 @@ interface IAccessibilitySettings : IInspectable
871871
[propget] HRESULT HighContrast([out] [retval] boolean* value);
872872
[propget] HRESULT HighContrastScheme([out] [retval] HSTRING* value);
873873
}
874+
875+
[uuid(997439FE-F681-4A11-B416-C13A47E8BA36)]
876+
interface IApiInformationStatics : IInspectable
877+
{
878+
int IsTypePresent(HSTRING typeName, boolean* result);
879+
int IsMethodPresent(HSTRING typeName, HSTRING methodName, boolean* result);
880+
int IsMethodPresentWithArity(HSTRING typeName, HSTRING methodName, UINT32 inputParameterCount, boolean* result);
881+
int IsEventPresent(HSTRING typeName, HSTRING eventName, boolean* result);
882+
int IsPropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
883+
int IsReadOnlyPropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
884+
int IsWriteablePropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
885+
int IsEnumNamedValuePresent(HSTRING enumTypeName, HSTRING valueName, boolean* result);
886+
int IsApiContractPresentByMajor(HSTRING contractName, UINT16 majorVersion, boolean* result);
887+
int IsApiContractPresentByMajorAndMinor(HSTRING contractName, UINT16 majorVersion, UINT16 minorVersion, boolean* result);
888+
}

0 commit comments

Comments
 (0)