diff --git a/readme.md b/readme.md
index c2be487af3..2600cf83cc 100644
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,5 @@
+[](https://avaloniaui.net/xpf)
+
[](https://t.me/Avalonia)
[](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) []( https://aka.ms/dotnet-discord) [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [](#backers) [](#sponsors) 
diff --git a/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs b/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs
index a0b7d32d3b..ac09c48ccd 100644
--- a/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs
+++ b/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs
@@ -47,7 +47,7 @@ public class D3DMemoryHelper
MipLevels = 1,
SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
CpuAccessFlags = default,
- OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
+ OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle,
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
});
}
diff --git a/samples/GpuInterop/VulkanDemo/VulkanContext.cs b/samples/GpuInterop/VulkanDemo/VulkanContext.cs
index 3fdd9695f2..1d44549089 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanContext.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanContext.cs
@@ -173,7 +173,7 @@ public unsafe class VulkanContext : IDisposable
api.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, ref queueFamilyCount, familyProperties);
for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++)
{
- var family = familyProperties[c];
+ var family = familyProperties[queueFamilyIndex];
if (!family.QueueFlags.HasAllFlags(QueueFlags.GraphicsBit))
continue;
diff --git a/samples/GpuInterop/VulkanDemo/VulkanImage.cs b/samples/GpuInterop/VulkanDemo/VulkanImage.cs
index 59b2ef7e30..c1865a817d 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanImage.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanImage.cs
@@ -4,10 +4,13 @@ using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Platform;
using Avalonia.Vulkan;
+using SharpDX.DXGI;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
using SilkNetDemo;
using SkiaSharp;
+using Device = Silk.NET.Vulkan.Device;
+using Format = Silk.NET.Vulkan.Format;
namespace GpuInterop.VulkanDemo;
@@ -24,7 +27,6 @@ public unsafe class VulkanImage : IDisposable
private ImageView? _imageView { get; set; }
private DeviceMemory _imageMemory { get; set; }
private SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
- private IntPtr _win32ShareHandle;
internal Image? InternalHandle { get; private set; }
internal Format Format { get; }
@@ -60,7 +62,7 @@ public unsafe class VulkanImage : IDisposable
//MipLevels = MipLevels != 0 ? MipLevels : (uint)Math.Floor(Math.Log(Math.Max(Size.Width, Size.Height), 2));
var handleType = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
- ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit :
+ ExternalMemoryHandleTypeFlags.D3D11TextureBit :
ExternalMemoryHandleTypeFlags.OpaqueFDBit;
var externalMemoryCreateInfo = new ExternalMemoryImageCreateInfo
{
@@ -108,14 +110,14 @@ public unsafe class VulkanImage : IDisposable
if (exportable && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
- using var dxgi = _d3dTexture2D.QueryInterface();
- _win32ShareHandle = dxgi.SharedHandle;
+ using var dxgi = _d3dTexture2D.QueryInterface();
+
handleImport = new ImportMemoryWin32HandleInfoKHR
{
PNext = &dedicatedAllocation,
SType = StructureType.ImportMemoryWin32HandleInfoKhr,
- HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit,
- Handle = _win32ShareHandle,
+ HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
+ Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
};
}
@@ -185,11 +187,19 @@ public unsafe class VulkanImage : IDisposable
return fd;
}
- public IPlatformHandle Export() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
- new PlatformHandle(_win32ShareHandle,
- KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle) :
- new PlatformHandle(new IntPtr(ExportFd()),
- KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
+ public IPlatformHandle Export()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ using var dxgi = _d3dTexture2D!.QueryInterface();
+ return new PlatformHandle(
+ dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+ KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
+ }
+ else
+ return new PlatformHandle(new IntPtr(ExportFd()),
+ KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
+ }
public ImageTiling Tiling => ImageTiling.Optimal;
diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs
index c885a7768c..df0c494648 100644
--- a/src/Android/Avalonia.Android/AndroidInputMethod.cs
+++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs
@@ -32,7 +32,7 @@ namespace Avalonia.Android
ActionPrevious = 0x00000007,
}
- class AndroidInputMethod : ITextInputMethodImpl, IAndroidInputMethod
+ internal class AndroidInputMethod : ITextInputMethodImpl, IAndroidInputMethod
where TView : View, IInitEditorInfo
{
private readonly TView _host;
@@ -167,7 +167,7 @@ namespace Avalonia.Android
}
}
- public readonly record struct ComposingRegion
+ internal readonly record struct ComposingRegion
{
private readonly int _start = -1;
private readonly int _end = -1;
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 66557418dd..2533016e9f 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -5,6 +5,7 @@
true
true
portable
+ Avalonia.Android.Internal
diff --git a/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs b/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
index 726ccdbbdd..ab84801e57 100644
--- a/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
+++ b/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
@@ -5,7 +5,7 @@ using Avalonia.Input;
namespace Avalonia.Android.Platform.Input
{
- public class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice {
+ internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice {
private static readonly Dictionary KeyDic = new Dictionary
{
// { Keycode.Cancel?, Key.Cancel },
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
index f205458f0e..47297a4f76 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
@@ -10,7 +10,7 @@ using Avalonia.Platform;
namespace Avalonia.Android
{
- public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle
+ internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle
{
bool _invalidateQueued;
readonly object _lock = new object();
diff --git a/src/Android/Avalonia.Android/PlatformIconLoader.cs b/src/Android/Avalonia.Android/PlatformIconLoader.cs
index 88677a9375..f557685dd2 100644
--- a/src/Android/Avalonia.Android/PlatformIconLoader.cs
+++ b/src/Android/Avalonia.Android/PlatformIconLoader.cs
@@ -3,7 +3,7 @@ using Avalonia.Platform;
namespace Avalonia.Android
{
- class PlatformIconLoader : IPlatformIconLoader
+ internal class PlatformIconLoader : IPlatformIconLoader
{
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
@@ -29,7 +29,7 @@ namespace Avalonia.Android
}
// Stores the icon created as a stream to support saving even though an icon is never shown
- public class FakeIcon : IWindowIconImpl
+ internal class FakeIcon : IWindowIconImpl
{
private Stream stream = new MemoryStream();
diff --git a/src/Android/Avalonia.Android/Stubs.cs b/src/Android/Avalonia.Android/Stubs.cs
index f36c01dbc8..05638cdf88 100644
--- a/src/Android/Avalonia.Android/Stubs.cs
+++ b/src/Android/Avalonia.Android/Stubs.cs
@@ -4,7 +4,7 @@ using Avalonia.Platform;
namespace Avalonia.Android
{
- class WindowingPlatformStub : IWindowingPlatform
+ internal class WindowingPlatformStub : IWindowingPlatform
{
public IWindowImpl CreateWindow() => throw new NotSupportedException();
@@ -13,7 +13,7 @@ namespace Avalonia.Android
public ITrayIconImpl CreateTrayIcon() => null;
}
- class PlatformIconLoaderStub : IPlatformIconLoader
+ internal class PlatformIconLoaderStub : IPlatformIconLoader
{
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
@@ -38,7 +38,7 @@ namespace Avalonia.Android
}
}
- public class IconStub : IWindowIconImpl
+ internal class IconStub : IWindowIconImpl
{
private readonly MemoryStream _ms;
diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs
index 1c1d09c3f5..45ab293a89 100644
--- a/src/Avalonia.Base/AvaloniaProperty.cs
+++ b/src/Avalonia.Base/AvaloniaProperty.cs
@@ -225,13 +225,8 @@ namespace Avalonia
/// The default value of the property.
/// Whether the property inherits its value.
/// The default binding mode for the property.
- /// A value validation callback.
+ /// A value validation callback.
/// A value coercion callback.
- ///
- /// A method that gets called before and after the property starts being notified on an
- /// object; the bool argument will be true before and false afterwards. This callback is
- /// intended to support IsDataContextChanging.
- ///
/// A
public static StyledProperty Register(
string name,
@@ -239,8 +234,40 @@ namespace Avalonia
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.OneWay,
Func? validate = null,
- Func? coerce = null,
- Action? notifying = null)
+ Func? coerce = null)
+ where TOwner : AvaloniaObject
+ {
+ _ = name ?? throw new ArgumentNullException(nameof(name));
+
+ var metadata = new StyledPropertyMetadata(
+ defaultValue,
+ defaultBindingMode: defaultBindingMode,
+ coerce: coerce);
+
+ var result = new StyledProperty(
+ name,
+ typeof(TOwner),
+ metadata,
+ inherits,
+ validate);
+ AvaloniaPropertyRegistry.Instance.Register(typeof(TOwner), result);
+ return result;
+ }
+
+ ///
+ ///
+ /// A method that gets called before and after the property starts being notified on an
+ /// object; the bool argument will be true before and false afterwards. This callback is
+ /// intended to support IsDataContextChanging.
+ ///
+ internal static StyledProperty Register(
+ string name,
+ TValue defaultValue,
+ bool inherits,
+ BindingMode defaultBindingMode,
+ Func? validate,
+ Func? coerce,
+ Action? notifying)
where TOwner : AvaloniaObject
{
_ = name ?? throw new ArgumentNullException(nameof(name));
diff --git a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
index bf18a7da5b..3dbc7c1bb2 100644
--- a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
+++ b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
@@ -26,6 +26,6 @@ namespace Avalonia.Platform
bool CurrentThreadIsLoopThread { get; }
- event Action Signaled;
+ event Action? Signaled;
}
}
diff --git a/src/Avalonia.Base/Platform/Storage/FilePickerFileType.cs b/src/Avalonia.Base/Platform/Storage/FilePickerFileType.cs
index 75076e2bb8..f9c7f9685d 100644
--- a/src/Avalonia.Base/Platform/Storage/FilePickerFileType.cs
+++ b/src/Avalonia.Base/Platform/Storage/FilePickerFileType.cs
@@ -7,9 +7,9 @@ namespace Avalonia.Platform.Storage;
///
public sealed class FilePickerFileType
{
- public FilePickerFileType(string name)
+ public FilePickerFileType(string? name)
{
- Name = name;
+ Name = name ?? string.Empty;
}
///
diff --git a/src/Avalonia.Base/Rendering/IRenderTimer.cs b/src/Avalonia.Base/Rendering/IRenderTimer.cs
index 07af7eeec8..14fcffd6a9 100644
--- a/src/Avalonia.Base/Rendering/IRenderTimer.cs
+++ b/src/Avalonia.Base/Rendering/IRenderTimer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Threading.Tasks;
using Avalonia.Metadata;
namespace Avalonia.Rendering
diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs
index 5bf022cd51..2cdb973174 100644
--- a/src/Avalonia.Base/StyledElement.cs
+++ b/src/Avalonia.Base/StyledElement.cs
@@ -41,7 +41,11 @@ namespace Avalonia
public static readonly StyledProperty