From f8e83db6b0367c0ace69d95bcc789bf10e6f1c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Tue, 24 Sep 2019 03:18:44 +0100 Subject: [PATCH 01/32] Update .NET Core SDK to version 3.0.x. --- azure-pipelines.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 92e4afdca8..389f343c54 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -34,9 +34,17 @@ jobs: pool: vmImage: 'macOS-10.14' steps: - - task: DotNetCoreInstaller@0 + - task: UseDotNet@2 + displayName: 'Use .NET Core SDK 3.0.x' inputs: - version: '2.1.403' + packageType: sdk + version: 3.0.x + + - task: UseDotNet@2 + displayName: 'Use .NET Core Runtime 2.1.x' + inputs: + packageType: runtime + version: 2.1.x - task: CmdLine@2 displayName: 'Install Mono 5.18' From 1cd113182cdb29fb645d54f66477956827548fda Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 4 Nov 2019 20:22:29 +0100 Subject: [PATCH 02/32] Added failing test for #2985. --- .../TreeViewTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index a91b7a0701..cfc9daa402 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -893,6 +893,37 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(2, GetItem(target, 0, 1, 0).Level); } + [Fact] + public void Adding_Node_To_Removed_And_ReAdded_Parent_Should_Not_Crash() + { + // Issue #2985 + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + }; + + var visualRoot = new TestRoot(); + visualRoot.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + ExpandAll(target); + + var parent = tree[0]; + var node = parent.Children[1]; + + parent.Children.Remove(node); + parent.Children.Add(node); + + var item = target.ItemContainerGenerator.Index.ContainerFromItem(node); + ApplyTemplates(new[] { item }); + + // #2985 causes ArgumentException here. + node.Children.Add(new Node()); + } + [Fact] public void Auto_Expanding_In_Style_Should_Not_Break_Range_Selection() { From 15dfb88fe7b39eb786e37d5e29ca39eeb1df0502 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 4 Nov 2019 20:24:35 +0100 Subject: [PATCH 03/32] Update tree item container index dynamically. Update `TreeItemContainerGenerator.Index` when a `TreeViewItem` is added to or removed from the logical tree. This ensures that removed `TreeViewItem`s won't try to add duplicate containers to the index. Fixes #2985 --- .../Generators/ITreeItemContainerGenerator.cs | 5 ++ .../Generators/TreeItemContainerGenerator.cs | 49 ++++++++++++++----- src/Avalonia.Controls/TreeView.cs | 3 +- src/Avalonia.Controls/TreeViewItem.cs | 9 ++-- .../TreeViewTests.cs | 7 +++ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs index e2e591215e..5c931bc771 100644 --- a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs @@ -12,5 +12,10 @@ namespace Avalonia.Controls.Generators /// Gets the container index for the tree. /// TreeContainerIndex Index { get; } + + /// + /// Updates the index based on the parent . + /// + void UpdateIndex(); } } diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs index c06a64443c..9200490668 100644 --- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Avalonia.Controls.Templates; using Avalonia.Data; +using Avalonia.LogicalTree; namespace Avalonia.Controls.Generators { @@ -15,6 +17,8 @@ namespace Avalonia.Controls.Generators public class TreeItemContainerGenerator : ItemContainerGenerator, ITreeItemContainerGenerator where T : class, IControl, new() { + private TreeView _treeView; + /// /// Initializes a new instance of the class. /// @@ -23,31 +27,28 @@ namespace Avalonia.Controls.Generators /// The container's ContentTemplate property. /// The container's Items property. /// The container's IsExpanded property. - /// The container index for the tree public TreeItemContainerGenerator( IControl owner, AvaloniaProperty contentProperty, AvaloniaProperty contentTemplateProperty, AvaloniaProperty itemsProperty, - AvaloniaProperty isExpandedProperty, - TreeContainerIndex index) + AvaloniaProperty isExpandedProperty) : base(owner, contentProperty, contentTemplateProperty) { Contract.Requires(owner != null); Contract.Requires(contentProperty != null); Contract.Requires(itemsProperty != null); Contract.Requires(isExpandedProperty != null); - Contract.Requires(index != null); ItemsProperty = itemsProperty; IsExpandedProperty = isExpandedProperty; - Index = index; + UpdateIndex(); } /// /// Gets the container index for the tree. /// - public TreeContainerIndex Index { get; } + public TreeContainerIndex Index { get; private set; } /// /// Gets the item container's Items property. @@ -70,7 +71,7 @@ namespace Avalonia.Controls.Generators } else if (container != null) { - Index.Add(item, container); + Index?.Add(item, container); return container; } else @@ -92,7 +93,7 @@ namespace Avalonia.Controls.Generators result.DataContext = item; } - Index.Add(item, result); + Index?.Add(item, result); return result; } @@ -101,24 +102,50 @@ namespace Avalonia.Controls.Generators public override IEnumerable Clear() { var items = base.Clear(); - Index.Remove(0, items); + Index?.Remove(0, items); return items; } public override IEnumerable Dematerialize(int startingIndex, int count) { - Index.Remove(startingIndex, GetContainerRange(startingIndex, count)); + Index?.Remove(startingIndex, GetContainerRange(startingIndex, count)); return base.Dematerialize(startingIndex, count); } public override IEnumerable RemoveRange(int startingIndex, int count) { - Index.Remove(startingIndex, GetContainerRange(startingIndex, count)); + Index?.Remove(startingIndex, GetContainerRange(startingIndex, count)); return base.RemoveRange(startingIndex, count); } public override bool TryRecycle(int oldIndex, int newIndex, object item) => false; + public void UpdateIndex() + { + if (Owner is TreeView treeViewOwner && Index == null) + { + Index = new TreeContainerIndex(); + _treeView = treeViewOwner; + } + else if (Owner.IsAttachedToLogicalTree) + { + var treeView = Owner.GetSelfAndLogicalAncestors().OfType().FirstOrDefault(); + + if (treeView != _treeView) + { + Clear(); + Index = treeView?.ItemContainerGenerator?.Index; + _treeView = treeView; + } + } + else + { + Clear(); + Index = null; + _treeView = null; + } + } + class WrapperTreeDataTemplate : ITreeDataTemplate { private readonly IDataTemplate _inner; diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 8907137ecb..acfef5117c 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -393,8 +393,7 @@ namespace Avalonia.Controls TreeViewItem.HeaderProperty, TreeViewItem.ItemTemplateProperty, TreeViewItem.ItemsProperty, - TreeViewItem.IsExpandedProperty, - new TreeContainerIndex()); + TreeViewItem.IsExpandedProperty); result.Index.Materialized += ContainerMaterialized; return result; } diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index 07d5497c14..4d24337c3a 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -98,17 +98,18 @@ namespace Avalonia.Controls TreeViewItem.HeaderProperty, TreeViewItem.ItemTemplateProperty, TreeViewItem.ItemsProperty, - TreeViewItem.IsExpandedProperty, - _treeView?.ItemContainerGenerator.Index ?? new TreeContainerIndex()); + TreeViewItem.IsExpandedProperty); } /// protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { base.OnAttachedToLogicalTree(e); + _treeView = this.GetLogicalAncestors().OfType().FirstOrDefault(); - + Level = CalculateDistanceFromLogicalParent(this) - 1; + ItemContainerGenerator.UpdateIndex(); if (ItemTemplate == null && _treeView?.ItemTemplate != null) { @@ -119,7 +120,7 @@ namespace Avalonia.Controls protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) { base.OnDetachedFromLogicalTree(e); - ItemContainerGenerator.Clear(); + ItemContainerGenerator.UpdateIndex(); } protected virtual void OnRequestBringIntoView(RequestBringIntoViewEventArgs e) diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index cfc9daa402..ed8a39d063 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -10,6 +10,7 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Data.Core; +using Avalonia.Diagnostics; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; @@ -33,6 +34,8 @@ namespace Avalonia.Controls.UnitTests Items = CreateTestTreeData(), }; + var root = new TestRoot(target); + CreateNodeDataTemplate(target); ApplyTemplates(target); @@ -77,6 +80,8 @@ namespace Avalonia.Controls.UnitTests Items = CreateTestTreeData(), }; + var root = new TestRoot(target); + CreateNodeDataTemplate(target); ApplyTemplates(target); @@ -527,6 +532,8 @@ namespace Avalonia.Controls.UnitTests Items = data, }; + var root = new TestRoot(target); + CreateNodeDataTemplate(target); ApplyTemplates(target); From 138ea74b88f64e2977482583b9e4042d68567b24 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Nov 2019 19:32:09 +0000 Subject: [PATCH 04/32] Add code to show desired syntax. --- samples/ControlCatalog/App.xaml | 5 +++++ samples/ControlCatalog/App.xaml.cs | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index e40509dfda..813a043b01 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -17,4 +17,9 @@ + + + + + diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 958729e2e8..b713c3dfd6 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -1,18 +1,32 @@ using System; +using System.Reactive; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using ReactiveUI; namespace ControlCatalog { public class App : Application { + public App() + { + DataContext = this; + + AboutCommand = ReactiveCommand.Create(() => + { + + }); + } + public override void Initialize() { AvaloniaXamlLoader.Load(this); } + public ReactiveCommand AboutCommand { get; } + public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) From 11a67d5b1088433ed9b3e951f216f127e79553a4 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Fri, 22 Nov 2019 23:51:50 +0100 Subject: [PATCH 05/32] Make sure window and its children get detached from visual and logical trees when closing. --- src/Avalonia.Controls/TopLevel.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 293809bf51..81f132660d 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -269,6 +269,18 @@ namespace Avalonia.Controls /// protected virtual void HandleClosed() { + { + var e = new LogicalTreeAttachmentEventArgs(this); + + ((ILogical)this).NotifyDetachedFromLogicalTree(e); + } + + { + var e = new VisualTreeAttachmentEventArgs(this, this); + + OnDetachedFromVisualTreeCore(e); + } + (this as IInputRoot).MouseDevice?.TopLevelClosed(this); PlatformImpl = null; OnClosed(EventArgs.Empty); From 1212e2444769f76c60c75b8b06e4988fcdae7ff3 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sun, 24 Nov 2019 15:45:31 +0800 Subject: [PATCH 06/32] Hackfix for #3284 --- src/Avalonia.Controls/Primitives/RangeBase.cs | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index f1ee7c0e1a..39d00b6953 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -75,8 +75,11 @@ namespace Avalonia.Controls.Primitives set { - ValidateDouble(value, "Minimum"); - + if (!ValidateDouble(value)) + { + value = _minimum; + } + if (IsInitialized) { SetAndRaise(MinimumProperty, ref _minimum, value); @@ -102,7 +105,10 @@ namespace Avalonia.Controls.Primitives set { - ValidateDouble(value, "Maximum"); + if (!ValidateDouble(value)) + { + value = _maximum; + } if (IsInitialized) { @@ -129,7 +135,10 @@ namespace Avalonia.Controls.Primitives set { - ValidateDouble(value, "Value"); + if (!ValidateDouble(value)) + { + value = default; + } if (IsInitialized) { @@ -167,13 +176,9 @@ namespace Avalonia.Controls.Primitives /// Throws an exception if the double value is NaN or Inf. /// /// The value. - /// The name of the property being set. - private static void ValidateDouble(double value, string property) + private static bool ValidateDouble(double value) { - if (double.IsInfinity(value) || double.IsNaN(value)) - { - throw new ArgumentException($"{value} is not a valid value for {property}."); - } + return (!double.IsInfinity(value) || !double.IsNaN(value)); } /// From 7c7f6022cba12ad59c69fe2b614da27e2786c725 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 24 Nov 2019 15:46:00 +0100 Subject: [PATCH 07/32] Cleanup event args locals. --- src/Avalonia.Controls/TopLevel.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 81f132660d..a0df186eb7 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -269,17 +269,11 @@ namespace Avalonia.Controls /// protected virtual void HandleClosed() { - { - var e = new LogicalTreeAttachmentEventArgs(this); - - ((ILogical)this).NotifyDetachedFromLogicalTree(e); - } + var logicalArgs = new LogicalTreeAttachmentEventArgs(this); + ((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs); - { - var e = new VisualTreeAttachmentEventArgs(this, this); - - OnDetachedFromVisualTreeCore(e); - } + var visualArgs = new VisualTreeAttachmentEventArgs(this, this); + OnDetachedFromVisualTreeCore(visualArgs); (this as IInputRoot).MouseDevice?.TopLevelClosed(this); PlatformImpl = null; From 6a74ab560c96078aa15e268900df342c47d6f50d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 25 Nov 2019 10:05:45 +0100 Subject: [PATCH 08/32] Added IDataContextProvider. So that non-`IStyledElement`s can take part in binding. Apply the interface to `Application`. --- src/Avalonia.Controls/Application.cs | 22 +++++++++++++++++++- src/Avalonia.Styling/IDataContextProvider.cs | 13 ++++++++++++ src/Avalonia.Styling/IStyledElement.cs | 8 ++----- src/Avalonia.Styling/StyledElement.cs | 2 +- src/Markup/Avalonia.Markup/Data/Binding.cs | 4 ++-- 5 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 src/Avalonia.Styling/IDataContextProvider.cs diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 59c6c47ed9..9df92a49bc 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -32,7 +32,7 @@ namespace Avalonia /// method. /// - Tracks the lifetime of the application. /// - public class Application : AvaloniaObject, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode + public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode { /// /// The application-global data templates. @@ -45,6 +45,13 @@ namespace Avalonia private Styles _styles; private IResourceDictionary _resources; + /// + /// Defines the property. + /// + public static readonly StyledProperty DataContextProperty = + AvaloniaProperty.Register( + nameof(DataContext)); + /// public event EventHandler ResourcesChanged; @@ -56,6 +63,19 @@ namespace Avalonia Name = "Avalonia Application"; } + /// + /// Gets or sets the Applications's data context. + /// + /// + /// The data context property specifies the default object that will + /// be used for data binding. + /// + public object DataContext + { + get { return GetValue(DataContextProperty); } + set { SetValue(DataContextProperty, value); } + } + /// /// Gets the current instance of the class. /// diff --git a/src/Avalonia.Styling/IDataContextProvider.cs b/src/Avalonia.Styling/IDataContextProvider.cs new file mode 100644 index 0000000000..31639c5784 --- /dev/null +++ b/src/Avalonia.Styling/IDataContextProvider.cs @@ -0,0 +1,13 @@ +namespace Avalonia +{ + /// + /// Defines an element with a data context that can be used for binding. + /// + public interface IDataContextProvider : IAvaloniaObject + { + /// + /// Gets or sets the element's data context. + /// + object DataContext { get; set; } + } +} diff --git a/src/Avalonia.Styling/IStyledElement.cs b/src/Avalonia.Styling/IStyledElement.cs index bcf1898c4c..d4d0f179c3 100644 --- a/src/Avalonia.Styling/IStyledElement.cs +++ b/src/Avalonia.Styling/IStyledElement.cs @@ -10,7 +10,8 @@ namespace Avalonia IStyleHost, ILogical, IResourceProvider, - IResourceNode + IResourceNode, + IDataContextProvider { /// /// Occurs when the control has finished initialization. @@ -27,11 +28,6 @@ namespace Avalonia /// new Classes Classes { get; set; } - /// - /// Gets or sets the control's data context. - /// - object DataContext { get; set; } - /// /// Gets the control's logical parent. /// diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs index de8093c048..cf3c4dc855 100644 --- a/src/Avalonia.Styling/StyledElement.cs +++ b/src/Avalonia.Styling/StyledElement.cs @@ -24,7 +24,7 @@ namespace Avalonia /// - Implements to form part of a logical tree. /// - A collection of class strings for custom styling. /// - public class StyledElement : Animatable, IStyledElement, ISetLogicalParent, ISetInheritanceParent + public class StyledElement : Animatable, IDataContextProvider, IStyledElement, ISetLogicalParent, ISetInheritanceParent { /// /// Defines the property. diff --git a/src/Markup/Avalonia.Markup/Data/Binding.cs b/src/Markup/Avalonia.Markup/Data/Binding.cs index 61d0f7c83b..b4545f792e 100644 --- a/src/Markup/Avalonia.Markup/Data/Binding.cs +++ b/src/Markup/Avalonia.Markup/Data/Binding.cs @@ -231,9 +231,9 @@ namespace Avalonia.Data { Contract.Requires(target != null); - if (!(target is IStyledElement)) + if (!(target is IDataContextProvider)) { - target = anchor as IStyledElement; + target = anchor as IDataContextProvider; if (target == null) { From 7b11d7674aecbd31e8c15bee1c2715ffd798105e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 09:28:42 +0000 Subject: [PATCH 09/32] implement IDataContextProvider on NativeMenuItem --- src/Avalonia.Controls/NativeMenuItemBase.cs | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs index 47eb86cdc3..fa2ecd609a 100644 --- a/src/Avalonia.Controls/NativeMenuItemBase.cs +++ b/src/Avalonia.Controls/NativeMenuItemBase.cs @@ -2,7 +2,7 @@ namespace Avalonia.Controls { - public class NativeMenuItemBase : AvaloniaObject + public class NativeMenuItemBase : AvaloniaObject, IDataContextProvider { private NativeMenu _parent; @@ -11,6 +11,7 @@ namespace Avalonia.Controls } + public static readonly DirectProperty ParentProperty = AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v); @@ -19,5 +20,26 @@ namespace Avalonia.Controls get => _parent; set => SetAndRaise(ParentProperty, ref _parent, value); } + + /// + /// Defines the property. + /// + public static readonly StyledProperty DataContextProperty = + AvaloniaProperty.Register( + nameof(DataContext)); + + /// + /// Gets or sets the controls's data context. + /// + /// + /// The data context property + /// specifies the default object that will + /// be used for data binding. + /// + public object DataContext + { + get { return GetValue(DataContextProperty); } + set { SetValue(DataContextProperty, value); } + } } } From 7eea7f65c65fca0b7f4e35b3b8a518e31afc687b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:07:18 +0000 Subject: [PATCH 10/32] dont implement datacontext on menuitems --- src/Avalonia.Controls/NativeMenuItemBase.cs | 24 +-------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs index fa2ecd609a..47eb86cdc3 100644 --- a/src/Avalonia.Controls/NativeMenuItemBase.cs +++ b/src/Avalonia.Controls/NativeMenuItemBase.cs @@ -2,7 +2,7 @@ namespace Avalonia.Controls { - public class NativeMenuItemBase : AvaloniaObject, IDataContextProvider + public class NativeMenuItemBase : AvaloniaObject { private NativeMenu _parent; @@ -11,7 +11,6 @@ namespace Avalonia.Controls } - public static readonly DirectProperty ParentProperty = AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v); @@ -20,26 +19,5 @@ namespace Avalonia.Controls get => _parent; set => SetAndRaise(ParentProperty, ref _parent, value); } - - /// - /// Defines the property. - /// - public static readonly StyledProperty DataContextProperty = - AvaloniaProperty.Register( - nameof(DataContext)); - - /// - /// Gets or sets the controls's data context. - /// - /// - /// The data context property - /// specifies the default object that will - /// be used for data binding. - /// - public object DataContext - { - get { return GetValue(DataContextProperty); } - set { SetValue(DataContextProperty, value); } - } } } From eb6f3e620d802b495f0120204cc4b9c3590a9a4a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:07:45 +0000 Subject: [PATCH 11/32] GetDefaultAnchor will looks for IDataContextProviders --- .../MarkupExtensions/BindingExtension.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs index a466714136..7532e01f55 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -52,6 +52,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions // the context. object anchor = context.GetFirstParent(); + if(anchor is null) + { + anchor = context.GetFirstParent(); + } + // If a control was not found, then try to find the highest-level style as the XAML // file could be a XAML file containing only styles. return anchor ?? From 2ffb1af3bc0fbbcd6f666e4cf62d63111e9f03ef Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:08:55 +0000 Subject: [PATCH 12/32] add comment --- .../Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs index 7532e01f55..20f68df820 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -54,6 +54,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions if(anchor is null) { + // Try to find IDataContextProvider, this was added to allow us to find + // a datacontext for Application class when using NativeMenuItems. anchor = context.GetFirstParent(); } From 055115415c4aaad19f755aa525e778014444ec67 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:11:29 +0000 Subject: [PATCH 13/32] Application class uses AddOwner instead of making its own version of datacontext property. --- src/Avalonia.Controls/Application.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 9df92a49bc..9158ac7038 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -49,8 +49,7 @@ namespace Avalonia /// Defines the property. /// public static readonly StyledProperty DataContextProperty = - AvaloniaProperty.Register( - nameof(DataContext)); + StyledElement.DataContextProperty.AddOwner(); /// public event EventHandler ResourcesChanged; From c37562971734e5bbad55055ec47410235c48e3ad Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:31:12 +0000 Subject: [PATCH 14/32] restore app.xaml /cs --- samples/ControlCatalog/App.xaml | 5 ----- samples/ControlCatalog/App.xaml.cs | 6 ------ 2 files changed, 11 deletions(-) diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index 813a043b01..e40509dfda 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -17,9 +17,4 @@ - - - - - diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index b713c3dfd6..ea5ae0a75b 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -12,12 +12,6 @@ namespace ControlCatalog { public App() { - DataContext = this; - - AboutCommand = ReactiveCommand.Create(() => - { - - }); } public override void Initialize() From 79527e6ab9e195437fb533e1e12f2ab435682e45 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:35:15 +0000 Subject: [PATCH 15/32] restore app.xaml.cs --- samples/ControlCatalog/App.xaml.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index ea5ae0a75b..52a9591c94 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -1,33 +1,23 @@ -using System; -using System.Reactive; using Avalonia; -using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; -using ReactiveUI; namespace ControlCatalog { public class App : Application { - public App() - { - } - public override void Initialize() { AvaloniaXamlLoader.Load(this); } - public ReactiveCommand AboutCommand { get; } - public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) desktopLifetime.MainWindow = new MainWindow(); else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime) singleViewLifetime.MainView = new MainView(); - + base.OnFrameworkInitializationCompleted(); } } From 73e1224ac33de0e100bbbd3be8333569b4553777 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Mon, 25 Nov 2019 21:55:26 +0800 Subject: [PATCH 16/32] Ignore changes if isnt a valid double value. --- src/Avalonia.Controls/Primitives/RangeBase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index 39d00b6953..7155cceb8b 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -77,9 +77,9 @@ namespace Avalonia.Controls.Primitives { if (!ValidateDouble(value)) { - value = _minimum; + return; } - + if (IsInitialized) { SetAndRaise(MinimumProperty, ref _minimum, value); @@ -107,7 +107,7 @@ namespace Avalonia.Controls.Primitives { if (!ValidateDouble(value)) { - value = _maximum; + return; } if (IsInitialized) @@ -137,7 +137,7 @@ namespace Avalonia.Controls.Primitives { if (!ValidateDouble(value)) { - value = default; + return; } if (IsInitialized) @@ -178,7 +178,7 @@ namespace Avalonia.Controls.Primitives /// The value. private static bool ValidateDouble(double value) { - return (!double.IsInfinity(value) || !double.IsNaN(value)); + return !double.IsInfinity(value) || !double.IsNaN(value); } /// From f569287998ee37b90f5604683c11dd5704765e0e Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Mon, 25 Nov 2019 21:56:19 +0800 Subject: [PATCH 17/32] Update xml comment. --- src/Avalonia.Controls/Primitives/RangeBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index 7155cceb8b..baa51f92ec 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -173,7 +173,7 @@ namespace Avalonia.Controls.Primitives } /// - /// Throws an exception if the double value is NaN or Inf. + /// Checks if the double value is not inifinity nor NaN. /// /// The value. private static bool ValidateDouble(double value) From e23da2873111e7fabdf12c2e56abddca6d180aa0 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Mon, 25 Nov 2019 23:13:01 +0800 Subject: [PATCH 18/32] Remove obsolete unit test. --- .../Primitives/RangeBaseTests.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs index e2eb628512..34e6b228d0 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs @@ -82,22 +82,6 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.Equal(50, target.Value); } - [Fact] - public void Properties_Should_Not_Accept_Nan_And_Inifinity() - { - var target = new TestRange(); - - Assert.Throws(() => target.Minimum = double.NaN); - Assert.Throws(() => target.Minimum = double.PositiveInfinity); - Assert.Throws(() => target.Minimum = double.NegativeInfinity); - Assert.Throws(() => target.Maximum = double.NaN); - Assert.Throws(() => target.Maximum = double.PositiveInfinity); - Assert.Throws(() => target.Maximum = double.NegativeInfinity); - Assert.Throws(() => target.Value = double.NaN); - Assert.Throws(() => target.Value = double.PositiveInfinity); - Assert.Throws(() => target.Value = double.NegativeInfinity); - } - [Theory] [InlineData(true)] [InlineData(false)] From 552e536aec8dc993543b55fdc6ca0bb2d4eac61e Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 26 Nov 2019 22:38:47 +0100 Subject: [PATCH 19/32] Cache delegates used for reacting to logical and visual children changes. --- src/Avalonia.Styling/StyledElement.cs | 2 +- src/Avalonia.Visuals/Visual.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs index de8093c048..19bd17f123 100644 --- a/src/Avalonia.Styling/StyledElement.cs +++ b/src/Avalonia.Styling/StyledElement.cs @@ -288,7 +288,7 @@ namespace Avalonia var list = new AvaloniaList { ResetBehavior = ResetBehavior.Remove, - Validate = ValidateLogicalChild + Validate = logical => ValidateLogicalChild(logical) }; list.CollectionChanged += LogicalChildrenCollectionChanged; _logicalChildren = list; diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index f4306d3929..7ecd6b8171 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -121,7 +121,7 @@ namespace Avalonia { var visualChildren = new AvaloniaList(); visualChildren.ResetBehavior = ResetBehavior.Remove; - visualChildren.Validate = ValidateVisualChild; + visualChildren.Validate = visual => ValidateVisualChild(visual); visualChildren.CollectionChanged += VisualChildrenChanged; VisualChildren = visualChildren; } From 4b7e4313fe7c0d745e787ebe7fe6df9d25329046 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 27 Nov 2019 00:41:36 +0100 Subject: [PATCH 20/32] Bump version to 0.9.999 for CI builds. Now that 0.9 is (nearly) out, bump version on master. --- build/SharedVersion.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 44d5c239ef..897e70ff81 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.8.999 + 0.9.999 Copyright 2019 © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ From cff59382c78367859ab8a25da4987d8a62a1d451 Mon Sep 17 00:00:00 2001 From: FoggyFinder Date: Wed, 27 Nov 2019 11:16:28 +0200 Subject: [PATCH 21/32] adjust comments --- src/Avalonia.Input/InputElement.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Input/InputElement.cs b/src/Avalonia.Input/InputElement.cs index 535b930f8b..1e2a621bd1 100644 --- a/src/Avalonia.Input/InputElement.cs +++ b/src/Avalonia.Input/InputElement.cs @@ -342,7 +342,7 @@ namespace Avalonia.Input } /// - /// Gets or sets a value indicating whether the control is focused. + /// Gets a value indicating whether the control is focused. /// public bool IsFocused { @@ -360,7 +360,7 @@ namespace Avalonia.Input } /// - /// Gets or sets a value indicating whether the pointer is currently over the control. + /// Gets a value indicating whether the pointer is currently over the control. /// public bool IsPointerOver { From e61933c206857c829cde9c148b6b278e5bcce314 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 27 Nov 2019 19:59:45 +0000 Subject: [PATCH 22/32] [OSX] fix the osx menu on catalina. --- native/Avalonia.Native/src/OSX/app.mm | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm index 81855995b7..5c50aad4cc 100644 --- a/native/Avalonia.Native/src/OSX/app.mm +++ b/native/Avalonia.Native/src/OSX/app.mm @@ -1,16 +1,25 @@ #include "common.h" @interface AvnAppDelegate : NSObject @end + extern NSApplicationActivationPolicy AvnDesiredActivationPolicy = NSApplicationActivationPolicyRegular; @implementation AvnAppDelegate - (void)applicationWillFinishLaunching:(NSNotification *)notification { - [[NSApplication sharedApplication] setActivationPolicy: AvnDesiredActivationPolicy]; + if([[NSApplication sharedApplication] activationPolicy] != AvnDesiredActivationPolicy) + { + for (NSRunningApplication * app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) { + [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; + break; + } + + [[NSApplication sharedApplication] setActivationPolicy: AvnDesiredActivationPolicy]; + } } - (void)applicationDidFinishLaunching:(NSNotification *)notification { - [NSApp activateIgnoringOtherApps:true]; + [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; } @end @@ -20,5 +29,4 @@ extern void InitializeAvnApp() NSApplication* app = [NSApplication sharedApplication]; id delegate = [AvnAppDelegate new]; [app setDelegate:delegate]; - } From d7be0f9837ac353c4d17ce2cad0c11ac6709cb87 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:12:34 +0000 Subject: [PATCH 23/32] add implementation of platform handles on the managed side. --- .../Platform/IMacOSTopLevelPlatformHandle.cs | 15 +++++++++ src/Avalonia.Native/WindowImplBase.cs | 33 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs diff --git a/src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs b/src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs new file mode 100644 index 0000000000..837ea1abcd --- /dev/null +++ b/src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs @@ -0,0 +1,15 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; + +namespace Avalonia.Platform +{ + public interface IMacOSTopLevelPlatformHandle + { + IntPtr NSView { get; } + IntPtr GetNSViewRetained(); + IntPtr NSWindow { get; } + IntPtr GetNSWindowRetained(); + } +} diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 8b397403ca..f8c9c7c440 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -16,6 +16,34 @@ using Avalonia.Threading; namespace Avalonia.Native { + public class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle + { + IAvnWindowBase _native; + + public MacOSTopLevelWindowHandle(IAvnWindowBase native) + { + _native = native; + } + + public IntPtr Handle => IntPtr.Zero; + + public string HandleDescriptor => "NOT SUPPORTED"; + + public IntPtr NSView => throw new NotImplementedException(); + + public IntPtr NSWindow => throw new NotImplementedException(); + + public IntPtr GetNSViewRetained() + { + throw new NotImplementedException(); + } + + public IntPtr GetNSWindowRetained() + { + throw new NotImplementedException(); + } + } + public abstract class WindowBaseImpl : IWindowBaseImpl, IFramebufferPlatformSurface { @@ -45,6 +73,9 @@ namespace Avalonia.Native protected void Init(IAvnWindowBase window, IAvnScreens screens) { _native = window; + + Handle = new MacOSTopLevelWindowHandle(window); + _glSurface = new GlPlatformSurface(window); Screen = new ScreenImpl(screens); _savedLogicalSize = ClientSize; @@ -349,6 +380,6 @@ namespace Avalonia.Native } - public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED"); + public IPlatformHandle Handle { get; private set; } } } From c41ef366287b0ee857f193a96d73e30925b2f62e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:30:49 +0000 Subject: [PATCH 24/32] add osx implementation to get nsview and nswindow. --- native/Avalonia.Native/inc/avalonia-native.h | 4 ++ native/Avalonia.Native/src/OSX/window.mm | 48 ++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index f1c7664c3e..e5d67717c1 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -212,6 +212,10 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0; virtual HRESULT SetMainMenu(IAvnAppMenu* menu) = 0; virtual HRESULT ObtainMainMenu(IAvnAppMenu** retOut) = 0; + virtual HRESULT GetNSWindowHandle(void** ret) = 0; + virtual HRESULT GetNSWindowHandleRetained(void** ret) = 0; + virtual HRESULT GetNSViewHandle(void** ret) = 0; + virtual HRESULT GetNSViewHandleRetained(void** ret) = 0; virtual bool TryLock() = 0; virtual void Unlock() = 0; }; diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 0e85332555..ed86b2f612 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -83,6 +83,54 @@ public: [Window setContentView: View]; } + virtual HRESULT GetNSWindowHandle(void** ret) override + { + if (ret == nullptr) + { + return E_POINTER; + } + + *ret = (__bridge void*)Window; + + return S_OK; + } + + virtual HRESULT GetNSWindowHandleRetained(void** ret) override + { + if (ret == nullptr) + { + return E_POINTER; + } + + *ret = (__bridge_retained void*)Window; + + return S_OK; + } + + virtual HRESULT GetNSViewHandle(void** ret) override + { + if (ret == nullptr) + { + return E_POINTER; + } + + *ret = (__bridge void*)View; + + return S_OK; + } + + virtual HRESULT GetNSViewHandleRetained(void** ret) override + { + if (ret == nullptr) + { + return E_POINTER; + } + + *ret = (__bridge_retained void*)View; + + return S_OK; + } + virtual AvnWindow* GetNSWindow() override { return Window; From 9c67c805f96a04f15a46faaf3dfdf339d61ec175 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:41:44 +0000 Subject: [PATCH 25/32] fix method signature for sharpgen conventions. --- native/Avalonia.Native/inc/avalonia-native.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index e5d67717c1..becc354c0e 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -212,10 +212,10 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0; virtual HRESULT SetMainMenu(IAvnAppMenu* menu) = 0; virtual HRESULT ObtainMainMenu(IAvnAppMenu** retOut) = 0; - virtual HRESULT GetNSWindowHandle(void** ret) = 0; - virtual HRESULT GetNSWindowHandleRetained(void** ret) = 0; - virtual HRESULT GetNSViewHandle(void** ret) = 0; - virtual HRESULT GetNSViewHandleRetained(void** ret) = 0; + virtual HRESULT GetNSWindowHandle(void** ppv) = 0; + virtual HRESULT GetNSWindowHandleRetained(void** ppv) = 0; + virtual HRESULT GetNSViewHandle(void** ppv) = 0; + virtual HRESULT GetNSViewHandleRetained(void** ppv) = 0; virtual bool TryLock() = 0; virtual void Unlock() = 0; }; From 6cd6f71ee7c1037a8fe4cb7faa8653324c1c2f49 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:45:49 +0000 Subject: [PATCH 26/32] try out var --- native/Avalonia.Native/inc/avalonia-native.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index becc354c0e..9fa0123906 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -213,9 +213,9 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT SetMainMenu(IAvnAppMenu* menu) = 0; virtual HRESULT ObtainMainMenu(IAvnAppMenu** retOut) = 0; virtual HRESULT GetNSWindowHandle(void** ppv) = 0; - virtual HRESULT GetNSWindowHandleRetained(void** ppv) = 0; - virtual HRESULT GetNSViewHandle(void** ppv) = 0; - virtual HRESULT GetNSViewHandleRetained(void** ppv) = 0; + virtual HRESULT GetNSWindowHandleRetained(void** retOut) = 0; + virtual HRESULT GetNSViewHandle(void** retOut) = 0; + virtual HRESULT GetNSViewHandleRetained(void** retOut) = 0; virtual bool TryLock() = 0; virtual void Unlock() = 0; }; From 726d692cb675489fd54922dd7de8bc90e8117e06 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:48:03 +0000 Subject: [PATCH 27/32] use obtain instead of get so sharpgen doesnt generate invalid properties. --- native/Avalonia.Native/inc/avalonia-native.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 9fa0123906..06d6bdf311 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -212,10 +212,10 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0; virtual HRESULT SetMainMenu(IAvnAppMenu* menu) = 0; virtual HRESULT ObtainMainMenu(IAvnAppMenu** retOut) = 0; - virtual HRESULT GetNSWindowHandle(void** ppv) = 0; - virtual HRESULT GetNSWindowHandleRetained(void** retOut) = 0; - virtual HRESULT GetNSViewHandle(void** retOut) = 0; - virtual HRESULT GetNSViewHandleRetained(void** retOut) = 0; + virtual HRESULT ObtainNSWindowHandle(void** retOut) = 0; + virtual HRESULT ObtainNSWindowHandleRetained(void** retOut) = 0; + virtual HRESULT ObtainNSViewHandle(void** retOut) = 0; + virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0; virtual bool TryLock() = 0; virtual void Unlock() = 0; }; From b9f0898a37a9d004ae109c377e93509fd8a12f12 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 11:50:58 +0000 Subject: [PATCH 28/32] return native handles. --- src/Avalonia.Native/WindowImplBase.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index f8c9c7c440..d51da8fe1c 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -29,18 +29,18 @@ namespace Avalonia.Native public string HandleDescriptor => "NOT SUPPORTED"; - public IntPtr NSView => throw new NotImplementedException(); + public IntPtr NSView => _native.ObtainNSViewHandle(); - public IntPtr NSWindow => throw new NotImplementedException(); + public IntPtr NSWindow => _native.ObtainNSWindowHandle(); public IntPtr GetNSViewRetained() { - throw new NotImplementedException(); + return _native.ObtainNSViewHandleRetained(); } public IntPtr GetNSWindowRetained() { - throw new NotImplementedException(); + return _native.ObtainNSWindowHandleRetained(); } } From 916343448e8ac20a98da7ee38a728010495679d0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 13:54:00 +0000 Subject: [PATCH 29/32] make the default handle the NSWindow. --- src/Avalonia.Native/WindowImplBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index d51da8fe1c..e72fefe3ce 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -25,9 +25,9 @@ namespace Avalonia.Native _native = native; } - public IntPtr Handle => IntPtr.Zero; + public IntPtr Handle => NSWindow; - public string HandleDescriptor => "NOT SUPPORTED"; + public string HandleDescriptor => "NSWindow"; public IntPtr NSView => _native.ObtainNSViewHandle(); From 172da86e65e9a982fe078ce008bbf8398d2d794f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 14:00:43 +0000 Subject: [PATCH 30/32] fix Implementation method names. --- native/Avalonia.Native/src/OSX/window.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index ed86b2f612..021f6e5603 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -83,7 +83,7 @@ public: [Window setContentView: View]; } - virtual HRESULT GetNSWindowHandle(void** ret) override + virtual HRESULT ObtainNSWindowHandle(void** ret) override { if (ret == nullptr) { @@ -95,7 +95,7 @@ public: return S_OK; } - virtual HRESULT GetNSWindowHandleRetained(void** ret) override + virtual HRESULT ObtainNSWindowHandleRetained(void** ret) override { if (ret == nullptr) { @@ -107,7 +107,7 @@ public: return S_OK; } - virtual HRESULT GetNSViewHandle(void** ret) override + virtual HRESULT ObtainNSViewHandle(void** ret) override { if (ret == nullptr) { @@ -119,7 +119,7 @@ public: return S_OK; } - virtual HRESULT GetNSViewHandleRetained(void** ret) override + virtual HRESULT ObtainNSViewHandleRetained(void** ret) override { if (ret == nullptr) { From 0d2e10498f2f46d92ff34731eb1ca08dcb1c5672 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 28 Nov 2019 19:37:30 +0000 Subject: [PATCH 31/32] Window shouldnt call HandleClosed as this is called by TopLevel signaled by backed Closed event. --- src/Avalonia.Controls/Window.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 1816a6c81d..f66a248aaf 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -336,7 +336,6 @@ namespace Avalonia.Controls if (close) { PlatformImpl?.Dispose(); - HandleClosed(); } } } From b8b8e3f8cc16a7669a0360e00582390c55d4c16a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 29 Nov 2019 10:44:39 +0100 Subject: [PATCH 32/32] Fix IWindowImpl mocks to call Close on Dispose. --- tests/Avalonia.Controls.UnitTests/WindowTests.cs | 3 +-- tests/Avalonia.UnitTests/MockWindowingPlatform.cs | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index d87014f646..0508edd92f 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -228,8 +228,7 @@ namespace Avalonia.Controls.UnitTests { using (UnitTestApplication.Start(TestServices.StyledWindow)) { - var windowImpl = Mock.Of(x => x.Scaling == 1); - var target = new Window(windowImpl); + var target = new Window(); target.Show(); target.Close(); diff --git a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs index c33ec72141..a6701ef655 100644 --- a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs +++ b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs @@ -28,6 +28,10 @@ namespace Avalonia.UnitTests return CreatePopupMock().Object; }); + mock.Setup(x => x.Dispose()).Callback(() => + { + mock.Object.Closed?.Invoke(); + }); PixelPoint pos = default; mock.SetupGet(x => x.Position).Returns(() => pos); mock.Setup(x => x.Move(It.IsAny())).Callback(new Action(np => pos = np));