diff --git a/samples/ControlCatalog/Pages/DrawerPage/DrawerPageCustomizationPage.xaml b/samples/ControlCatalog/Pages/DrawerPage/DrawerPageCustomizationPage.xaml
index cba7837314..4987e8979e 100644
--- a/samples/ControlCatalog/Pages/DrawerPage/DrawerPageCustomizationPage.xaml
+++ b/samples/ControlCatalog/Pages/DrawerPage/DrawerPageCustomizationPage.xaml
@@ -118,6 +118,11 @@
Header="Customization"
DrawerLength="260"
DrawerHeaderBackground="{DynamicResource SystemControlHighlightAccentBrush}">
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/DrawerPage/EcoTrackerAppPage.xaml b/samples/ControlCatalog/Pages/DrawerPage/EcoTrackerAppPage.xaml
index 22320fbc8d..1e9106ccfe 100644
--- a/samples/ControlCatalog/Pages/DrawerPage/EcoTrackerAppPage.xaml
+++ b/samples/ControlCatalog/Pages/DrawerPage/EcoTrackerAppPage.xaml
@@ -52,9 +52,13 @@
-
+ M12 3C9 6 6 9 6 13C6 17.4 8.7 21 12 22C15.3 21 18 17.4 18 13C18 9 15 6 12 3Z
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomTabBarPage.xaml.cs b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomTabBarPage.xaml.cs
index bb7302c1cd..b1a692b85a 100644
--- a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomTabBarPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomTabBarPage.xaml.cs
@@ -5,7 +5,6 @@ namespace ControlCatalog.Pages
{
public partial class TabbedPageCustomTabBarPage : UserControl
{
- // Fluent UI icon geometries (24x24 viewbox)
private static readonly StreamGeometry HomeGeometry =
StreamGeometry.Parse("M12.9942 2.79444C12.4118 2.30208 11.5882 2.30208 11.0058 2.79444L3.50582 9.39444C3.18607 9.66478 3 10.0634 3 10.4828V20.25C3 20.9404 3.55964 21.5 4.25 21.5H8.25C8.94036 21.5 9.5 20.9404 9.5 20.25V14.75C9.5 14.6119 9.61193 14.5 9.75 14.5H14.25C14.3881 14.5 14.5 14.6119 14.5 14.75V20.25C14.5 20.9404 15.0596 21.5 15.75 21.5H19.75C20.4404 21.5 21 20.9404 21 20.25V10.4828C21 10.0634 20.8139 9.66478 20.4942 9.39444L12.9942 2.79444Z");
private static readonly StreamGeometry WalletGeometry =
@@ -25,16 +24,11 @@ namespace ControlCatalog.Pages
private void SetupIcons()
{
- SetIcon(HomePage, HomeGeometry);
- SetIcon(WalletPage, WalletGeometry);
- SetIcon(SendPage, SendGeometry);
- SetIcon(ActivityPage, ActivityGeometry);
- SetIcon(ProfilePage, ProfileGeometry);
- }
-
- private static void SetIcon(ContentPage page, StreamGeometry geometry)
- {
- page.Icon = geometry;
+ HomePage.Icon = new PathIcon { Data = HomeGeometry };
+ WalletPage.Icon = new PathIcon { Data = WalletGeometry };
+ SendPage.Icon = new PathIcon { Data = SendGeometry };
+ ActivityPage.Icon = new PathIcon { Data = ActivityGeometry };
+ ProfilePage.Icon = new PathIcon { Data = ProfileGeometry };
}
}
}
diff --git a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomizationPage.xaml.cs b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomizationPage.xaml.cs
index dc72759c5e..b4eb6d9b49 100644
--- a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomizationPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageCustomizationPage.xaml.cs
@@ -109,14 +109,9 @@ namespace ControlCatalog.Pages
private void OnShowIconsChanged(object? sender, RoutedEventArgs e)
{
bool show = ShowIconsCheck.IsChecked == true;
- SetIcon(HomePage, show ? HomeGeometry : null);
- SetIcon(SearchPage, show ? SearchGeometry : null);
- SetIcon(SettingsPage, show ? SettingsGeometry : null);
- }
-
- private static void SetIcon(ContentPage page, StreamGeometry? geometry)
- {
- page.Icon = geometry;
+ HomePage.Icon = show ? new PathIcon { Data = HomeGeometry } : null;
+ SearchPage.Icon = show ? new PathIcon { Data = SearchGeometry } : null;
+ SettingsPage.Icon = show ? new PathIcon { Data = SettingsGeometry } : null;
}
private void OnTabEnabledChanged(object? sender, RoutedEventArgs e)
diff --git a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageFabPage.xaml.cs b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageFabPage.xaml.cs
index 5c10a50df7..b52bfd4d8a 100644
--- a/samples/ControlCatalog/Pages/TabbedPage/TabbedPageFabPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabbedPage/TabbedPageFabPage.xaml.cs
@@ -28,10 +28,10 @@ namespace ControlCatalog.Pages
private void SetupIcons()
{
- FeedPage.Icon = FeedGeometry;
- DiscoverPage.Icon = DiscoverGeometry;
- AlertsPage.Icon = AlertsGeometry;
- ProfilePage.Icon = ProfileGeometry;
+ FeedPage.Icon = new PathIcon { Data = FeedGeometry };
+ DiscoverPage.Icon = new PathIcon { Data = DiscoverGeometry };
+ AlertsPage.Icon = new PathIcon { Data = AlertsGeometry };
+ ProfilePage.Icon = new PathIcon { Data = ProfileGeometry };
}
private void OnFabClicked(object? sender, RoutedEventArgs e)
diff --git a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
index 47d95d8da1..59ec332b2d 100644
--- a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
+++ b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
@@ -12,6 +12,7 @@ using Avalonia.Logging;
using Avalonia.Platform.Storage;
using Avalonia.Platform.Storage.FileIO;
using Java.Lang;
+using static Android.Provider.DocumentsContract;
using AndroidUri = Android.Net.Uri;
using Exception = System.Exception;
using JavaFile = Java.IO.File;
@@ -35,10 +36,10 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
}
internal AndroidUri Uri { get; set; }
-
+
protected Activity Activity => _activity ?? throw new ObjectDisposedException(nameof(AndroidStorageItem));
- public virtual string Name => GetColumnValue(Activity, Uri, DocumentsContract.Document.ColumnDisplayName)
+ public virtual string Name => GetColumnValue(Activity, Uri, Document.ColumnDisplayName)
?? GetColumnValue(Activity, Uri, MediaStore.IMediaColumns.DisplayName)
?? Uri.PathSegments?.LastOrDefault()?.Split("/", StringSplitOptions.RemoveEmptyEntries).LastOrDefault() ?? string.Empty;
@@ -67,7 +68,7 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
Activity.ContentResolver?.ReleasePersistableUriPermission(Uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantReadUriPermission);
}
-
+
public abstract Task GetBasicPropertiesAsync();
protected static string? GetColumnValue(Context context, AndroidUri contentUri, string column, string? selection = null, string[]? selectionArgs = null)
@@ -98,7 +99,7 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
return null;
}
- if(_parent != null)
+ if (_parent != null)
{
return _parent;
}
@@ -106,8 +107,8 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
using var javaFile = new JavaFile(Uri.Path!);
// Java file represents files AND directories. Don't be confused.
- if (javaFile.ParentFile is {} parentFile
- && AndroidUri.FromFile(parentFile) is {} androidUri)
+ if (javaFile.ParentFile is { } parentFile
+ && AndroidUri.FromFile(parentFile) is { } androidUri)
{
return new AndroidStorageFolder(Activity, androidUri, false);
}
@@ -124,12 +125,12 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
return await _activity!.CheckPermission(Manifest.Permission.ReadExternalStorage);
}
-
+
public void Dispose()
{
_activity = null;
}
-
+
internal AndroidUri? PermissionRoot => _permissionRoot;
public abstract Task DeleteAsync();
@@ -138,8 +139,8 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
public static IStorageItem CreateItem(Activity activity, AndroidUri uri)
{
- var mimeType = GetColumnValue(activity, uri, DocumentsContract.Document.ColumnMimeType);
- if (mimeType == DocumentsContract.Document.MimeTypeDir)
+ var mimeType = GetColumnValue(activity, uri, Document.ColumnMimeType);
+ if (mimeType == Document.MimeTypeDir)
{
return new AndroidStorageFolder(activity, uri, false);
}
@@ -160,8 +161,8 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
{
var mimeType = MimeTypeMap.Singleton?.GetMimeTypeFromExtension(MimeTypeMap.GetFileExtensionFromUrl(name)) ?? "application/octet-stream";
var treeUri = GetTreeUri().treeUri;
- var newFile = DocumentsContract.CreateDocument(Activity.ContentResolver!, treeUri!, mimeType, name);
- if(newFile == null)
+ var newFile = CreateDocument(Activity.ContentResolver!, treeUri!, mimeType, name);
+ if (newFile == null)
{
return Task.FromResult(null);
}
@@ -172,7 +173,7 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
public Task CreateFolderAsync(string name)
{
var treeUri = GetTreeUri().treeUri;
- var newFolder = DocumentsContract.CreateDocument(Activity.ContentResolver!, treeUri!, DocumentsContract.Document.MimeTypeDir, name);
+ var newFolder = CreateDocument(Activity.ContentResolver!, treeUri!, Document.MimeTypeDir, name);
if (newFolder == null)
{
return Task.FromResult(null);
@@ -197,24 +198,76 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
{
await foreach (var file in storageFolder.GetItemsAsync())
{
- if(file is AndroidStorageFolder folder)
+ if (file is AndroidStorageFolder folder)
{
await DeleteContents(folder);
}
- else if(file is AndroidStorageFile storageFile)
+ else if (file is AndroidStorageFile storageFile)
{
await storageFile.DeleteAsync();
}
}
var treeUri = GetTreeUri().treeUri;
- DocumentsContract.DeleteDocument(Activity.ContentResolver!, treeUri!);
+ DeleteDocument(Activity.ContentResolver!, treeUri!);
}
}
public override Task GetBasicPropertiesAsync()
{
- return Task.FromResult(new StorageItemProperties());
+ DateTimeOffset? dateModified = null;
+
+ AndroidUri? queryUri = null;
+
+ try
+ {
+ try
+ {
+ // When Uri is a tree URI, use its document id to build a document URI.
+ var folderId = GetTreeDocumentId(Uri);
+ queryUri = BuildDocumentUriUsingTree(Uri, folderId);
+ }
+ catch (UnsupportedOperationException)
+ {
+ // For non-root items, Uri may already be a document URI; use it directly.
+ queryUri = Uri;
+ }
+
+ if (queryUri != null)
+ {
+ var projection = new[]
+ {
+ Document.ColumnLastModified
+ };
+ using var cursor = Activity.ContentResolver!.Query(queryUri, projection, null, null, null);
+
+ if (cursor?.MoveToFirst() == true)
+ {
+ try
+ {
+ var columnIndex = cursor.GetColumnIndex(Document.ColumnLastModified);
+ if (columnIndex != -1)
+ {
+ var longValue = cursor.GetLong(columnIndex);
+ dateModified = longValue > 0 ? DateTimeOffset.FromUnixTimeMilliseconds(longValue) : null;
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?
+ .Log(this, "Directory LastModified metadata reader failed: '{Exception}'", ex);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Data may not be available for this item or the URI may not be in the expected shape.
+ Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?
+ .Log(this, "Directory basic properties metadata unavailable: '{Exception}'", ex);
+ }
+
+ return Task.FromResult(new StorageItemProperties(null, null, dateModified));
}
public async IAsyncEnumerable GetItemsAsync()
@@ -234,8 +287,8 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
var projection = new[]
{
- DocumentsContract.Document.ColumnDocumentId,
- DocumentsContract.Document.ColumnMimeType
+ Document.ColumnDocumentId,
+ Document.ColumnMimeType
};
if (childrenUri != null)
{
@@ -247,8 +300,8 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
var mime = cursor.GetString(1);
var id = cursor.GetString(0);
- bool isDirectory = mime == DocumentsContract.Document.MimeTypeDir;
- var uri = DocumentsContract.BuildDocumentUriUsingTree(root, id);
+ bool isDirectory = mime == Document.MimeTypeDir;
+ var uri = BuildDocumentUriUsingTree(root, id);
if (uri == null)
{
@@ -313,9 +366,9 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
var projection = new[]
{
- DocumentsContract.Document.ColumnDocumentId,
- DocumentsContract.Document.ColumnMimeType,
- DocumentsContract.Document.ColumnDisplayName
+ Document.ColumnDocumentId,
+ Document.ColumnMimeType,
+ Document.ColumnDisplayName
};
if (childrenUri != null)
@@ -332,15 +385,15 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
if (fileName != name)
{
continue;
- }
+ }
- bool mineDirectory = mime == DocumentsContract.Document.MimeTypeDir;
+ bool mineDirectory = mime == Document.MimeTypeDir;
if (isDirectory != mineDirectory)
{
return null;
}
- var uri = DocumentsContract.BuildDocumentUriUsingTree(root, id);
+ var uri = BuildDocumentUriUsingTree(root, id);
if (uri == null)
{
return null;
@@ -370,8 +423,8 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
private (AndroidUri root, AndroidUri? treeUri) GetTreeUri()
{
var root = PermissionRoot ?? Uri;
- var folderId = root != Uri ? DocumentsContract.GetDocumentId(Uri) : DocumentsContract.GetTreeDocumentId(Uri);
- return (root, DocumentsContract.BuildChildDocumentsUriUsingTree(root, folderId));
+ var folderId = root != Uri ? GetDocumentId(Uri) : GetTreeDocumentId(Uri);
+ return (root, BuildChildDocumentsUriUsingTree(root, folderId));
}
}
@@ -419,10 +472,10 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
if (!OperatingSystem.IsAndroidVersionAtLeast(24))
return false;
- if (!DocumentsContract.IsDocumentUri(context, uri))
+ if (!IsDocumentUri(context, uri))
return false;
- var value = GetColumnValue(context, uri, DocumentsContract.Document.ColumnFlags);
+ var value = GetColumnValue(context, uri, Document.ColumnFlags);
if (!string.IsNullOrEmpty(value) && int.TryParse(value, out var flagsInt))
{
var flags = (DocumentContractFlags)flagsInt;
@@ -530,7 +583,7 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
if (Activity != null)
{
- DocumentsContract.DeleteDocument(Activity.ContentResolver!, Uri);
+ DeleteDocument(Activity.ContentResolver!, Uri);
}
}
@@ -553,7 +606,7 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
storageFolder.Uri is { } targetParentUri &&
await GetParentAsync() is AndroidStorageFolder parentFolder)
{
- movedUri = DocumentsContract.MoveDocument(contentResolver, Uri, parentFolder.Uri, targetParentUri);
+ movedUri = MoveDocument(contentResolver, Uri, parentFolder.Uri, targetParentUri);
}
}
catch (Exception)
diff --git a/src/Avalonia.Base/Input/DragEventArgs.cs b/src/Avalonia.Base/Input/DragEventArgs.cs
index e68a6138e0..d4e0cb1bce 100644
--- a/src/Avalonia.Base/Input/DragEventArgs.cs
+++ b/src/Avalonia.Base/Input/DragEventArgs.cs
@@ -1,6 +1,5 @@
using System;
using Avalonia.Interactivity;
-using Avalonia.Metadata;
namespace Avalonia.Input
{
@@ -25,9 +24,8 @@ namespace Avalonia.Input
return _target.TranslatePoint(_targetLocation, relativeTo) ?? new Point(0, 0);
}
- [Unstable("This constructor might be removed in 12.0. For unit testing, consider using DragDrop.DoDragDrop or IHeadlessWindow.DragDrop.")]
public DragEventArgs(
- RoutedEvent routedEvent,
+ RoutedEvent? routedEvent,
IDataTransfer dataTransfer,
Interactive target,
Point targetLocation,
diff --git a/src/Avalonia.Base/Input/FocusChangedEventArgs.cs b/src/Avalonia.Base/Input/FocusChangedEventArgs.cs
index ade599ee08..ecca7750ed 100644
--- a/src/Avalonia.Base/Input/FocusChangedEventArgs.cs
+++ b/src/Avalonia.Base/Input/FocusChangedEventArgs.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Input
/// Initializes a new instance of .
///
/// The routed event associated with these event args.
- public FocusChangedEventArgs(RoutedEvent routedEvent)
+ public FocusChangedEventArgs(RoutedEvent? routedEvent)
: base(routedEvent)
{
}
diff --git a/src/Avalonia.Base/Input/FocusChangingEventArgs.cs b/src/Avalonia.Base/Input/FocusChangingEventArgs.cs
index 372ddf38b6..ed237265a6 100644
--- a/src/Avalonia.Base/Input/FocusChangingEventArgs.cs
+++ b/src/Avalonia.Base/Input/FocusChangingEventArgs.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Input
///
/// Provides data for focus changing.
///
- internal FocusChangingEventArgs(RoutedEvent routedEvent) : base(routedEvent)
+ public FocusChangingEventArgs(RoutedEvent? routedEvent) : base(routedEvent)
{
}
diff --git a/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs b/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs
index 3c4562edf4..6a6c61d315 100644
--- a/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs
+++ b/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs
@@ -1,7 +1,4 @@
-using System;
using Avalonia.Interactivity;
-using Avalonia.Metadata;
-using Avalonia.VisualTree;
namespace Avalonia.Input
{
@@ -9,8 +6,7 @@ namespace Avalonia.Input
{
public Vector Delta { get; }
- [Unstable("This constructor might be removed in 12.0.")]
- public PointerDeltaEventArgs(RoutedEvent routedEvent, object? source,
+ public PointerDeltaEventArgs(RoutedEvent? routedEvent, object? source,
IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp,
PointerPointProperties properties, KeyModifiers modifiers, Vector delta)
: base(routedEvent, source, pointer, rootVisual, rootVisualPosition,
diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs
index f4bf785c56..9285e65fa5 100644
--- a/src/Avalonia.Base/Input/PointerEventArgs.cs
+++ b/src/Avalonia.Base/Input/PointerEventArgs.cs
@@ -14,8 +14,7 @@ namespace Avalonia.Input
private readonly PointerPointProperties _properties;
private readonly Lazy?>? _previousPoints;
- [Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
- public PointerEventArgs(RoutedEvent routedEvent,
+ public PointerEventArgs(RoutedEvent? routedEvent,
object? source,
IPointer pointer,
Visual? rootVisual, Point rootVisualPosition,
@@ -32,8 +31,9 @@ namespace Avalonia.Input
Timestamp = timestamp;
KeyModifiers = modifiers;
}
-
- internal PointerEventArgs(RoutedEvent routedEvent,
+
+ [PrivateApi]
+ public PointerEventArgs(RoutedEvent? routedEvent,
object? source,
IPointer pointer,
Visual? rootVisual, Point rootVisualPosition,
@@ -41,9 +41,7 @@ namespace Avalonia.Input
PointerPointProperties properties,
KeyModifiers modifiers,
Lazy?>? previousPoints)
-#pragma warning disable CS0618
: this(routedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers)
-#pragma warning restore CS0618
{
_previousPoints = previousPoints;
}
@@ -160,9 +158,8 @@ namespace Avalonia.Input
public class PointerPressedEventArgs : PointerEventArgs
{
- [Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
public PointerPressedEventArgs(
- object source,
+ object? source,
IPointer pointer,
Visual rootVisual, Point rootVisualPosition,
ulong timestamp,
@@ -180,9 +177,8 @@ namespace Avalonia.Input
public class PointerReleasedEventArgs : PointerEventArgs
{
- [Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
public PointerReleasedEventArgs(
- object source, IPointer pointer,
+ object? source, IPointer pointer,
Visual rootVisual, Point rootVisualPosition, ulong timestamp,
PointerPointProperties properties, KeyModifiers modifiers,
MouseButton initialPressMouseButton)
@@ -202,8 +198,7 @@ namespace Avalonia.Input
{
public IPointer Pointer { get; }
- [Unstable("This constructor might be removed in 12.0. If you need to remove capture, use stable methods on the IPointer instance.")]
- public PointerCaptureLostEventArgs(object source, IPointer pointer) : base(InputElement.PointerCaptureLostEvent)
+ public PointerCaptureLostEventArgs(object? source, IPointer pointer) : base(InputElement.PointerCaptureLostEvent)
{
Pointer = pointer;
Source = source;
@@ -216,7 +211,7 @@ namespace Avalonia.Input
public CaptureSource CaptureSource { get; }
public IInputElement? NewValue { get; }
- internal PointerCaptureChangingEventArgs(object source, IPointer pointer, IInputElement? newValue, CaptureSource captureSource) : base(InputElement.PointerCaptureChangingEvent)
+ internal PointerCaptureChangingEventArgs(object? source, IPointer pointer, IInputElement? newValue, CaptureSource captureSource) : base(InputElement.PointerCaptureChangingEvent)
{
Pointer = pointer;
Source = source;
diff --git a/src/Avalonia.Base/Input/PointerWheelEventArgs.cs b/src/Avalonia.Base/Input/PointerWheelEventArgs.cs
index 22624a61dd..9cfeaeea74 100644
--- a/src/Avalonia.Base/Input/PointerWheelEventArgs.cs
+++ b/src/Avalonia.Base/Input/PointerWheelEventArgs.cs
@@ -1,16 +1,10 @@
-using System;
-using Avalonia.Interactivity;
-using Avalonia.Metadata;
-using Avalonia.VisualTree;
-
namespace Avalonia.Input
{
public class PointerWheelEventArgs : PointerEventArgs
{
public Vector Delta { get; }
- [Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow.MouseWheel.")]
- public PointerWheelEventArgs(object source, IPointer pointer, Visual rootVisual,
+ public PointerWheelEventArgs(object? source, IPointer pointer, Visual rootVisual,
Point rootVisualPosition, ulong timestamp,
PointerPointProperties properties, KeyModifiers modifiers, Vector delta)
: base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition,
diff --git a/src/Avalonia.Base/Input/TappedEventArgs.cs b/src/Avalonia.Base/Input/TappedEventArgs.cs
index a235d495d6..924f4be11f 100644
--- a/src/Avalonia.Base/Input/TappedEventArgs.cs
+++ b/src/Avalonia.Base/Input/TappedEventArgs.cs
@@ -6,7 +6,7 @@ namespace Avalonia.Input
{
private readonly PointerEventArgs lastPointerEventArgs;
- public TappedEventArgs(RoutedEvent routedEvent, PointerEventArgs lastPointerEventArgs)
+ public TappedEventArgs(RoutedEvent? routedEvent, PointerEventArgs lastPointerEventArgs)
: base(routedEvent)
{
this.lastPointerEventArgs = lastPointerEventArgs;
diff --git a/src/Avalonia.Base/Rect.cs b/src/Avalonia.Base/Rect.cs
index 58a8c56c8b..9c901254a6 100644
--- a/src/Avalonia.Base/Rect.cs
+++ b/src/Avalonia.Base/Rect.cs
@@ -1,7 +1,6 @@
using System;
using System.Globalization;
using System.Numerics;
-using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
index 81a3c09b35..e8ae84eb03 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
@@ -149,12 +149,16 @@ namespace Avalonia.Rendering.Composition.Server
try
{
- if (_renderTarget == null && !_compositor.IsReadyToCreateRenderTarget(_surfaces()))
+ if (_renderTarget == null)
{
- IsWaitingForReadyRenderTarget = IsEnabled;
- return;
+ if (!_compositor.IsReadyToCreateRenderTarget(_surfaces()))
+ {
+ IsWaitingForReadyRenderTarget = IsEnabled;
+ return;
+ }
+
+ _renderTarget = _compositor.CreateRenderTarget(_surfaces());
}
- _renderTarget ??= _compositor.CreateRenderTarget(_surfaces());
}
catch (RenderTargetNotReadyException)
{
diff --git a/src/Avalonia.Base/Threading/Dispatcher.Invoke.cs b/src/Avalonia.Base/Threading/Dispatcher.Invoke.cs
index fbd96ed7d8..90167fa8a1 100644
--- a/src/Avalonia.Base/Threading/Dispatcher.Invoke.cs
+++ b/src/Avalonia.Base/Threading/Dispatcher.Invoke.cs
@@ -737,9 +737,6 @@ public partial class Dispatcher
///
public static DispatcherPriorityAwaitable Yield(DispatcherPriority priority)
{
- // TODO12: Update to use Dispatcher.CurrentDispatcher once multi-dispatcher support is merged
- var current = UIThread;
- current.VerifyAccess();
- return UIThread.Resume(priority);
+ return CurrentDispatcher.Resume(priority);
}
}
diff --git a/src/Avalonia.Controls/Converters/BorderGapMaskConverter.cs b/src/Avalonia.Controls/Converters/BorderGapMaskConverter.cs
new file mode 100644
index 0000000000..913b2f1534
--- /dev/null
+++ b/src/Avalonia.Controls/Converters/BorderGapMaskConverter.cs
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Avalonia.Controls.Shapes;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+
+namespace Avalonia.Controls.Converters
+{
+ // Ported from https://github.com/dotnet/wpf/blob/main/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/BorderGapMaskConverter.cs
+
+ ///
+ /// Converter that generates the visual brush for
+ ///
+ public class BorderGapMaskConverter : IMultiValueConverter
+ {
+ ///
+ /// Convert a value.
+ ///
+ /// values as produced by source binding
+ /// target type
+ /// converter parameter
+ /// culture information
+ ///
+ /// Converted value.
+ /// Visual Brush that is used as the opacity mask for the Border
+ /// in the style for GroupBox.
+ ///
+ public object? Convert(IList