From 1eb3d875108cdf366487461ec85fe6e21322e876 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 7 Feb 2020 11:40:48 -0300 Subject: [PATCH 01/60] remove nullable directive. --- src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index bf811ad008..31c62dec28 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -6,8 +6,6 @@ using Avalonia.LogicalTree; using Avalonia.Rendering; using Avalonia.Threading; -#nullable enable - namespace Avalonia.Controls.Platform { /// From a3ab1578cd8806151bf52a078027f0fe56135740 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 7 Feb 2020 18:00:03 +0300 Subject: [PATCH 02/60] Removed C# 8.0 feature usage --- .../Platform/DefaultMenuInteractionHandler.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index 31c62dec28..8af71a6c1f 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -14,8 +14,8 @@ namespace Avalonia.Controls.Platform public class DefaultMenuInteractionHandler : IMenuInteractionHandler { private readonly bool _isContextMenu; - private IDisposable? _inputManagerSubscription; - private IRenderRoot? _root; + private IDisposable _inputManagerSubscription; + private IRenderRoot _root; public DefaultMenuInteractionHandler(bool isContextMenu) : this(isContextMenu, Input.InputManager.Instance, DefaultDelayRun) @@ -24,7 +24,7 @@ namespace Avalonia.Controls.Platform public DefaultMenuInteractionHandler( bool isContextMenu, - IInputManager? inputManager, + IInputManager inputManager, Action delayRun) { delayRun = delayRun ?? throw new ArgumentNullException(nameof(delayRun)); @@ -94,7 +94,7 @@ namespace Avalonia.Controls.Platform root.Deactivated -= WindowDeactivated; } - _inputManagerSubscription!.Dispose(); + _inputManagerSubscription.Dispose(); Menu = null; _root = null; @@ -102,9 +102,9 @@ namespace Avalonia.Controls.Platform protected Action DelayRun { get; } - protected IInputManager? InputManager { get; } + protected IInputManager InputManager { get; } - protected IMenu? Menu { get; private set; } + protected IMenu Menu { get; private set; } protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400); @@ -133,7 +133,7 @@ namespace Avalonia.Controls.Platform KeyDown(GetMenuItem(e.Source as IControl), e); } - protected internal virtual void KeyDown(IMenuItem? item, KeyEventArgs e) + protected internal virtual void KeyDown(IMenuItem item, KeyEventArgs e) { switch (e.Key) { @@ -202,7 +202,7 @@ namespace Avalonia.Controls.Platform } else { - Menu!.Close(); + Menu.Close(); } e.Handled = true; @@ -215,7 +215,7 @@ namespace Avalonia.Controls.Platform { if (item == null && _isContextMenu) { - if (Menu!.MoveSelection(direction.Value, true) == true) + if (Menu.MoveSelection(direction.Value, true) == true) { e.Handled = true; } @@ -410,7 +410,7 @@ namespace Avalonia.Controls.Platform protected void CloseMenu(IMenuItem item) { - var current = (IMenuElement?)item; + var current = (IMenuElement)item; while (current != null && !(current is IMenu)) { @@ -458,7 +458,7 @@ namespace Avalonia.Controls.Platform protected void SelectItemAndAncestors(IMenuItem item) { - var current = (IMenuItem?)item; + var current = item; while (current?.Parent != null) { @@ -467,7 +467,7 @@ namespace Avalonia.Controls.Platform } } - protected static IMenuItem? GetMenuItem(IControl? item) + protected static IMenuItem GetMenuItem(IControl item) { while (true) { From 82a0f0e476a6c0e5bee816b68832d2cc12322572 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 10 Feb 2020 12:44:30 +0100 Subject: [PATCH 03/60] Merge pull request #3537 from MarchingCube/fix-weak-event-manager-compact WeakEventHandlerManager: Ensure that weak refs with collected refs are compacted as well. --- src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs index 37e25d0fac..aca08f5259 100644 --- a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs +++ b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs @@ -183,11 +183,16 @@ namespace Avalonia.Utilities for (int c = 0; c < _count; c++) { var r = _data[c]; + + TSubscriber target = null; + + r.Subscriber?.TryGetTarget(out target); + //Mark current index as first empty - if (r.Subscriber == null && empty == -1) + if (target == null && empty == -1) empty = c; //If current element isn't null and we have an empty one - if (r.Subscriber != null && empty != -1) + if (target != null && empty != -1) { _data[c] = default; _data[empty] = r; From 8e452a1e4fa87154c1c5567c3cd5dd9793471387 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 12 Feb 2020 14:45:17 +0100 Subject: [PATCH 04/60] Merge pull request #3557 from AvaloniaUI/fixes/3426-selecting-disabled-control Don't select disabled controls with keyboard --- src/Avalonia.Controls/ItemsControl.cs | 5 ++++- .../Primitives/SelectingItemsControlTests.cs | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index bf22f0a08a..5f7a36f2f9 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -504,7 +504,10 @@ namespace Avalonia.Controls result = container.GetControl(direction, c, wrap); from = from ?? result; - if (result?.Focusable == true) + if (result != null && + result.Focusable && + result.IsEffectivelyEnabled && + result.IsEffectivelyVisible) { return result; } diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index 696c0dbf46..004cf009fc 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -1202,6 +1202,28 @@ namespace Avalonia.Controls.UnitTests.Primitives target.MoveSelection(NavigationDirection.Next, true); } + [Fact] + public void MoveSelection_Does_Select_Disabled_Controls() + { + // Issue #3426. + var target = new TestSelector + { + Template = Template(), + Items = new[] + { + new ListBoxItem(), + new ListBoxItem { IsEnabled = false }, + }, + SelectedIndex = 0, + }; + + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + target.MoveSelection(NavigationDirection.Next, true); + + Assert.Equal(0, target.SelectedIndex); + } + [Fact] public void Pre_Selecting_Item_Should_Set_Selection_After_It_Was_Added_When_AlwaysSelected() { From ff868c8e1e19dd59617c2c75b3adac252e449db7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 12 Feb 2020 18:55:23 +0100 Subject: [PATCH 05/60] Merge pull request #3558 from AvaloniaUI/fixes/3365-icon-null Allow assigning null to Window.Icon. --- src/Avalonia.Controls/Window.cs | 2 +- src/Avalonia.X11/X11Window.cs | 17 ++++++++++++----- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index f66a248aaf..0c37858223 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -129,7 +129,7 @@ namespace Avalonia.Controls ShowInTaskbarProperty.Changed.AddClassHandler((w, e) => w.PlatformImpl?.ShowTaskbarIcon((bool)e.NewValue)); - IconProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl)); + IconProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue)?.PlatformImpl)); CanResizeProperty.Changed.AddClassHandler((w, e) => w.PlatformImpl?.CanResize((bool)e.NewValue)); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 81d8424f76..5a01d86de4 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -977,11 +977,18 @@ namespace Avalonia.X11 public void SetIcon(IWindowIconImpl icon) { - var data = ((X11IconData)icon).Data; - fixed (void* pdata = data) - XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_ICON, - new IntPtr((int)Atom.XA_CARDINAL), 32, PropertyMode.Replace, - pdata, data.Length); + if (icon != null) + { + var data = ((X11IconData)icon).Data; + fixed (void* pdata = data) + XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_ICON, + new IntPtr((int)Atom.XA_CARDINAL), 32, PropertyMode.Replace, + pdata, data.Length); + } + else + { + XDeleteProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_ICON); + } } public void ShowTaskbarIcon(bool value) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 4d936cc871..1594a1f467 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -926,7 +926,7 @@ namespace Avalonia.Win32 public void SetIcon(IWindowIconImpl icon) { var impl = (IconImpl)icon; - var hIcon = impl.HIcon; + var hIcon = impl?.HIcon ?? IntPtr.Zero; UnmanagedMethods.PostMessage(_hwnd, (int)UnmanagedMethods.WindowsMessage.WM_SETICON, new IntPtr((int)UnmanagedMethods.Icons.ICON_BIG), hIcon); } From bebe0ca88e0f65cc612c4da8e8cc191a3adf061e Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Mon, 17 Feb 2020 01:16:03 +0800 Subject: [PATCH 06/60] Merge pull request #3581 from AvaloniaUI/fixes/3544-osx-window-close-crash Fix: dont crash when closing window on OSX. --- src/Avalonia.Native/WindowImplBase.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 64cea1c430..331f083e8b 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -162,9 +162,12 @@ namespace Avalonia.Native void IAvnWindowBaseEvents.Resized(AvnSize size) { - var s = new Size(size.Width, size.Height); - _parent._savedLogicalSize = s; - _parent.Resized?.Invoke(s); + if (_parent._native != null) + { + var s = new Size(size.Width, size.Height); + _parent._savedLogicalSize = s; + _parent.Resized?.Invoke(s); + } } void IAvnWindowBaseEvents.PositionChanged(AvnPoint position) @@ -317,7 +320,7 @@ namespace Avalonia.Native _native.SetTopMost(value); } - public double Scaling => _native.GetScaling(); + public double Scaling => _native?.GetScaling() ?? 1; public Action Deactivated { get; set; } public Action Activated { get; set; } From fc3278d171e6bd76b05ec9ef994181faf02ef66b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 12 Feb 2020 09:17:33 +0100 Subject: [PATCH 07/60] Merge pull request #3553 from AvaloniaUI/fixes/3550-menu-sizing Prevent reentrancy in LayoutManager.ExecuteInitialLayoutPass --- src/Avalonia.Layout/LayoutManager.cs | 12 +++++-- .../LayoutManagerTests.cs | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Layout/LayoutManager.cs b/src/Avalonia.Layout/LayoutManager.cs index 855f123748..917f5408d9 100644 --- a/src/Avalonia.Layout/LayoutManager.cs +++ b/src/Avalonia.Layout/LayoutManager.cs @@ -126,8 +126,16 @@ namespace Avalonia.Layout /// public void ExecuteInitialLayoutPass(ILayoutRoot root) { - Measure(root); - Arrange(root); + try + { + _running = true; + Measure(root); + Arrange(root); + } + finally + { + _running = false; + } // Running the initial layout pass may have caused some control to be invalidated // so run a full layout pass now (this usually due to scrollbars; its not known diff --git a/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs b/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs index 3f20c9a76a..0165b91844 100644 --- a/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs +++ b/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs @@ -374,5 +374,38 @@ namespace Avalonia.Layout.UnitTests Assert.True(control.Measured); Assert.True(control.IsMeasureValid); } + + [Fact] + public void Calling_ExecuteLayoutPass_From_ExecuteInitialLayoutPass_Does_Not_Break_Measure() + { + // Test for issue #3550. + var control = new LayoutTestControl(); + var root = new LayoutTestRoot { Child = control }; + var count = 0; + + root.LayoutManager.ExecuteInitialLayoutPass(root); + control.Measured = false; + + control.DoMeasureOverride = (l, s) => + { + if (count++ == 0) + { + control.InvalidateMeasure(); + root.LayoutManager.ExecuteLayoutPass(); + return new Size(100, 100); + } + else + { + return new Size(200, 200); + } + }; + + root.InvalidateMeasure(); + control.InvalidateMeasure(); + root.LayoutManager.ExecuteInitialLayoutPass(root); + + Assert.Equal(new Size(200, 200), control.Bounds.Size); + Assert.Equal(new Size(200, 200), control.DesiredSize); + } } } From 4f84e0741801c2c7a2b3fc5d545a536f3eee6a5c Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Fri, 14 Feb 2020 17:39:14 +0800 Subject: [PATCH 08/60] Merge pull request #3570 from AvaloniaUI/fixes/3569-window-sizing Fix window sizing --- src/Avalonia.Controls/Window.cs | 2 +- .../WindowTests.cs | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 0c37858223..6554237b3a 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -529,7 +529,7 @@ namespace Avalonia.Controls { var sizeToContent = SizeToContent; var clientSize = ClientSize; - Size constraint = clientSize; + var constraint = availableSize; if ((sizeToContent & SizeToContent.Width) != 0) { diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 0508edd92f..81699b075c 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -341,11 +341,62 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var child = new ChildControl(); + var target = new Window + { + Width = 100, + Height = 50, + SizeToContent = SizeToContent.Manual, + Content = child + }; + + target.Show(); + + Assert.Equal(new Size(100, 50), child.MeasureSize); + } + } + + [Fact] + public void Child_Should_Be_Measured_With_Infinity_If_SizeToContent_Is_WidthAndHeight() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var child = new ChildControl(); + var target = new Window + { + Width = 100, + Height = 50, + SizeToContent = SizeToContent.WidthAndHeight, + Content = child + }; + + target.Show(); + + Assert.Equal(Size.Infinity, child.MeasureSize); + } + } + private IWindowImpl CreateImpl(Mock renderer) { return Mock.Of(x => x.Scaling == 1 && x.CreateRenderer(It.IsAny()) == renderer.Object); } + + private class ChildControl : Control + { + public Size MeasureSize { get; private set; } + + protected override Size MeasureOverride(Size availableSize) + { + MeasureSize = availableSize; + return base.MeasureOverride(availableSize); + } + } } } From c030e8a980a43a68fda8c1a7dca633826d414e3b Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 20 Feb 2020 14:53:47 +0300 Subject: [PATCH 09/60] Fix inertial scrolling --- src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs index 4f3c7c0bba..a582fae8b5 100644 --- a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -148,6 +148,7 @@ namespace Avalonia.Input.GestureRecognizers EndGesture(); else { + _tracking = null; var savedGestureId = _gestureId; var st = Stopwatch.StartNew(); var lastTime = TimeSpan.Zero; From a819eff46cee0ca08050b472ab28e7dc95aba777 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Tue, 18 Feb 2020 17:14:40 +0800 Subject: [PATCH 10/60] Merge pull request #3585 from AvaloniaUI/fixes/3584-convert-timespan Use TypeConverters in TypeUtilities.TryConvert --- src/Avalonia.Base/Utilities/TypeUtilities.cs | 9 +++++++++ .../Data/DefaultValueConverterTests.cs | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Avalonia.Base/Utilities/TypeUtilities.cs b/src/Avalonia.Base/Utilities/TypeUtilities.cs index d85eb4cd76..39736ab389 100644 --- a/src/Avalonia.Base/Utilities/TypeUtilities.cs +++ b/src/Avalonia.Base/Utilities/TypeUtilities.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reflection; @@ -188,6 +189,14 @@ namespace Avalonia.Utilities } } + var typeConverter = TypeDescriptor.GetConverter(to); + + if (typeConverter.CanConvertFrom(from) == true) + { + result = typeConverter.ConvertFrom(null, culture, value); + return true; + } + var cast = FindTypeConversionOperatorMethod(from, to, OperatorType.Implicit | OperatorType.Explicit); if (cast != null) diff --git a/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs index ecf559951a..f29dabb6bf 100644 --- a/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs @@ -50,6 +50,18 @@ namespace Avalonia.Base.UnitTests.Data.Converters Assert.Equal(TestEnum.Bar, result); } + [Fact] + public void Can_Convert_String_To_TimeSpan() + { + var result = DefaultValueConverter.Instance.Convert( + "00:00:10", + typeof(TimeSpan), + null, + CultureInfo.InvariantCulture); + + Assert.Equal(TimeSpan.FromSeconds(10), result); + } + [Fact] public void Can_Convert_Int_To_Enum() { From b996d06522490f3329249f2d0efb284a46240a69 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Wed, 26 Feb 2020 07:57:28 -0300 Subject: [PATCH 11/60] Merge pull request #3613 from AvaloniaUI/osx-potential-deadlock-in-user-code OSX - fix potential deadlock with user code --- native/Avalonia.Native/src/OSX/platformthreading.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/platformthreading.mm b/native/Avalonia.Native/src/OSX/platformthreading.mm index e7abedae51..ed00f8c5e1 100644 --- a/native/Avalonia.Native/src/OSX/platformthreading.mm +++ b/native/Avalonia.Native/src/OSX/platformthreading.mm @@ -157,11 +157,14 @@ NSArray* _modes; -(void) perform { + ComPtr cb; @synchronized (self) { _signaled = false; - if(_parent != NULL && _parent->SignaledCallback != NULL) - _parent->SignaledCallback->Signaled(0, false); + if(_parent != NULL) + cb = _parent->SignaledCallback; } + if(cb != nullptr) + cb->Signaled(0, false); } -(void) setParent:(PlatformThreadingInterface *)parent From f578639d75a3021a159962a7618bacd70828dae4 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Thu, 19 Mar 2020 13:26:26 -0300 Subject: [PATCH 12/60] Merge pull request #3680 from AvaloniaUI/fix/osx-window-state-binding Fix OSX binding to WindowState. --- native/Avalonia.Native/src/OSX/window.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 483b70f7e9..9664bf13e4 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -427,6 +427,7 @@ private: ComPtr WindowEvents; WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl) { + _lastWindowState = Normal; WindowEvents = events; [Window setCanBecomeKeyAndMain]; [Window disableCursorRects]; @@ -440,7 +441,7 @@ private: [[Window parentWindow] removeChildWindow:Window]; WindowBaseImpl::Show(); - return SetWindowState(Normal); + return SetWindowState(_lastWindowState); } } From ea200b00e94470bc9cc824ea0db6b2c1b1b1ae08 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 26 Mar 2020 22:45:57 +0800 Subject: [PATCH 13/60] Merge pull request #3696 from AvaloniaUI/treeviewitem-header-stretch Don't constrain header's ContentPresenter on TreeViewItem --- src/Avalonia.Themes.Default/TreeViewItem.xaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Themes.Default/TreeViewItem.xaml b/src/Avalonia.Themes.Default/TreeViewItem.xaml index 0d826806d0..a3f8d8b7f7 100644 --- a/src/Avalonia.Themes.Default/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Default/TreeViewItem.xaml @@ -17,8 +17,7 @@ BorderThickness="{TemplateBinding BorderThickness}" TemplatedControl.IsTemplateFocusTarget="True"> Date: Fri, 27 Mar 2020 23:02:48 +0800 Subject: [PATCH 14/60] Merge pull request #3698 from AvaloniaUI/non-mapped-wm-state [X11] When not mapped change _NET_WM_STATE property directly --- src/Avalonia.X11/X11Window.cs | 46 +++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 5a01d86de4..94d4003e1c 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -527,14 +527,14 @@ namespace Avalonia.X11 } else if (value == WindowState.Maximized) { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero); - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)1, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN); + ChangeWMAtoms(true, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); } else { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero); - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN); + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); } } @@ -965,8 +965,7 @@ namespace Avalonia.X11 public void SetTopmost(bool value) { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, - (IntPtr)(value ? 1 : 0), _x11.Atoms._NET_WM_STATE_ABOVE, IntPtr.Zero); + ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } public void ShowDialog(IWindowImpl parent) @@ -993,8 +992,41 @@ namespace Avalonia.X11 public void ShowTaskbarIcon(bool value) { + ChangeWMAtoms(!value, _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR); + } + + void ChangeWMAtoms(bool enable, params IntPtr[] atoms) + { + if (atoms.Length < 1 || atoms.Length > 4) + throw new ArgumentException(); + + if (!_mapped) + { + XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, IntPtr.Zero, new IntPtr(256), + false, (IntPtr)Atom.XA_ATOM, out _, out _, out var nitems, out _, + out var prop); + var ptr = (IntPtr*)prop.ToPointer(); + var newAtoms = new HashSet(); + for (var c = 0; c < nitems.ToInt64(); c++) + newAtoms.Add(*ptr); + XFree(prop); + foreach(var atom in atoms) + if (enable) + newAtoms.Add(atom); + else + newAtoms.Remove(atom); + + XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, + PropertyMode.Replace, newAtoms.ToArray(), newAtoms.Count); + } + SendNetWMMessage(_x11.Atoms._NET_WM_STATE, - (IntPtr)(value ? 0 : 1), _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR, IntPtr.Zero); + (IntPtr)(enable ? 1 : 0), + atoms[0], + atoms.Length > 1 ? atoms[1] : IntPtr.Zero, + atoms.Length > 2 ? atoms[2] : IntPtr.Zero, + atoms.Length > 3 ? atoms[3] : IntPtr.Zero + ); } public IPopupPositioner PopupPositioner { get; } From 823187e3065b756aa026e76a1179036c0fe06c32 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 27 Mar 2020 12:07:58 -0300 Subject: [PATCH 15/60] bump version --- build/SharedVersion.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 1294b5f6f2..75fd869134 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.9.3 + 0.9.5 Copyright 2020 © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ From 757220107b7725d2b40e792488f8f3ab4bad689e Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Fri, 27 Mar 2020 19:10:09 -0300 Subject: [PATCH 16/60] Merge pull request #3699 from AvaloniaUI/fixes/osx-dont-zoom-when-normal-state-selected OSX backend calls OnResized to keep WindowState inSync. # Conflicts: # native/Avalonia.Native/src/OSX/window.mm --- native/Avalonia.Native/src/OSX/window.mm | 95 ++++++++++++++---------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 9664bf13e4..cd42ea0437 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -31,9 +31,11 @@ public: AvnPoint lastPositionSet; NSString* _lastTitle; IAvnAppMenu* _mainMenu; + bool _shown; WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl) { + _shown = false; _mainMenu = nullptr; BaseEvents = events; _glContext = gl; @@ -116,6 +118,8 @@ public: [Window setTitle:_lastTitle]; [Window setTitleVisibility:NSWindowTitleVisible]; + + _shown = true; return S_OK; } @@ -401,6 +405,7 @@ protected: [Window setStyleMask:GetStyle()]; } +public: virtual void OnResized () { @@ -592,57 +597,63 @@ private: { _lastWindowState = state; - switch (state) { - case Maximized: - lastPositionSet.X = 0; - lastPositionSet.Y = 0; - - if([Window isMiniaturized]) - { - [Window deminiaturize:Window]; - } - - if(!IsZoomed()) - { - DoZoom(); - } - break; - - case Minimized: - [Window miniaturize:Window]; - break; - - default: - if([Window isMiniaturized]) - { - [Window deminiaturize:Window]; - } - - if(IsZoomed()) - { - DoZoom(); - } - break; + if(_shown) + { + switch (state) { + case Maximized: + lastPositionSet.X = 0; + lastPositionSet.Y = 0; + + if([Window isMiniaturized]) + { + [Window deminiaturize:Window]; + } + + if(!IsZoomed()) + { + DoZoom(); + } + break; + + case Minimized: + [Window miniaturize:Window]; + break; + + default: + if([Window isMiniaturized]) + { + [Window deminiaturize:Window]; + } + + if(IsZoomed()) + { + DoZoom(); + } + break; + } } return S_OK; } } - -protected: + virtual void OnResized () override { - auto windowState = [Window isMiniaturized] ? Minimized - : (IsZoomed() ? Maximized : Normal); - - if (windowState != _lastWindowState) + if(_shown) { - _lastWindowState = windowState; + auto windowState = [Window isMiniaturized] ? Minimized + : (IsZoomed() ? Maximized : Normal); - WindowEvents->WindowStateChanged(windowState); + if (windowState != _lastWindowState) + { + _lastWindowState = windowState; + + WindowEvents->WindowStateChanged(windowState); + } } } +protected: virtual NSWindowStyleMask GetStyle() override { unsigned long s = NSWindowStyleMaskBorderless; @@ -1290,6 +1301,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent } } +- (void)windowDidResize:(NSNotification *)notification +{ + _parent->OnResized(); +} + - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { return true; @@ -1360,6 +1376,7 @@ protected: [Window setContentSize:NSSize{x, y}]; [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))]; + return S_OK; } } From 5247c38deb0561524408050c77f3e122289b053c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 27 Mar 2020 19:20:05 -0300 Subject: [PATCH 17/60] bump version. --- build/SharedVersion.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 75fd869134..cfec024391 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.9.5 + 0.9.6 Copyright 2020 © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ From 510d7ad1237c2c3cd079030d20b1706703d4ae43 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 3 Apr 2020 10:07:06 -0300 Subject: [PATCH 18/60] Revert "Merge pull request #3570 from AvaloniaUI/fixes/3569-window-sizing" This reverts commit 4f84e0741801c2c7a2b3fc5d545a536f3eee6a5c. --- src/Avalonia.Controls/Window.cs | 2 +- .../WindowTests.cs | 51 ------------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 6554237b3a..0c37858223 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -529,7 +529,7 @@ namespace Avalonia.Controls { var sizeToContent = SizeToContent; var clientSize = ClientSize; - var constraint = availableSize; + Size constraint = clientSize; if ((sizeToContent & SizeToContent.Width) != 0) { diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 81699b075c..0508edd92f 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -341,62 +341,11 @@ namespace Avalonia.Controls.UnitTests } } - [Fact] - public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual() - { - using (UnitTestApplication.Start(TestServices.StyledWindow)) - { - var child = new ChildControl(); - var target = new Window - { - Width = 100, - Height = 50, - SizeToContent = SizeToContent.Manual, - Content = child - }; - - target.Show(); - - Assert.Equal(new Size(100, 50), child.MeasureSize); - } - } - - [Fact] - public void Child_Should_Be_Measured_With_Infinity_If_SizeToContent_Is_WidthAndHeight() - { - using (UnitTestApplication.Start(TestServices.StyledWindow)) - { - var child = new ChildControl(); - var target = new Window - { - Width = 100, - Height = 50, - SizeToContent = SizeToContent.WidthAndHeight, - Content = child - }; - - target.Show(); - - Assert.Equal(Size.Infinity, child.MeasureSize); - } - } - private IWindowImpl CreateImpl(Mock renderer) { return Mock.Of(x => x.Scaling == 1 && x.CreateRenderer(It.IsAny()) == renderer.Object); } - - private class ChildControl : Control - { - public Size MeasureSize { get; private set; } - - protected override Size MeasureOverride(Size availableSize) - { - MeasureSize = availableSize; - return base.MeasureOverride(availableSize); - } - } } } From 401c03a1a83dd8c6027e613d9e70c95c6a7c04a9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 3 Apr 2020 10:20:49 -0300 Subject: [PATCH 19/60] bump version. --- build/SharedVersion.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index cfec024391..97cd470868 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.9.6 + 0.9.7 Copyright 2020 © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ From 4e5cec2d9e933f56be489ccc5ba5cf6706ff86aa Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Fri, 3 Apr 2020 09:46:44 -0300 Subject: [PATCH 20/60] Merge pull request #3712 from AvaloniaUI/x11-remove-transient-hint [X11, FlyWM] Completely remove WM_TRANSIENT_FOR property --- src/Avalonia.X11/X11Window.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 94d4003e1c..74a7a33be6 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -735,7 +735,15 @@ namespace Avalonia.X11 _transientParent = window; _transientParent?._transientChildren.Add(this); if (informServer) - XSetTransientForHint(_x11.Display, _handle, _transientParent?._handle ?? IntPtr.Zero); + SetTransientForHint(_transientParent?._handle); + } + + void SetTransientForHint(IntPtr? parent) + { + if (parent == null || parent == IntPtr.Zero) + XDeleteProperty(_x11.Display, _handle, _x11.Atoms.XA_WM_TRANSIENT_FOR); + else + XSetTransientForHint(_x11.Display, _handle, parent.Value); } public void Show() From d8e4e56e92b48506e0943823b50088f06b9da117 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Fri, 3 Apr 2020 11:16:30 -0300 Subject: [PATCH 21/60] Merge pull request #3711 from AvaloniaUI/fix-gtk-initial-name Fixed InitialFileName for GTK-based file dialog --- samples/ControlCatalog/Pages/DialogsPage.xaml.cs | 5 +++-- src/Avalonia.X11/NativeDialogs/Gtk.cs | 3 +++ src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs index d207689223..6f5e503fb3 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs @@ -42,14 +42,15 @@ namespace ControlCatalog.Pages new SaveFileDialog() { Title = "Save file", - Filters = GetFilters() + Filters = GetFilters(), + InitialFileName = "test.txt" }.ShowAsync(GetWindow()); }; this.FindControl