Skip to content

Commit

Permalink
[Windows] fixing window glitches while moving or resizing (#14861)
Browse files Browse the repository at this point in the history
* Window glitch fix for windows

* Minor refactoring
  • Loading branch information
salarcode committed Aug 3, 2023
1 parent 800b5b0 commit e093edf
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
44 changes: 39 additions & 5 deletions src/Controls/src/Core/Window/Window.cs
Expand Up @@ -210,24 +210,58 @@ public double MinimumHeight

void IWindow.FrameChanged(Rect frame)
{
if (new Rect(X, Y, Width, Height) == frame)
var x = X;
var y = Y;
var width = Width;
var height = Height;
if (new Rect(x, y, width, height) == frame)
return;

_batchFrameUpdate++;

X = frame.X;
Y = frame.Y;
Width = frame.Width;
Height = frame.Height;
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);
SetValueCore(YProperty, frame.Y, SetValueFlags.None, SetValuePrivateFlags.Silent);
SetValueCore(WidthProperty, frame.Width, SetValueFlags.None, SetValuePrivateFlags.Silent);
SetValueCore(HeightProperty, frame.Height, SetValueFlags.None, SetValuePrivateFlags.Silent);

_batchFrameUpdate--;
if (_batchFrameUpdate < 0)
_batchFrameUpdate = 0;

if (_batchFrameUpdate == 0)
{
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);
}

[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);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue)
{
if (oldValue == newValue)
return;

OnPropertyChanged(name);
property.PropertyChanged?.Invoke(this, oldValue, newValue);
}
}

public event EventHandler<ModalPoppedEventArgs>? ModalPopped;
Expand Down
36 changes: 24 additions & 12 deletions src/Controls/tests/Core.UnitTests/WindowsTests.cs
Expand Up @@ -434,70 +434,82 @@ void ValidateSetup(Application app, Page page = null)
public void SettingCoreFrameOnlyFiresEventOnce()
{
var sizeChangedCount = 0;
var propertyChanges = new List<string>();
var changingProperties = new List<string>();
var changedProperties = new List<string>();

var window = new TestWindow();
window.SizeChanged += (sender, e) => sizeChangedCount++;
window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName);
window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName);
window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName);

((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400));

Assert.Equal(1, sizeChangedCount);
Assert.Equal(new[] { "X", "Y", "Width", "Height" }, propertyChanges);
Assert.Equal(new[] { "X", "Y", "Width", "Height" }, changingProperties);
Assert.Equal(new[] { "X", "Y", "Width", "Height" }, changedProperties);
}

[Fact]
public void SettingSameCoreFrameDoesNothing()
{
var sizeChangedCount = 0;
var propertyChanges = new List<string>();
var changingProperties = new List<string>();
var changedProperties = new List<string>();

var window = new TestWindow();
((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400));

window.SizeChanged += (sender, e) => sizeChangedCount++;
window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName);
window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName);
window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName);

((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400));

Assert.Equal(0, sizeChangedCount);
Assert.Empty(propertyChanges);
Assert.Empty(changingProperties);
Assert.Empty(changedProperties);
}

[Fact]
public void UpdatingSingleCoordinateOnlyFiresSinglePropertyAndFrameEvent()
{
var sizeChangedCount = 0;
var propertyChanges = new List<string>();
var changingProperties = new List<string>();
var changedProperties = new List<string>();

var window = new TestWindow();
((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400));

window.SizeChanged += (sender, e) => sizeChangedCount++;
window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName);
window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName);
window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName);

((IWindow)window).FrameChanged(new Rect(100, 250, 300, 400));

Assert.Equal(1, sizeChangedCount);
Assert.Equal(new[] { "Y" }, propertyChanges);
Assert.Equal(new[] { "Y" }, changingProperties);
Assert.Equal(new[] { "Y" }, changedProperties);
}

[Fact]
public void UpdatingSingleBoundOnlyFiresSingleProperty()
{
var sizeChangedCount = 0;
var propertyChanges = new List<string>();
var changingProperties = new List<string>();
var changedProperties = new List<string>();

var window = new TestWindow();
((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400));

window.SizeChanged += (sender, e) => sizeChangedCount++;
window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName);
window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName);
window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName);

((IWindow)window).FrameChanged(new Rect(100, 200, 350, 400));

Assert.Equal(1, sizeChangedCount);
Assert.Equal(new[] { "Width" }, propertyChanges);
Assert.Equal(new[] { "Width" }, changingProperties);
Assert.Equal(new[] { "Width" }, changedProperties);
}

[Fact]
Expand Down

0 comments on commit e093edf

Please sign in to comment.