From 701eb9976cd567c231b8edd0c79926e46b9161fd Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Thu, 24 Nov 2022 14:08:31 +0100 Subject: [PATCH 01/35] Make KeyEventArgs and TextInputEventArgs public again --- src/Avalonia.Base/Input/KeyEventArgs.cs | 2 +- src/Avalonia.Base/Input/TextInputEventArgs.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Input/KeyEventArgs.cs b/src/Avalonia.Base/Input/KeyEventArgs.cs index 39c9766105..35fa549995 100644 --- a/src/Avalonia.Base/Input/KeyEventArgs.cs +++ b/src/Avalonia.Base/Input/KeyEventArgs.cs @@ -5,7 +5,7 @@ namespace Avalonia.Input { public class KeyEventArgs : RoutedEventArgs { - internal KeyEventArgs() + public KeyEventArgs() { } diff --git a/src/Avalonia.Base/Input/TextInputEventArgs.cs b/src/Avalonia.Base/Input/TextInputEventArgs.cs index 787bf1abd3..a027bec0c6 100644 --- a/src/Avalonia.Base/Input/TextInputEventArgs.cs +++ b/src/Avalonia.Base/Input/TextInputEventArgs.cs @@ -4,7 +4,7 @@ namespace Avalonia.Input { public class TextInputEventArgs : RoutedEventArgs { - internal TextInputEventArgs() + public TextInputEventArgs() { } From 4e6f379334430a6fa5139a15c3d1d03484a6a1e7 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Mon, 5 Dec 2022 20:50:13 +0300 Subject: [PATCH 02/35] Make all TextElement properties affect TextPresenter's render --- src/Avalonia.Controls/Presenters/TextPresenter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index cc1fa6c513..1381160550 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -110,7 +110,8 @@ namespace Avalonia.Controls.Presenters static TextPresenter() { - AffectsRender(CaretBrushProperty, SelectionBrushProperty); + AffectsRender(CaretBrushProperty, SelectionBrushProperty, + TextElement.FontFamilyProperty, TextElement.FontSizeProperty, TextElement.FontStyleProperty, TextElement.FontWeightProperty, TextElement.FontStretchProperty, TextElement.ForegroundProperty); } public TextPresenter() From 3b8a2a9be2153a4c9660f17f1c53c450ebe15b89 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Tue, 6 Dec 2022 12:14:49 +0300 Subject: [PATCH 03/35] Reformat AffectRender's parameters --- src/Avalonia.Controls/Presenters/TextPresenter.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 1381160550..683b8f1768 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -110,8 +110,15 @@ namespace Avalonia.Controls.Presenters static TextPresenter() { - AffectsRender(CaretBrushProperty, SelectionBrushProperty, - TextElement.FontFamilyProperty, TextElement.FontSizeProperty, TextElement.FontStyleProperty, TextElement.FontWeightProperty, TextElement.FontStretchProperty, TextElement.ForegroundProperty); + AffectsRender( + CaretBrushProperty, + SelectionBrushProperty, + TextElement.FontFamilyProperty, + TextElement.FontSizeProperty, + TextElement.FontStyleProperty, + TextElement.FontWeightProperty, + TextElement.FontStretchProperty, + TextElement.ForegroundProperty); } public TextPresenter() From 0320fc703350195ecadb0229b95bc438b1833115 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Tue, 6 Dec 2022 21:34:25 +0300 Subject: [PATCH 04/35] Remove unnecessary TextElement properties from TextPresenter's AffectRender --- src/Avalonia.Controls/Presenters/TextPresenter.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 683b8f1768..7eaff49910 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -110,15 +110,7 @@ namespace Avalonia.Controls.Presenters static TextPresenter() { - AffectsRender( - CaretBrushProperty, - SelectionBrushProperty, - TextElement.FontFamilyProperty, - TextElement.FontSizeProperty, - TextElement.FontStyleProperty, - TextElement.FontWeightProperty, - TextElement.FontStretchProperty, - TextElement.ForegroundProperty); + AffectsRender(CaretBrushProperty, SelectionBrushProperty, TextElement.ForegroundProperty); } public TextPresenter() From 7d0367119cb9330635127616238f9bfe1c9ca424 Mon Sep 17 00:00:00 2001 From: startewho Date: Fri, 9 Dec 2022 13:21:49 +0800 Subject: [PATCH 05/35] fix the separator can not show --- src/Avalonia.Controls/NativeMenuItemSeparator.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/NativeMenuItemSeparator.cs b/src/Avalonia.Controls/NativeMenuItemSeparator.cs index 97278130b1..f55d714884 100644 --- a/src/Avalonia.Controls/NativeMenuItemSeparator.cs +++ b/src/Avalonia.Controls/NativeMenuItemSeparator.cs @@ -1,7 +1,10 @@ namespace Avalonia.Controls { - public class NativeMenuItemSeparator : NativeMenuItemBase + public class NativeMenuItemSeparator : NativeMenuItem { - + public NativeMenuItemSeparator() + { + Header = "-"; + } } } From e29257c52bdd22371de5588c302630f64d23d566 Mon Sep 17 00:00:00 2001 From: Michal Tomecki Date: Sun, 11 Dec 2022 23:15:57 +0100 Subject: [PATCH 06/35] Fixed incorrect startup window position on Linux --- src/Avalonia.X11/X11Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 160401c5fc..955096e18a 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -298,7 +298,7 @@ namespace Avalonia.X11 min_height = min.Height }; hints.height_inc = hints.width_inc = 1; - var flags = XSizeHintsFlags.PMinSize | XSizeHintsFlags.PResizeInc | XSizeHintsFlags.PPosition | XSizeHintsFlags.PSize; + var flags = XSizeHintsFlags.PMinSize | XSizeHintsFlags.PResizeInc; // People might be passing double.MaxValue if (max.Width < 100000 && max.Height < 100000) { From 07e9bad0aed1b26f70dd952051261038f11f3a4c Mon Sep 17 00:00:00 2001 From: Michal Tomecki Date: Mon, 12 Dec 2022 12:11:35 +0100 Subject: [PATCH 07/35] Updated Window startup positioning behaviour on Linux to be more consistent with WPF behaviour --- src/Avalonia.X11/X11Window.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 955096e18a..62e4441066 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -57,6 +57,7 @@ namespace Avalonia.X11 private TransparencyHelper _transparencyHelper; private RawEventGrouper _rawEventGrouper; private bool _useRenderWindow = false; + private bool _usePositioningFlags = false; enum XSyncState { @@ -299,6 +300,9 @@ namespace Avalonia.X11 }; hints.height_inc = hints.width_inc = 1; var flags = XSizeHintsFlags.PMinSize | XSizeHintsFlags.PResizeInc; + if (_usePositioningFlags) + flags |= XSizeHintsFlags.PPosition | XSizeHintsFlags.PSize; + // People might be passing double.MaxValue if (max.Width < 100000 && max.Height < 100000) { @@ -958,6 +962,9 @@ namespace Avalonia.X11 get => _position ?? default; set { + _usePositioningFlags = true; + UpdateSizeHints(null); + var changes = new XWindowChanges { x = (int)value.X, From 4bb3a0d8bebce6eeadca964f36f729f55bc46621 Mon Sep 17 00:00:00 2001 From: Julian Date: Mon, 12 Dec 2022 11:55:28 +0000 Subject: [PATCH 08/35] Add missing SystemControlBackgroundAltLowBrush in fluent theme --- src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml | 1 + src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml index 89841c92c0..0192fb1b54 100644 --- a/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml @@ -36,6 +36,7 @@ + diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml index 89b646fb52..a9e5ed949a 100644 --- a/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml @@ -36,6 +36,7 @@ + From 1e5c0b2911d5bace24b347897d93b60cc342f364 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Tue, 13 Dec 2022 10:36:48 +0100 Subject: [PATCH 09/35] feat: Linked AvaloniaResource Items --- .../GenerateAvaloniaResourcesTask.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs index fad6ad397b..65681a2d28 100644 --- a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs +++ b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs @@ -7,7 +7,7 @@ using System.Text; using Avalonia.Markup.Xaml.PortableXaml; using Avalonia.Utilities; using Microsoft.Build.Framework; -using SPath=System.IO.Path; +using SPath = System.IO.Path; namespace Avalonia.Build.Tasks { public class GenerateAvaloniaResourcesTask : ITask @@ -30,12 +30,17 @@ namespace Avalonia.Build.Tasks private byte[] _data; private string _sourcePath; - public Source(string relativePath, string root) + public Source(ITaskItem avaloniaResourceItem, string root) { root = SPath.GetFullPath(root); - Path = "/" + relativePath.Replace('\\', '/'); + var relativePath = avaloniaResourceItem.ItemSpec; _sourcePath = SPath.Combine(root, relativePath); Size = (int)new FileInfo(_sourcePath).Length; + var link = avaloniaResourceItem.GetMetadata("Link"); + var path = !string.IsNullOrEmpty(link) + ? link + : relativePath; + Path = "/" + path.Replace('\\', '/'); } public string SystemPath => _sourcePath ?? Path; @@ -65,8 +70,7 @@ namespace Avalonia.Build.Tasks List BuildResourceSources() => Resources.Select(r => { - - var src = new Source(r.ItemSpec, Root); + var src = new Source(r, Root); BuildEngine.LogMessage(FormattableString.Invariant($"avares -> name:{src.Path}, path: {src.SystemPath}, size:{src.Size}, ItemSpec:{r.ItemSpec}"), _reportImportance); return src; }).ToList(); @@ -93,15 +97,15 @@ namespace Avalonia.Build.Tasks ms.CopyTo(output); foreach (var s in sources) { - using(var input = s.Open()) + using (var input = s.Open()) input.CopyTo(output); } } private bool PreProcessXamlFiles(List sources) { - var typeToXamlIndex = new Dictionary(); - + var typeToXamlIndex = new Dictionary(); + foreach (var s in sources.ToArray()) { if (s.Path.ToLowerInvariant().EndsWith(".xaml") || s.Path.ToLowerInvariant().EndsWith(".paml") || s.Path.ToLowerInvariant().EndsWith(".axaml")) @@ -111,7 +115,7 @@ namespace Avalonia.Build.Tasks { info = XamlFileInfo.Parse(s.ReadAsString()); } - catch(Exception e) + catch (Exception e) { BuildEngine.LogError(BuildEngineErrorCode.InvalidXAML, s.SystemPath, "File doesn't contain valid XAML: " + e); return false; @@ -121,7 +125,7 @@ namespace Avalonia.Build.Tasks { if (typeToXamlIndex.ContainsKey(info.XClass)) { - + BuildEngine.LogError(BuildEngineErrorCode.DuplicateXClass, s.SystemPath, $"Duplicate x:Class directive, {info.XClass} is already used in {typeToXamlIndex[info.XClass]}"); return false; From 58b404a3ab25a8a7e6df0300f6356ce7f9e01dc6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 13 Dec 2022 18:25:37 +0100 Subject: [PATCH 10/35] Added failing test for #7974. --- .../Selection/SelectionModelTests_Single.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs index 668af3b5d7..1b629be695 100644 --- a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs +++ b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Specialized; +using System.Linq; using Avalonia.Collections; using Avalonia.Controls.Selection; using Avalonia.Controls.Utils; @@ -1144,6 +1145,24 @@ namespace Avalonia.Controls.UnitTests.Selection Assert.Equal(new[] { "foo" }, target.SelectedItems); Assert.Equal(0, target.AnchorIndex); } + + [Fact] + public void SelectedItems_Indexer_Is_Correct() + { + // Issue #7974 + var target = CreateTarget(); + var raised = 0; + + target.SelectionChanged += (s, e) => + { + Assert.Equal("bar", e.SelectedItems.First()); + Assert.Equal("bar", e.SelectedItems[0]); + ++raised; + }; + + target.Select(1); + Assert.Equal(1, raised); + } } public class BatchUpdate From 467303099cc5ebcb8e091c508d888d8c66e690c8 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 13 Dec 2022 18:32:52 +0100 Subject: [PATCH 11/35] Fix SelectedItems indexer. The index is an index into `Ranges`, not `Items`. Fixes #7974. --- src/Avalonia.Controls/Selection/SelectedItems.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Selection/SelectedItems.cs b/src/Avalonia.Controls/Selection/SelectedItems.cs index 4fbcfde438..ef642b7bdc 100644 --- a/src/Avalonia.Controls/Selection/SelectedItems.cs +++ b/src/Avalonia.Controls/Selection/SelectedItems.cs @@ -35,9 +35,9 @@ namespace Avalonia.Controls.Selection { return _owner.SelectedItem; } - else if (Items is object) + else if (Items is not null && Ranges is not null) { - return Items[index]; + return Items[IndexRange.GetAt(Ranges, index)]; } else { From 7deed3555674f46b1ef1bb2cc4e75043b3c0c383 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Wed, 14 Dec 2022 10:56:02 +0000 Subject: [PATCH 12/35] add refresh button to manager file chooser --- .../Controls/ManagedFileChooser.xaml | 7 +++++-- .../Controls/ManagedFileChooser.xaml | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml index d1707d0af2..63b3d46a41 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml @@ -153,9 +153,13 @@ - + @@ -322,7 +326,6 @@ diff --git a/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml b/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml index ba1b35e2ee..945622f22f 100644 --- a/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml +++ b/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml @@ -9,17 +9,16 @@ - - From 6b07b9016198e444850c17b8c2e4421d139e1d4b Mon Sep 17 00:00:00 2001 From: Dmitry Zhelnin Date: Fri, 16 Dec 2022 16:38:53 +0300 Subject: [PATCH 27/35] DataGridValueConverter: fix processing of nullable values --- .../DataGridValueConverter.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs b/src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs index 6144679b60..c823ee1b9c 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs @@ -22,14 +22,18 @@ namespace Avalonia.Controls return DefaultValueConverter.Instance.Convert(value, targetType, parameter, culture); } - // This suppresses a warning saying that we should use String.IsNullOrEmpty instead of a string - // comparison, but in this case we want to explicitly check for Empty and not Null. + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (targetType != null && targetType.IsNullableType()) { var strValue = value as string; - if (string.IsNullOrEmpty(strValue)) + + // This suppresses a warning saying that we should use String.IsNullOrEmpty instead of a string + // comparison, but in this case we want to explicitly check for Empty and not Null. +#pragma warning disable CA1820 + if (strValue == string.Empty) +#pragma warning restore CA1820 { return null; } From e0c2d5b63dcc92f5af44433e9e20c88cd9f0c8a4 Mon Sep 17 00:00:00 2001 From: Dmitry Zhelnin Date: Fri, 16 Dec 2022 18:29:34 +0300 Subject: [PATCH 28/35] DataGridColumn: change access modifier of OwningGrid property to protected internal --- src/Avalonia.Controls.DataGrid/DataGridColumn.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs index d417c87746..2b715d6a9f 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs @@ -50,10 +50,13 @@ namespace Avalonia.Controls InheritsWidth = true; } - internal DataGrid OwningGrid + /// + /// Gets the control that contains this column. + /// + protected internal DataGrid OwningGrid { get; - set; + internal set; } internal int Index From 04db818a477471ace38b684c5557dc486d438134 Mon Sep 17 00:00:00 2001 From: 0xDB6 <120456350+0xDB6@users.noreply.github.com> Date: Fri, 16 Dec 2022 16:30:56 +0100 Subject: [PATCH 29/35] Defer execution of UnregisterClass to fix RWM atom table leak (#9700) --- .../Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 4 ++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 15 +++++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index a7cca5b0f3..f828b156da 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1409,7 +1409,7 @@ namespace Avalonia.Win32.Interop [DllImport("user32.dll")] public static extern bool TranslateMessage(ref MSG lpMsg); - [DllImport("user32.dll")] + [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern bool UnregisterClass(string lpClassName, IntPtr hInstance); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetWindowTextW")] diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index fe7d881f11..060366a8ac 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -10,6 +10,7 @@ using Avalonia.Controls.Remote; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Platform; +using Avalonia.Threading; using Avalonia.Win32.Automation; using Avalonia.Win32.Input; using Avalonia.Win32.Interop.Automation; @@ -106,6 +107,9 @@ namespace Avalonia.Win32 _touchDevice?.Dispose(); //Free other resources Dispose(); + + // Schedule cleanup of anything that requires window to be destroyed + Dispatcher.UIThread.Post(AfterCloseCleanup); return IntPtr.Zero; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9e11959101..fa4517dc92 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -643,12 +643,6 @@ namespace Avalonia.Win32 _hwnd = IntPtr.Zero; } - if (_className != null) - { - UnregisterClass(_className, GetModuleHandle(null)); - _className = null; - } - _framebuffer.Dispose(); } @@ -1144,6 +1138,15 @@ namespace Avalonia.Win32 } } + private void AfterCloseCleanup() + { + if (_className != null) + { + UnregisterClass(_className, GetModuleHandle(null)); + _className = null; + } + } + private void MaximizeWithoutCoveringTaskbar() { IntPtr monitor = MonitorFromWindow(_hwnd, MONITOR.MONITOR_DEFAULTTONEAREST); From c208e93281a8293a49a97d3f82ca8aea643fb971 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 17 Dec 2022 01:30:16 +0600 Subject: [PATCH 30/35] Logging --- .../Server/ServerCustomCompositionVisual.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs index 555972876d..227df87a87 100644 --- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs +++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs @@ -12,7 +12,7 @@ internal class ServerCompositionCustomVisual : ServerCompositionContainerVisual, private bool _wantsNextAnimationFrameAfterTick; internal ServerCompositionCustomVisual(ServerCompositor compositor, CompositionCustomVisualHandler handler) : base(compositor) { - _handler = handler; + _handler = handler ?? throw new ArgumentNullException(nameof(handler)); _handler.Attach(this); } @@ -29,7 +29,7 @@ internal class ServerCompositionCustomVisual : ServerCompositionContainerVisual, catch (Exception e) { Logger.TryGet(LogEventLevel.Error, LogArea.Visual) - ?.Log(_handler, $"Exception in {nameof(CompositionCustomVisualHandler)} {{0}}", e); + ?.Log(_handler, $"Exception in {_handler.GetType().Name}.{nameof(CompositionCustomVisualHandler.OnMessage)} {{0}}", e); } } } @@ -68,7 +68,15 @@ internal class ServerCompositionCustomVisual : ServerCompositionContainerVisual, protected override void RenderCore(CompositorDrawingContextProxy canvas, Rect currentTransformedClip) { - var context = new ImmediateDrawingContext(canvas, false); - _handler.OnRender(context); + using var context = new ImmediateDrawingContext(canvas, false); + try + { + _handler.OnRender(context); + } + catch (Exception e) + { + Logger.TryGet(LogEventLevel.Error, LogArea.Visual) + ?.Log(_handler, $"Exception in {_handler.GetType().Name}.{nameof(CompositionCustomVisualHandler.OnRender)} {{0}}", e); + } } } \ No newline at end of file From a5e018f77957d50f6ace60b034f7bf24c0092af0 Mon Sep 17 00:00:00 2001 From: Michal Tomecki Date: Fri, 16 Dec 2022 20:39:43 +0100 Subject: [PATCH 31/35] Changed X11Window/Position UpdateSizeHints to only fire if it's not already set --- src/Avalonia.X11/X11Window.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 62e4441066..890b49344c 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -962,8 +962,11 @@ namespace Avalonia.X11 get => _position ?? default; set { - _usePositioningFlags = true; - UpdateSizeHints(null); + if(!_usePositioningFlags) + { + _usePositioningFlags = true; + UpdateSizeHints(null); + } var changes = new XWindowChanges { From cfb8a896fa7010333d5c4e7ec82c34868ba5a639 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 17 Dec 2022 11:49:29 -0500 Subject: [PATCH 32/35] Modernize ComboBox properties --- src/Avalonia.Controls/ComboBox.cs | 71 ++++++++++++++++--------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index f02df2e9c1..564a2e478e 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -95,10 +95,9 @@ namespace Avalonia.Controls { ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); FocusableProperty.OverrideDefaultValue(true); - SelectedItemProperty.Changed.AddClassHandler((x, e) => x.SelectedItemChanged(e)); - KeyDownEvent.AddClassHandler((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel); IsTextSearchEnabledProperty.OverrideDefaultValue(true); - IsDropDownOpenProperty.Changed.AddClassHandler((x, e) => x.DropdownChanged(e)); + + KeyDownEvent.AddClassHandler((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel); } /// @@ -106,8 +105,8 @@ namespace Avalonia.Controls /// public bool IsDropDownOpen { - get { return _isDropDownOpen; } - set { SetAndRaise(IsDropDownOpenProperty, ref _isDropDownOpen, value); } + get => _isDropDownOpen; + set => SetAndRaise(IsDropDownOpenProperty, ref _isDropDownOpen, value); } /// @@ -115,8 +114,8 @@ namespace Avalonia.Controls /// public double MaxDropDownHeight { - get { return GetValue(MaxDropDownHeightProperty); } - set { SetValue(MaxDropDownHeightProperty, value); } + get => GetValue(MaxDropDownHeightProperty); + set => SetValue(MaxDropDownHeightProperty, value); } /// @@ -124,8 +123,8 @@ namespace Avalonia.Controls /// protected object? SelectionBoxItem { - get { return _selectionBoxItem; } - set { SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); } + get => _selectionBoxItem; + set => SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); } /// @@ -133,8 +132,8 @@ namespace Avalonia.Controls /// public string? PlaceholderText { - get { return GetValue(PlaceholderTextProperty); } - set { SetValue(PlaceholderTextProperty, value); } + get => GetValue(PlaceholderTextProperty); + set => SetValue(PlaceholderTextProperty, value); } /// @@ -142,8 +141,8 @@ namespace Avalonia.Controls /// public IBrush? PlaceholderForeground { - get { return GetValue(PlaceholderForegroundProperty); } - set { SetValue(PlaceholderForegroundProperty, value); } + get => GetValue(PlaceholderForegroundProperty); + set => SetValue(PlaceholderForegroundProperty, value); } /// @@ -151,8 +150,8 @@ namespace Avalonia.Controls /// public ItemVirtualizationMode VirtualizationMode { - get { return GetValue(VirtualizationModeProperty); } - set { SetValue(VirtualizationModeProperty, value); } + get => GetValue(VirtualizationModeProperty); + set => SetValue(VirtualizationModeProperty, value); } /// @@ -160,8 +159,8 @@ namespace Avalonia.Controls /// public HorizontalAlignment HorizontalContentAlignment { - get { return GetValue(HorizontalContentAlignmentProperty); } - set { SetValue(HorizontalContentAlignmentProperty, value); } + get => GetValue(HorizontalContentAlignmentProperty); + set => SetValue(HorizontalContentAlignmentProperty, value); } /// @@ -169,8 +168,8 @@ namespace Avalonia.Controls /// public VerticalAlignment VerticalContentAlignment { - get { return GetValue(VerticalContentAlignmentProperty); } - set { SetValue(VerticalContentAlignmentProperty, value); } + get => GetValue(VerticalContentAlignmentProperty); + set => SetValue(VerticalContentAlignmentProperty, value); } /// @@ -182,6 +181,7 @@ namespace Avalonia.Controls ComboBoxItem.ContentTemplateProperty); } + /// protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); @@ -234,7 +234,7 @@ namespace Avalonia.Controls } // This part of code is needed just to acquire initial focus, subsequent focus navigation will be done by ItemsControl. else if (IsDropDownOpen && SelectedIndex < 0 && ItemCount > 0 && - (e.Key == Key.Up || e.Key == Key.Down) && IsFocused == true) + (e.Key == Key.Up || e.Key == Key.Down) && IsFocused == true) { var firstChild = Presenter?.Panel?.Children.FirstOrDefault(c => CanFocus(c)); if (firstChild != null) @@ -304,12 +304,11 @@ namespace Avalonia.Controls e.Handled = true; } } + PseudoClasses.Set(pcPressed, false); base.OnPointerReleased(e); - } - /// protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { @@ -324,6 +323,22 @@ namespace Avalonia.Controls _popup.Closed += PopupClosed; } + /// + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + if (change.Property == SelectedItemProperty) + { + UpdateSelectionBoxItem(change.NewValue); + TryFocusSelectedItem(); + } + else if (change.Property == IsDropDownOpenProperty) + { + PseudoClasses.Set(pcDropdownOpen, change.GetNewValue()); + } + + base.OnPropertyChanged(change); + } + protected override AutomationPeer OnCreateAutomationPeer() { return new ComboBoxAutomationPeer(this); @@ -384,12 +399,6 @@ namespace Avalonia.Controls } } - private void SelectedItemChanged(AvaloniaPropertyChangedEventArgs e) - { - UpdateSelectionBoxItem(e.NewValue); - TryFocusSelectedItem(); - } - private void TryFocusSelectedItem() { var selectedIndex = SelectedIndex; @@ -489,11 +498,5 @@ namespace Avalonia.Controls MoveSelection(NavigationDirection.Previous, WrapSelection); } } - - private void DropdownChanged(AvaloniaPropertyChangedEventArgs e) - { - bool newValue = e.GetNewValue(); - PseudoClasses.Set(pcDropdownOpen, newValue); - } } } From 9b24a5bed64d6d5695fa073f8468481339b74af4 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 17 Dec 2022 11:53:17 -0500 Subject: [PATCH 33/35] Remove duplicate OnKeyDown handler --- src/Avalonia.Controls/ComboBox.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 564a2e478e..f3179a4644 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -96,8 +96,6 @@ namespace Avalonia.Controls ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); FocusableProperty.OverrideDefaultValue(true); IsTextSearchEnabledProperty.OverrideDefaultValue(true); - - KeyDownEvent.AddClassHandler((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel); } /// From 53a78131f54440ff863804636545d79882d203fb Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 17 Dec 2022 13:23:26 -0500 Subject: [PATCH 34/35] Add DropDownOpened and DropDownClosed events to ComboBox --- src/Avalonia.Controls/ComboBox.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index f3179a4644..c17b42b684 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -98,6 +98,16 @@ namespace Avalonia.Controls IsTextSearchEnabledProperty.OverrideDefaultValue(true); } + /// + /// Occurs after the drop-down (popup) list of the closes. + /// + public event EventHandler? DropDownClosed; + + /// + /// Occurs after the drop-down (popup) list of the opens. + /// + public event EventHandler? DropDownOpened; + /// /// Gets or sets a value indicating whether the dropdown is currently open. /// @@ -358,6 +368,8 @@ namespace Avalonia.Controls { Focus(); } + + DropDownClosed?.Invoke(this, EventArgs.Empty); } private void PopupOpened(object? sender, EventArgs e) @@ -387,6 +399,8 @@ namespace Avalonia.Controls } UpdateFlowDirection(); + + DropDownOpened?.Invoke(this, EventArgs.Empty); } private void IsVisibleChanged(bool isVisible) From 6497e49c267b28f365bbc735fa25de8b0609f610 Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 18 Dec 2022 12:14:19 -0500 Subject: [PATCH 35/35] Open/Close ComboBox drop-down with Enter and Space --- src/Avalonia.Controls/ComboBox.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index f02df2e9c1..a0085c92ca 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -213,7 +213,12 @@ namespace Avalonia.Controls IsDropDownOpen = false; e.Handled = true; } - else if (IsDropDownOpen && e.Key == Key.Enter) + else if (!IsDropDownOpen && (e.Key == Key.Enter || e.Key == Key.Space)) + { + IsDropDownOpen = true; + e.Handled = true; + } + else if (IsDropDownOpen && (e.Key == Key.Enter || e.Key == Key.Space)) { SelectFocusedItem(); IsDropDownOpen = false;