Browse Source

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
release/11.0.7
Max Katz 2 years ago
parent
commit
fc677b2a45
  1. 6
      src/Windows/Avalonia.Win32/Win32PlatformSettings.cs
  2. 160
      src/Windows/Avalonia.Win32/WinRT/WinRTApiInformation.cs
  3. 15
      src/Windows/Avalonia.Win32/WinRT/winrt.idl

6
src/Windows/Avalonia.Win32/Win32PlatformSettings.cs

@ -8,6 +8,10 @@ namespace Avalonia.Win32;
internal class Win32PlatformSettings : DefaultPlatformSettings
{
private static readonly Lazy<bool> s_uiSettingsSupported = new(() =>
WinRTApiInformation.IsTypePresent("Windows.UI.ViewManagement.UISettings")
&& WinRTApiInformation.IsTypePresent("Windows.UI.ViewManagement.AccessibilitySettings"));
private PlatformColorValues? _lastColorValues;
public override Size GetTapSize(PointerType type)
@ -32,7 +36,7 @@ internal class Win32PlatformSettings : DefaultPlatformSettings
public override PlatformColorValues GetColorValues()
{
if (Win32Platform.WindowsVersion.Major < 10)
if (!s_uiSettingsSupported.Value)
{
return base.GetColorValues();
}

160
src/Windows/Avalonia.Win32/WinRT/WinRTApiInformation.cs

@ -0,0 +1,160 @@
using System;
using Avalonia.Logging;
using MicroCom.Runtime;
namespace Avalonia.Win32.WinRT;
/// <summary>
/// Any WinRT API might not be available even if Windows version is supposed to support them (Win PE, Xbox...).
/// Using ApiInformation is a typical solution in UWP/WinUI apps, so we should do as well.
/// </summary>
internal static unsafe class WinRTApiInformation
{
private static readonly Lazy<IApiInformationStatics?> s_statics = new(() =>
{
if (Win32Platform.WindowsVersion.Major < 10)
{
return null;
}
try
{
using var apiStatics = NativeWinRTMethods.CreateActivationFactory<IApiInformationStatics>(
"Windows.Foundation.Metadata.ApiInformation");
return apiStatics.CloneReference();
}
catch (Exception ex)
{
Logger.TryGet(LogEventLevel.Warning, LogArea.Win32Platform)?
.Log(null, "Unable to create ApiInformation instance: {0}", ex);
return null;
}
});
public static bool IsTypePresent(string typeName)
{
using var typeNamePtr = new HStringInterop(typeName);
var result = 0;
if (s_statics.Value?.IsTypePresent(typeNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsMethodPresent(string typeName, string methodName)
{
using var typeNamePtr = new HStringInterop(typeName);
using var methodNamePtr = new HStringInterop(methodName);
var result = 0;
if (s_statics.Value?.IsMethodPresent(typeNamePtr.Handle, methodNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsMethodPresentWithArity(string typeName, string methodName, uint inputParameterCount)
{
using var typeNamePtr = new HStringInterop(typeName);
using var methodNamePtr = new HStringInterop(methodName);
var result = 0;
if (s_statics.Value?.IsMethodPresentWithArity(typeNamePtr.Handle, methodNamePtr.Handle, inputParameterCount, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsEventPresent(string typeName, string eventName)
{
using var typeNamePtr = new HStringInterop(typeName);
using var eventNamePtr = new HStringInterop(eventName);
var result = 0;
if (s_statics.Value?.IsEventPresent(typeNamePtr.Handle, eventNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsPropertyPresent(string typeName, string propertyName)
{
using var typeNamePtr = new HStringInterop(typeName);
using var propertyNamePtr = new HStringInterop(propertyName);
var result = 0;
if (s_statics.Value?.IsPropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsReadOnlyPropertyPresent(string typeName, string propertyName)
{
using var typeNamePtr = new HStringInterop(typeName);
using var propertyNamePtr = new HStringInterop(propertyName);
var result = 0;
if (s_statics.Value?.IsReadOnlyPropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsWriteablePropertyPresent(string typeName, string propertyName)
{
using var typeNamePtr = new HStringInterop(typeName);
using var propertyNamePtr = new HStringInterop(propertyName);
var result = 0;
if (s_statics.Value?.IsWriteablePropertyPresent(typeNamePtr.Handle, propertyNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsEnumNamedValuePresent(string enumTypeName, string valueName)
{
using var enumTypeNamePtr = new HStringInterop(enumTypeName);
using var valueNamePtr = new HStringInterop(valueName);
var result = 0;
if (s_statics.Value?.IsEnumNamedValuePresent(enumTypeNamePtr.Handle, valueNamePtr.Handle, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsApiContractPresentByMajor(string contractName, ushort majorVersion)
{
using var contractNamePtr = new HStringInterop(contractName);
var result = 0;
if (s_statics.Value?.IsApiContractPresentByMajor(contractNamePtr.Handle, majorVersion, &result) == 0)
{
return result == 1;
}
return false;
}
public static bool IsApiContractPresentByMajorAndMinor(string contractName, ushort majorVersion, ushort minorVersion)
{
using var contractNamePtr = new HStringInterop(contractName);
var result = 0;
if (s_statics.Value?.IsApiContractPresentByMajorAndMinor(contractNamePtr.Handle, majorVersion, minorVersion, &result) == 0)
{
return result == 1;
}
return false;
}
}

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

@ -871,3 +871,18 @@ interface IAccessibilitySettings : IInspectable
[propget] HRESULT HighContrast([out] [retval] boolean* value);
[propget] HRESULT HighContrastScheme([out] [retval] HSTRING* value);
}
[uuid(997439FE-F681-4A11-B416-C13A47E8BA36)]
interface IApiInformationStatics : IInspectable
{
int IsTypePresent(HSTRING typeName, boolean* result);
int IsMethodPresent(HSTRING typeName, HSTRING methodName, boolean* result);
int IsMethodPresentWithArity(HSTRING typeName, HSTRING methodName, UINT32 inputParameterCount, boolean* result);
int IsEventPresent(HSTRING typeName, HSTRING eventName, boolean* result);
int IsPropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
int IsReadOnlyPropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
int IsWriteablePropertyPresent(HSTRING typeName, HSTRING propertyName, boolean* result);
int IsEnumNamedValuePresent(HSTRING enumTypeName, HSTRING valueName, boolean* result);
int IsApiContractPresentByMajor(HSTRING contractName, UINT16 majorVersion, boolean* result);
int IsApiContractPresentByMajorAndMinor(HSTRING contractName, UINT16 majorVersion, UINT16 minorVersion, boolean* result);
}

Loading…
Cancel
Save