diff --git a/Avalonia.sln b/Avalonia.sln
index 071d0457b8..4999719676 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -559,6 +559,7 @@ Global
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
+ {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index e52430f50b..54acdd9114 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -21,12 +21,12 @@
True
-
+
True
diff --git a/samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs b/samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs
index 521d3674eb..81a5ba536f 100644
--- a/samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs
+++ b/samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs
@@ -22,8 +22,7 @@ public class EmbedSampleGtk : INativeDemoControl
var control = createDefault();
var nodes = Path.GetFullPath(Path.Combine(typeof(EmbedSample).Assembly.GetModules()[0].FullyQualifiedName,
- "..",
- "nodes.mp4"));
+ "..", "NativeControls", "Gtk", "nodes.mp4"));
_mplayer = Process.Start(new ProcessStartInfo("mplayer",
$"-vo x11 -zoom -loop 0 -wid {control.Handle.ToInt64()} \"{nodes}\"")
{
diff --git a/samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs b/samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs
index 456f77a44d..b1fef7c013 100644
--- a/samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs
+++ b/samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs
@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks;
using Avalonia.Controls.Platform;
using Avalonia.Platform.Interop;
+using Avalonia.X11.Interop;
using Avalonia.X11.NativeDialogs;
using static Avalonia.X11.NativeDialogs.Gtk;
using static Avalonia.X11.NativeDialogs.Glib;
@@ -10,8 +11,6 @@ namespace ControlCatalog.NetCore;
internal class GtkHelper
{
- private static Task s_gtkTask;
-
class FileChooser : INativeControlHostDestroyableControlHandle
{
private readonly IntPtr _widget;
@@ -38,11 +37,7 @@ internal class GtkHelper
public static INativeControlHostDestroyableControlHandle CreateGtkFileChooser(IntPtr parentXid)
{
- if (s_gtkTask == null)
- s_gtkTask = StartGtk();
- if (!s_gtkTask.Result)
- return null;
- return RunOnGlibThread(() =>
+ return GtkInteropHelper.RunOnGlibThread(() =>
{
using (var title = new Utf8Buffer("Embedded"))
{
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index d0e1bd885e..fab4622303 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -43,6 +43,7 @@
+
diff --git a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
index 282973c26a..a571a0518b 100644
--- a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
+++ b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
@@ -24,11 +24,12 @@ public class CompositingRenderer : IRendererWithCompositor
DrawingContext _recordingContext;
private HashSet _dirty = new();
private HashSet _recalculateChildren = new();
- private readonly CompositionTarget _target;
private bool _queuedUpdate;
private Action _update;
private Action _invalidateScene;
+ internal CompositionTarget CompositionTarget;
+
///
/// Asks the renderer to only draw frames on the render thread. Makes Paint to wait until frame is rendered.
///
@@ -40,8 +41,8 @@ public class CompositingRenderer : IRendererWithCompositor
_root = root;
_compositor = compositor;
_recordingContext = new DrawingContext(_recorder);
- _target = compositor.CreateCompositionTarget(root.CreateRenderTarget);
- _target.Root = ((Visual)root!.VisualRoot!).AttachToCompositor(compositor);
+ CompositionTarget = compositor.CreateCompositionTarget(root.CreateRenderTarget);
+ CompositionTarget.Root = ((Visual)root!.VisualRoot!).AttachToCompositor(compositor);
_update = Update;
_invalidateScene = InvalidateScene;
}
@@ -49,15 +50,15 @@ public class CompositingRenderer : IRendererWithCompositor
///
public bool DrawFps
{
- get => _target.DrawFps;
- set => _target.DrawFps = value;
+ get => CompositionTarget.DrawFps;
+ set => CompositionTarget.DrawFps = value;
}
///
public bool DrawDirtyRects
{
- get => _target.DrawDirtyRects;
- set => _target.DrawDirtyRects = value;
+ get => CompositionTarget.DrawDirtyRects;
+ set => CompositionTarget.DrawDirtyRects = value;
}
///
@@ -81,12 +82,11 @@ public class CompositingRenderer : IRendererWithCompositor
///
public IEnumerable HitTest(Point p, IVisual root, Func? filter)
{
- var res = _target.TryHitTest(p, filter);
+ var res = CompositionTarget.TryHitTest(p, filter);
if(res == null)
yield break;
- for (var index = res.Count - 1; index >= 0; index--)
+ foreach(var v in res)
{
- var v = res[index];
if (v is CompositionDrawListVisual dv)
{
if (filter == null || filter(dv.Visual))
@@ -234,8 +234,8 @@ public class CompositingRenderer : IRendererWithCompositor
SyncChildren(v);
_dirty.Clear();
_recalculateChildren.Clear();
- _target.Size = _root.ClientSize;
- _target.Scaling = _root.RenderScaling;
+ CompositionTarget.Size = _root.ClientSize;
+ CompositionTarget.Scaling = _root.RenderScaling;
Compositor.InvokeOnNextCommit(_invalidateScene);
}
@@ -246,24 +246,24 @@ public class CompositingRenderer : IRendererWithCompositor
public void Paint(Rect rect)
{
Update();
- _target.RequestRedraw();
+ CompositionTarget.RequestRedraw();
if(RenderOnlyOnRenderThread && Compositor.Loop.RunsInBackground)
Compositor.RequestCommitAsync().Wait();
else
- _target.ImmediateUIThreadRender();
+ CompositionTarget.ImmediateUIThreadRender();
}
- public void Start() => _target.IsEnabled = true;
+ public void Start() => CompositionTarget.IsEnabled = true;
public void Stop()
{
- _target.IsEnabled = false;
+ CompositionTarget.IsEnabled = false;
}
public void Dispose()
{
Stop();
- _target.Dispose();
+ CompositionTarget.Dispose();
// Wait for the composition batch to be applied and rendered to guarantee that
// render target is not used anymore and can be safely disposed
diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs b/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs
index 47cfcd325b..49aea1c3dc 100644
--- a/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs
@@ -54,13 +54,20 @@ internal class CompositionDrawListVisual : CompositionContainerVisual
internal override bool HitTest(Point pt, Func? filter)
{
- if (DrawList == null)
+ var custom = Visual as ICustomHitTest;
+ if (DrawList == null && custom == null)
return false;
if (filter != null && !filter(Visual))
return false;
- if (Visual is ICustomHitTest custom)
+ if (custom != null)
+ {
+ // Simulate the old behavior
+ // TODO: Change behavior once legacy renderers are removed
+ pt += new Point(Offset.X, Offset.Y);
return custom.HitTest(pt);
- foreach (var op in DrawList)
+ }
+
+ foreach (var op in DrawList!)
if (op.Item.HitTest(pt))
return true;
return false;
diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs
index 25bbd4dc88..01b2d0d5d9 100644
--- a/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs
@@ -62,7 +62,7 @@ namespace Avalonia.Rendering.Composition
bool TryGetInvertedTransform(CompositionVisual visual, out Matrix matrix)
{
- var m = visual.TryGetServerTransform();
+ var m = visual.TryGetServerGlobalTransform();
if (m == null)
{
matrix = default;
@@ -73,52 +73,44 @@ namespace Avalonia.Rendering.Composition
return m33.TryInvert(out matrix);
}
- bool TryTransformTo(CompositionVisual visual, ref Point v)
+ bool TryTransformTo(CompositionVisual visual, Point globalPoint, out Point v)
{
+ v = default;
if (TryGetInvertedTransform(visual, out var m))
{
- v = v * m;
+ v = globalPoint * m;
return true;
}
return false;
}
- bool HitTestCore(CompositionVisual visual, Point point, PooledList result,
+ void HitTestCore(CompositionVisual visual, Point globalPoint, PooledList result,
Func? filter)
{
- //TODO: Check readback too
if (visual.Visible == false)
- return false;
- if (!TryTransformTo(visual, ref point))
- return false;
+ return;
+ if (!TryTransformTo(visual, globalPoint, out var point))
+ return;
if (visual.ClipToBounds
&& (point.X < 0 || point.Y < 0 || point.X > visual.Size.X || point.Y > visual.Size.Y))
- return false;
- if (visual.Clip?.FillContains(point) == false)
- return false;
+ return;
- bool success = false;
- // Hit-test the current node
- if (visual.HitTest(point, filter))
- {
- result.Add(visual);
- success = true;
- }
-
- // Inspect children too
+ if (visual.Clip?.FillContains(point) == false)
+ return;
+
+ // Inspect children
if (visual is CompositionContainerVisual cv)
for (var c = cv.Children.Count - 1; c >= 0; c--)
{
var ch = cv.Children[c];
- var hit = HitTestCore(ch, point, result, filter);
- if (hit)
- return true;
+ HitTestCore(ch, globalPoint, result, filter);
}
-
- return success;
-
+
+ // Hit-test the current node
+ if (visual.HitTest(point, filter))
+ result.Add(visual);
}
///
diff --git a/src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs b/src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs
new file mode 100644
index 0000000000..045a4f8cc6
--- /dev/null
+++ b/src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs
@@ -0,0 +1,6 @@
+namespace Avalonia.Rendering.Composition;
+
+internal interface ICompositionTargetDebugEvents
+{
+ void RectInvalidated(Rect rc);
+}
\ No newline at end of file
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
index 0fde86e484..882b66bf70 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
@@ -33,7 +33,7 @@ namespace Avalonia.Rendering.Composition.Server
private HashSet _attachedVisuals = new();
private Queue _adornerUpdateQueue = new();
-
+ public ICompositionTargetDebugEvents? DebugEvents { get; set; }
public ReadbackIndices Readback { get; } = new();
public int RenderedVisuals { get; set; }
@@ -173,6 +173,7 @@ namespace Avalonia.Rendering.Composition.Server
if(rect.IsEmpty)
return;
var snapped = SnapToDevicePixels(rect, Scaling);
+ DebugEvents?.RectInvalidated(rect);
_dirtyRect = _dirtyRect.Union(snapped);
_redrawRequested = true;
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
index 6fdf105e58..c0e487f209 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
@@ -119,14 +119,15 @@ namespace Avalonia.Rendering.Composition.Server
var oldTransformedContentBounds = TransformedOwnContentBounds;
var oldCombinedTransformedClipBounds = _combinedTransformedClipBounds;
-
- var dirtyOldBounds = false;
+
if (_parent?.IsDirtyComposition == true)
{
IsDirtyComposition = true;
_isDirtyForUpdate = true;
- dirtyOldBounds = true;
}
+
+ var invalidateOldBounds = _isDirtyForUpdate;
+ var invalidateNewBounds = _isDirtyForUpdate;
GlobalTransformMatrix = newTransform;
@@ -157,30 +158,20 @@ namespace Avalonia.Rendering.Composition.Server
EffectiveOpacity = Opacity * (Parent?.EffectiveOpacity ?? 1);
- IsVisibleInFrame = Visible && EffectiveOpacity > 0.04 && !_isBackface &&
+ IsVisibleInFrame = _parent?.IsVisibleInFrame != false && Visible && EffectiveOpacity > 0.04 && !_isBackface &&
!_combinedTransformedClipBounds.IsEmpty;
-
- if (wasVisible != IsVisibleInFrame)
- _isDirtyForUpdate = true;
-
- // Invalidate previous rect and queue new rect based on visibility
- if (positionChanged)
- {
- if (wasVisible)
- dirtyOldBounds = true;
- if (IsVisibleInFrame)
- _isDirtyForUpdate = true;
+ if (wasVisible != IsVisibleInFrame || positionChanged)
+ {
+ invalidateOldBounds |= wasVisible;
+ invalidateNewBounds |= IsVisibleInFrame;
}
-
+
// Invalidate new bounds
- if (IsVisibleInFrame && _isDirtyForUpdate)
- {
- dirtyOldBounds = true;
+ if (invalidateNewBounds)
AddDirtyRect(TransformedOwnContentBounds.Intersect(_combinedTransformedClipBounds));
- }
- if (dirtyOldBounds && wasVisible)
+ if (invalidateOldBounds)
AddDirtyRect(oldTransformedContentBounds.Intersect(oldCombinedTransformedClipBounds));
@@ -190,7 +181,7 @@ namespace Avalonia.Rendering.Composition.Server
var i = Root!.Readback;
ref var readback = ref GetReadback(i.WriteIndex);
readback.Revision = root.Revision;
- readback.Matrix = CombinedTransformMatrix;
+ readback.Matrix = GlobalTransformMatrix;
readback.TargetId = Root.Id;
readback.Visible = IsVisibleInFrame;
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
index 65237473fb..6db480a966 100644
--- a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
@@ -72,7 +72,7 @@ internal class BatchStreamWriter : IDisposable
var size = Unsafe.SizeOf();
if (_currentDataSegment.Data == IntPtr.Zero || _currentDataSegment.ElementCount + size > _memoryPool.BufferSize)
NextDataSegment();
- *(T*)((byte*)_currentDataSegment.Data + _currentDataSegment.ElementCount) = item;
+ Unsafe.WriteUnaligned((byte*)_currentDataSegment.Data + _currentDataSegment.ElementCount, item);
_currentDataSegment.ElementCount += size;
}
@@ -123,7 +123,7 @@ internal class BatchStreamReader : IDisposable
if (_memoryOffset + size > _currentDataSegment.ElementCount)
throw new InvalidOperationException("Attempted to read more memory then left in the current segment");
- var rv = *(T*)((byte*)_currentDataSegment.Data + _memoryOffset);
+ var rv = Unsafe.ReadUnaligned((byte*)_currentDataSegment.Data + _memoryOffset);
_memoryOffset += size;
if (_memoryOffset == _currentDataSegment.ElementCount)
{
@@ -181,4 +181,4 @@ internal class BatchStreamReader : IDisposable
while (_input.Objects.Count > 0)
_objectPool.Return(_input.Objects.Dequeue().Data);
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs
index 32b4ed3026..b0a89c6f92 100644
--- a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
+using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Rendering.Composition.Transport;
@@ -17,6 +17,7 @@ internal abstract class BatchStreamPoolBase : IDisposable
int _usage;
readonly int[] _usageStatistics = new int[10];
int _usageStatisticsSlot;
+ bool _reclaimImmediately;
public int CurrentUsage => _usage;
public int CurrentPool => _pool.Count;
@@ -27,7 +28,10 @@ internal abstract class BatchStreamPoolBase : IDisposable
GC.SuppressFinalize(needsFinalize);
var updateRef = new WeakReference>(this);
- StartUpdateTimer(startTimer, updateRef);
+ if (AvaloniaLocator.Current.GetService() == null)
+ _reclaimImmediately = true;
+ else
+ StartUpdateTimer(startTimer, updateRef);
}
static void StartUpdateTimer(Action>? startTimer, WeakReference> updateRef)
@@ -90,7 +94,7 @@ internal abstract class BatchStreamPoolBase : IDisposable
lock (_pool)
{
_usage--;
- if (!_disposed)
+ if (!_disposed && !_reclaimImmediately)
{
_pool.Push(item);
return;
diff --git a/src/Avalonia.Base/Rendering/Composition/Visual.cs b/src/Avalonia.Base/Rendering/Composition/Visual.cs
index f9e1eae2ab..7ebbb0aa96 100644
--- a/src/Avalonia.Base/Rendering/Composition/Visual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Visual.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Rendering.Composition
}
}
- internal Matrix4x4? TryGetServerTransform()
+ internal Matrix4x4? TryGetServerGlobalTransform()
{
if (Root == null)
return null;
diff --git a/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs b/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs
index ca6020128c..ff222658db 100644
--- a/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs
+++ b/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs
@@ -268,11 +268,11 @@ namespace Avalonia.Collections
public static DataGridSortDescription FromComparer(IComparer comparer, ListSortDirection direction = ListSortDirection.Ascending)
{
- return new DataGridComparerSortDesctiption(comparer, direction);
+ return new DataGridComparerSortDescription(comparer, direction);
}
}
- public class DataGridComparerSortDesctiption : DataGridSortDescription
+ public class DataGridComparerSortDescription : DataGridSortDescription
{
private readonly IComparer _innerComparer;
private readonly ListSortDirection _direction;
@@ -281,7 +281,7 @@ namespace Avalonia.Collections
public IComparer SourceComparer => _innerComparer;
public override IComparer
/// The menu interaction handler.
- public MenuBase(IMenuInteractionHandler interactionHandler)
+ protected MenuBase(IMenuInteractionHandler interactionHandler)
{
InteractionHandler = interactionHandler ?? throw new ArgumentNullException(nameof(interactionHandler));
}
diff --git a/src/Avalonia.Controls/TrayIcon.cs b/src/Avalonia.Controls/TrayIcon.cs
index 20c8dff8ea..41a1abd838 100644
--- a/src/Avalonia.Controls/TrayIcon.cs
+++ b/src/Avalonia.Controls/TrayIcon.cs
@@ -61,6 +61,10 @@ namespace Avalonia.Controls
args.NewValue.Value.CollectionChanged += Icons_CollectionChanged;
}
}
+ else
+ {
+ throw new InvalidOperationException("TrayIcon.Icons must be set on the Application.");
+ }
});
var app = Application.Current ?? throw new InvalidOperationException("Application not yet initialized.");
@@ -123,9 +127,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty IsVisibleProperty =
Visual.IsVisibleProperty.AddOwner();
- public static void SetIcons(AvaloniaObject o, TrayIcons trayIcons) => o.SetValue(IconsProperty, trayIcons);
+ public static void SetIcons(Application o, TrayIcons trayIcons) => o.SetValue(IconsProperty, trayIcons);
- public static TrayIcons GetIcons(AvaloniaObject o) => o.GetValue(IconsProperty);
+ public static TrayIcons GetIcons(Application o) => o.GetValue(IconsProperty);
///
/// Gets or sets the property of a TrayIcon.
diff --git a/src/Avalonia.FreeDesktop/DBusHelper.cs b/src/Avalonia.FreeDesktop/DBusHelper.cs
index 9f9d75b411..ef99838208 100644
--- a/src/Avalonia.FreeDesktop/DBusHelper.cs
+++ b/src/Avalonia.FreeDesktop/DBusHelper.cs
@@ -24,8 +24,7 @@ namespace Avalonia.FreeDesktop
if (_ctx is not null)
_ctx?.Post(d, state);
else
- lock (_lock)
- d(state);
+ d(state);
}
}
diff --git a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
index c17d5b993c..7974069184 100644
--- a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
+++ b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
@@ -15,27 +15,26 @@ namespace Avalonia.FreeDesktop
{
internal class DBusSystemDialog : BclStorageProvider
{
- private static readonly Lazy s_fileChooser = new(() =>
+ private static readonly Lazy s_fileChooser = new(() => DBusHelper.Connection?
+ .CreateProxy("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"));
+
+ internal static async Task TryCreate(IPlatformHandle handle)
{
- var fileChooser = DBusHelper.Connection?.CreateProxy("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop");
- if (fileChooser is null)
- return null;
- try
+ if (handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser)
{
- _ = fileChooser.GetVersionAsync();
- return fileChooser;
- }
- catch (Exception e)
- {
- Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform)?.Log(null, $"Unable to connect to org.freedesktop.portal.Desktop: {e.Message}");
- return null;
+ try
+ {
+ await fileChooser.GetVersionAsync();
+ return new DBusSystemDialog(fileChooser, handle);
+ }
+ catch (Exception e)
+ {
+ Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform)?.Log(null, $"Unable to connect to org.freedesktop.portal.Desktop: {e.Message}");
+ return null;
+ }
}
- });
- internal static DBusSystemDialog? TryCreate(IPlatformHandle handle)
- {
- return handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser
- ? new DBusSystemDialog(fileChooser, handle) : null;
+ return null;
}
private readonly IFileChooser _fileChooser;
diff --git a/src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml b/src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml
index 81bd8f39c5..3b0019eea1 100644
--- a/src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml
+++ b/src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml
@@ -14,6 +14,7 @@