From 36474145283ed3f3037c641e2b8d3864d5e71e70 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Tue, 14 May 2024 22:07:40 -0300 Subject: [PATCH 01/12] just trigger SizeChanged when Window size changes --- src/Controls/src/Core/Window/Window.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index be74cc503588..d608603b4672 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -9,6 +9,7 @@ using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Platform; using Microsoft.Maui.Graphics; +using Microsoft.Maui.Layouts; namespace Microsoft.Maui.Controls { @@ -229,10 +230,13 @@ void IWindow.FrameChanged(Rect frame) { SetPropertyChanged(XProperty, nameof(X), x, frame.X); SetPropertyChanged(YProperty, nameof(Y), y, frame.Y); - SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); - SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); - SizeChanged?.Invoke(this, EventArgs.Empty); + if (width != frame.Width || height != frame.Height) + { + SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); + SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); + SizeChanged?.Invoke(this, EventArgs.Empty); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] From 552307df680bf0a7ffd18cd490b5882183417158 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Tue, 14 May 2024 22:29:14 -0300 Subject: [PATCH 02/12] adding unit test --- src/Controls/tests/Core.UnitTests/WindowsTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Controls/tests/Core.UnitTests/WindowsTests.cs b/src/Controls/tests/Core.UnitTests/WindowsTests.cs index 3270ef24b39e..3a43f78b6161 100644 --- a/src/Controls/tests/Core.UnitTests/WindowsTests.cs +++ b/src/Controls/tests/Core.UnitTests/WindowsTests.cs @@ -449,6 +449,20 @@ public void SettingCoreFrameOnlyFiresEventOnce() Assert.Equal(new[] { "X", "Y", "Width", "Height" }, changedProperties); } + [Fact] + public void MovingWindowDoNotTriggerSizeChanged() + { + var sizeChangedCount = 0; + + var window = new TestWindow(); + window.SizeChanged += (sender, e) => sizeChangedCount++; + + ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); + ((IWindow)window).FrameChanged(new Rect(200, 300, 300, 400)); + + Assert.Equal(1, sizeChangedCount); + } + [Fact] public void SettingSameCoreFrameDoesNothing() { From 2f771f92c6535f90b1f6c4ff00fb21b45dc3f942 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Wed, 15 May 2024 13:40:38 -0300 Subject: [PATCH 03/12] adjusted test to match new behavior --- src/Controls/tests/Core.UnitTests/WindowsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controls/tests/Core.UnitTests/WindowsTests.cs b/src/Controls/tests/Core.UnitTests/WindowsTests.cs index 3a43f78b6161..0e9a15993097 100644 --- a/src/Controls/tests/Core.UnitTests/WindowsTests.cs +++ b/src/Controls/tests/Core.UnitTests/WindowsTests.cs @@ -500,7 +500,7 @@ public void UpdatingSingleCoordinateOnlyFiresSinglePropertyAndFrameEvent() ((IWindow)window).FrameChanged(new Rect(100, 250, 300, 400)); - Assert.Equal(1, sizeChangedCount); + Assert.Equal(0, sizeChangedCount); Assert.Equal(new[] { "Y" }, changingProperties); Assert.Equal(new[] { "Y" }, changedProperties); } From fd5ea38764d232cf527c33d902be67e0f9227783 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 17:57:26 -0300 Subject: [PATCH 04/12] implement way to notify if handler should be aware of PC --- src/Controls/src/Core/Element/Element.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Controls/src/Core/Element/Element.cs b/src/Controls/src/Core/Element/Element.cs index 8d18b3e2458c..fb9fd1c7dfbe 100644 --- a/src/Controls/src/Core/Element/Element.cs +++ b/src/Controls/src/Core/Element/Element.cs @@ -567,11 +567,17 @@ protected virtual void OnParentSet() /// Method that is called when a bound property is changed. /// The name of the bound property that changed. - protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) + protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) => + OnPropertyChanged(propertyName, true); + + internal void OnPropertyChanged(string propertyName = null, bool propagateToHandler = true) { base.OnPropertyChanged(propertyName); - Handler?.UpdateValue(propertyName); + if (propagateToHandler) + { + Handler?.UpdateValue(propertyName); + } if (_effects?.Count > 0) { @@ -583,6 +589,7 @@ protected override void OnPropertyChanged([CallerMemberName] string propertyName } } + internal IEnumerable Descendants() => Descendants(); From 3aa94782aac6f6cf1fde78a8137ddb44d02dbae0 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 18:08:36 -0300 Subject: [PATCH 05/12] adjust SetPropertyChange method to accept the flag --- src/Controls/src/Core/Window/Window.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index d608603b4672..afd166f39d8d 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -233,8 +233,8 @@ void IWindow.FrameChanged(Rect frame) if (width != frame.Width || height != frame.Height) { - SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); - SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); + SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width, false); + SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height, false); SizeChanged?.Invoke(this, EventArgs.Empty); } } @@ -250,12 +250,12 @@ void SetPropertyChanging(BindableProperty property, string name, double oldValue } [MethodImpl(MethodImplOptions.AggressiveInlining)] - void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue) + void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue, bool shouldPropagateToHandler = true) { if (oldValue == newValue) return; - OnPropertyChanged(name); + OnPropertyChanged(name, shouldPropagateToHandler); property.PropertyChanged?.Invoke(this, oldValue, newValue); } } From 093a1fcf12503c32f9ab050bb2b96b5938ae063f Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 18:11:41 -0300 Subject: [PATCH 06/12] add the missing attribute Co-authored-by: Shane Neuville --- src/Controls/src/Core/Element/Element.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Element/Element.cs b/src/Controls/src/Core/Element/Element.cs index fb9fd1c7dfbe..ab2ee854a92f 100644 --- a/src/Controls/src/Core/Element/Element.cs +++ b/src/Controls/src/Core/Element/Element.cs @@ -570,7 +570,7 @@ protected virtual void OnParentSet() protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) => OnPropertyChanged(propertyName, true); - internal void OnPropertyChanged(string propertyName = null, bool propagateToHandler = true) + internal void OnPropertyChanged([CallerMemberName] string propertyName = null, bool propagateToHandler = true) { base.OnPropertyChanged(propertyName); From 221b2f1c38492ef7421967325a8b0392cd536252 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 20:09:21 -0300 Subject: [PATCH 07/12] update Window cs to match changes on main --- src/Controls/src/Core/Window/Window.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index afd166f39d8d..4ec47668ce45 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -200,7 +200,7 @@ double GetSizeCoordinate(BindableProperty property) } int _batchFrameUpdate = 0; - + bool disableHandlerUpdate; void IWindow.FrameChanged(Rect frame) { var x = X; @@ -233,8 +233,10 @@ void IWindow.FrameChanged(Rect frame) if (width != frame.Width || height != frame.Height) { - SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width, false); - SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height, false); + disableHandlerUpdate = true; + SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); + SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); + disableHandlerUpdate = false; SizeChanged?.Invoke(this, EventArgs.Empty); } } @@ -292,6 +294,14 @@ protected override void OnPropertyChanged([CallerMemberName] string? propertyNam Handler?.UpdateValue(nameof(IWindow.Content)); } + private protected override void UpdateHandlerValue(string property) + { + if (disableHandlerUpdate) + return; + + base.UpdateHandlerValue(property); + } + /// public bool AddOverlay(IWindowOverlay overlay) { From f51140074bc69ca1c8bb5a401d795e1213430715 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 20:39:36 -0300 Subject: [PATCH 08/12] revert Element.cs to main --- src/Controls/src/Core/Element/Element.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Controls/src/Core/Element/Element.cs b/src/Controls/src/Core/Element/Element.cs index d839b34571a2..bf3dada20406 100644 --- a/src/Controls/src/Core/Element/Element.cs +++ b/src/Controls/src/Core/Element/Element.cs @@ -567,17 +567,11 @@ protected virtual void OnParentSet() /// Method that is called when a bound property is changed. /// The name of the bound property that changed. - protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) => - OnPropertyChanged(propertyName, true); - - internal void OnPropertyChanged([CallerMemberName] string propertyName = null, bool propagateToHandler = true) + protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) { base.OnPropertyChanged(propertyName); - if (propagateToHandler) - { - UpdateHandlerValue(propertyName); - } + UpdateHandlerValue(propertyName); if (_effects?.Count > 0) { From 7d1227f3da8ec7517d004b713b4173fd866ccb70 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Thu, 16 May 2024 21:44:19 -0300 Subject: [PATCH 09/12] Revert changes on SetPropertyChanged method Co-authored-by: Shane Neuville --- src/Controls/src/Core/Window/Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 4ec47668ce45..7d3e2404b773 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -252,12 +252,12 @@ void SetPropertyChanging(BindableProperty property, string name, double oldValue } [MethodImpl(MethodImplOptions.AggressiveInlining)] - void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue, bool shouldPropagateToHandler = true) + void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue) { if (oldValue == newValue) return; - OnPropertyChanged(name, shouldPropagateToHandler); + OnPropertyChanged(name); property.PropertyChanged?.Invoke(this, oldValue, newValue); } } From 62bbe5d19bfd24b507793980e979d36173ec4ef4 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Fri, 17 May 2024 14:38:11 -0300 Subject: [PATCH 10/12] move Window class to old impl. and override UpdateHandlerValues --- src/Controls/src/Core/Window/Window.cs | 66 ++++++-------------------- 1 file changed, 14 insertions(+), 52 deletions(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 7d3e2404b773..86a9cf86a503 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -200,27 +200,18 @@ double GetSizeCoordinate(BindableProperty property) } int _batchFrameUpdate = 0; - bool disableHandlerUpdate; + void IWindow.FrameChanged(Rect frame) { - var x = X; - var y = Y; - var width = Width; - var height = Height; - if (new Rect(x, y, width, height) == frame) + if (new Rect(X, Y, Width, Height) == frame) return; _batchFrameUpdate++; - SetPropertyChanging(XProperty, nameof(X), x, frame.X); - SetPropertyChanging(YProperty, nameof(Y), y, frame.Y); - SetPropertyChanging(WidthProperty, nameof(Width), width, frame.Width); - SetPropertyChanging(HeightProperty, nameof(Height), height, frame.Height); - - SetValueCore(XProperty, frame.X, SetValueFlags.None, SetValuePrivateFlags.Silent, SetterSpecificity.FromHandler); - SetValueCore(YProperty, frame.Y, SetValueFlags.None, SetValuePrivateFlags.Silent, SetterSpecificity.FromHandler); - SetValueCore(WidthProperty, frame.Width, SetValueFlags.None, SetValuePrivateFlags.Silent, SetterSpecificity.FromHandler); - SetValueCore(HeightProperty, frame.Height, SetValueFlags.None, SetValuePrivateFlags.Silent, SetterSpecificity.FromHandler); + X = frame.X; + Y = frame.Y; + Width = frame.Width; + Height = frame.Height; _batchFrameUpdate--; if (_batchFrameUpdate < 0) @@ -228,40 +219,19 @@ void IWindow.FrameChanged(Rect frame) if (_batchFrameUpdate == 0) { - SetPropertyChanged(XProperty, nameof(X), x, frame.X); - SetPropertyChanged(YProperty, nameof(Y), y, frame.Y); - - if (width != frame.Width || height != frame.Height) - { - disableHandlerUpdate = true; - SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); - SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); - disableHandlerUpdate = false; - SizeChanged?.Invoke(this, EventArgs.Empty); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void SetPropertyChanging(BindableProperty property, string name, double oldValue, double newValue) - { - if (oldValue == newValue) - return; - - property.PropertyChanging?.Invoke(this, oldValue, newValue); - OnPropertyChanging(name); + SizeChanged?.Invoke(this, EventArgs.Empty); } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue) - { - if (oldValue == newValue) - return; + private protected override void UpdateHandlerValue(string property) + { + if (_batchFrameUpdate > 0) + return; - OnPropertyChanged(name); - property.PropertyChanged?.Invoke(this, oldValue, newValue); - } + base.UpdateHandlerValue(property); } + public event EventHandler? ModalPopped; public event EventHandler? ModalPopping; public event EventHandler? ModalPushed; @@ -294,14 +264,6 @@ protected override void OnPropertyChanged([CallerMemberName] string? propertyNam Handler?.UpdateValue(nameof(IWindow.Content)); } - private protected override void UpdateHandlerValue(string property) - { - if (disableHandlerUpdate) - return; - - base.UpdateHandlerValue(property); - } - /// public bool AddOverlay(IWindowOverlay overlay) { From 8ec4337b313e551fe17455da5168548c76553109 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Fri, 17 May 2024 14:41:59 -0300 Subject: [PATCH 11/12] add flag to trigger size changed --- src/Controls/src/Core/Window/Window.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 86a9cf86a503..b37300f8f38f 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -207,6 +207,7 @@ void IWindow.FrameChanged(Rect frame) return; _batchFrameUpdate++; + bool shouldTriggerSizeChanged = (Width != frame.Width) || (Height != frame.Height); X = frame.X; Y = frame.Y; @@ -217,7 +218,7 @@ void IWindow.FrameChanged(Rect frame) if (_batchFrameUpdate < 0) _batchFrameUpdate = 0; - if (_batchFrameUpdate == 0) + if (_batchFrameUpdate == 0 && shouldTriggerSizeChanged) { SizeChanged?.Invoke(this, EventArgs.Empty); } From df16a18e52c633d6e3a8bcf5ecb36ef35b8dc0ab Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Fri, 17 May 2024 17:03:07 -0300 Subject: [PATCH 12/12] add handle if the value changes during PC event --- src/Controls/src/Core/Window/Window.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index b37300f8f38f..3d37a59e2e8f 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -222,12 +222,33 @@ void IWindow.FrameChanged(Rect frame) { SizeChanged?.Invoke(this, EventArgs.Empty); } + + + // If for some reason during the PropertyChanged event on X,Y,Width,Height + // the user has changed these values. Then we need to propagate them back to the handler + UpdateHandler(X != frame.X, nameof(X)); + UpdateHandler(Y != frame.Y, nameof(Y)); + UpdateHandler(Width != frame.Width, nameof(Width)); + UpdateHandler(Height != frame.Height, nameof(Height)); + + + void UpdateHandler(bool condition, string property) + { + if (Handler is null || !condition) + { + return; + } + + Handler.UpdateValue(property); + } } private protected override void UpdateHandlerValue(string property) { - if (_batchFrameUpdate > 0) + if (_batchFrameUpdate > 0 && (property == nameof(X) || property == nameof(Y) || property == nameof(Width) || property == nameof(Height))) + { return; + } base.UpdateHandlerValue(property); }