Skip to content

Commit

Permalink
fix: dispatch safearea inset setter logic
Browse files Browse the repository at this point in the history
  • Loading branch information
kazo0 committed May 31, 2023
1 parent 7284d3f commit 251424c
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 38 deletions.
20 changes: 10 additions & 10 deletions samples/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@
<PackageVersion Include="Uno.Extensions.Logging.WebAssembly.Console" Version="1.4.0" />
<PackageVersion Include="Uno.Material" Version="2.6.0" />
<PackageVersion Include="Uno.Material.WinUI" Version="2.6.0" />
<PackageVersion Include="Uno.UI" Version="4.7.37" />
<PackageVersion Include="Uno.UI" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.5.9" />
<PackageVersion Include="Uno.UI.RemoteControl" Version="4.7.37" />
<PackageVersion Include="Uno.UI.Skia.Gtk" Version="4.7.37" />
<PackageVersion Include="Uno.UI.Skia.Tizen" Version="4.7.37" />
<PackageVersion Include="Uno.UI.Skia.Wpf" Version="4.7.37" />
<PackageVersion Include="Uno.UI.WebAssembly" Version="4.7.37" />
<PackageVersion Include="Uno.UI.RemoteControl" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UI.Skia.Gtk" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UI.Skia.Tizen" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UI.Skia.Wpf" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UI.WebAssembly" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.UniversalImageLoader" Version="1.9.35" />
<PackageVersion Include="Uno.Wasm.Bootstrap" Version="7.0.3" />
<PackageVersion Include="Uno.Wasm.Bootstrap.DevServer" Version="7.0.3" />
<PackageVersion Include="Uno.WinUI" Version="4.7.37" />
<PackageVersion Include="Uno.WinUI.RemoteControl" Version="4.7.37" />
<PackageVersion Include="Uno.WinUI.Skia.Gtk" Version="4.7.37" />
<PackageVersion Include="Uno.WinUI.WebAssembly" Version="4.7.37" />
<PackageVersion Include="Uno.WinUI" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.WinUI.RemoteControl" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.WinUI.Skia.Gtk" Version="4.10.0-dev.85" />
<PackageVersion Include="Uno.WinUI.WebAssembly" Version="4.10.0-dev.85" />
<PackageVersion Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.3" />
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.4.0.2" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.3.1.1" />
Expand Down
151 changes: 151 additions & 0 deletions src/Uno.Toolkit.RuntimeTests/Tests/SafeAreaTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Uno.Disposables;
using Uno.Toolkit.RuntimeTests.Extensions;
using Uno.Toolkit.RuntimeTests.Helpers;
using Uno.Toolkit.RuntimeTests.Tests.TestPages;
using Uno.Toolkit.UI;
using Uno.UI.RuntimeTests;
using Windows.System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

#if __IOS__
using UIKit;
#endif

#if IS_WINUI
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Windows.UI.ViewManagement;
#else
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI;
using Windows.UI.ViewManagement;
#endif

namespace Uno.Toolkit.RuntimeTests.Tests
{
[TestClass]
[RunsOnUIThread]
internal partial class SafeAreaTests
{
#if __ANDROID__
[TestMethod]
public async Task Translucent_SystemBars()
{
using var _ = UseFullWindow();
using var __ = UseTranslucentBars();

var redGrid = new Grid
{
Background = new SolidColorBrush(Colors.Red),
};

var blueGrid = new Grid
{
Background = new SolidColorBrush(Colors.Blue),
};

redGrid.Children.Add(blueGrid);

SafeArea.SetInsets(redGrid, SafeArea.InsetMask.VisibleBounds);

await UnitTestUIContentHelperEx.SetContentAndWait(redGrid);

var visibleBounds = ApplicationView.GetForCurrentView().VisibleBounds;
var blueRect = blueGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, blueGrid.ActualWidth, blueGrid.ActualHeight));
var redRect = redGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, redGrid.ActualWidth, redGrid.ActualHeight));

var statusBarHeight = visibleBounds.Top - redRect.Top;
var navAreaHeight = redRect.Bottom - visibleBounds.Bottom;

Assert.AreEqual(blueRect.Top, statusBarHeight);
Assert.AreEqual(blueRect.Bottom, redRect.Bottom - navAreaHeight);
Assert.AreEqual(redGrid.Padding.Top, statusBarHeight);
Assert.AreEqual(redGrid.Padding.Bottom, navAreaHeight);
}

[TestMethod]
public async Task Translucent_SystemBars_Dynamic()
{
using var _ = UseFullWindow();

var redGrid = new Grid
{
Background = new SolidColorBrush(Colors.Red),
};

var blueGrid = new Grid
{
Background = new SolidColorBrush(Colors.Blue),
};

redGrid.Children.Add(blueGrid);
SafeArea.SetInsets(redGrid, SafeArea.InsetMask.VisibleBounds);

await UnitTestUIContentHelperEx.SetContentAndWait(redGrid);

var blueWithOpaqueBars = blueGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, blueGrid.ActualWidth, blueGrid.ActualHeight));
var windowWithOpaqueBars = redGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, redGrid.ActualWidth, redGrid.ActualHeight));
var visibleBoundsWithOpaqueBars = ApplicationView.GetForCurrentView().VisibleBounds;

// before: windowWithOpaqueBars should be at (0, [statusBarHeight]) and the same size as visibleBoundsWithOpaqueBars
using var __ = UseTranslucentBars();
// after: windowWithTranslucentBars should be at (0, 0) and should differ from visibleBoundsWithTranslucentBars in height by [statusBarHeight] + [navAreaHeight]

await UnitTestsUIContentHelper.WaitForIdle();

var blueWithTranslucentBars = blueGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, blueGrid.ActualWidth, blueGrid.ActualHeight));
var windowWithTranslucentBars = redGrid.TransformToVisual(null).TransformBounds(new Windows.Foundation.Rect(0, 0, redGrid.ActualWidth, redGrid.ActualHeight));
var visibleBoundsWithTranslucentBars = ApplicationView.GetForCurrentView().VisibleBounds;

var statusBarHeight = windowWithOpaqueBars.Top - windowWithTranslucentBars.Top;
var navAreaHeight = windowWithTranslucentBars.Bottom - windowWithOpaqueBars.Bottom;

Assert.AreEqual(blueWithOpaqueBars, blueWithTranslucentBars);
Assert.AreEqual(blueWithTranslucentBars.Top, statusBarHeight);
Assert.AreEqual(blueWithTranslucentBars.Bottom, windowWithTranslucentBars.Bottom - navAreaHeight);
Assert.AreEqual(redGrid.Padding.Top, statusBarHeight);
Assert.AreEqual(redGrid.Padding.Bottom, navAreaHeight);
}


private IDisposable UseTranslucentBars()
{
var activity = Uno.UI.ContextHelper.Current as Android.App.Activity;
activity?.Window?.AddFlags(Android.Views.WindowManagerFlags.TranslucentNavigation | Android.Views.WindowManagerFlags.TranslucentStatus);

return Disposable.Create(() =>
{
activity?.Window?.ClearFlags(Android.Views.WindowManagerFlags.TranslucentNavigation | Android.Views.WindowManagerFlags.TranslucentStatus);
});
}

// The [RequiresFullWindow] attribute sets the app to fullscreen on Android, hiding all system bars.
// This method maintains the fullscreen state, but shows the system bars for tests that need them.
private IDisposable UseFullWindow()
{
UnitTestsUIContentHelper.UseActualWindowRoot = true;
UnitTestsUIContentHelper.SaveOriginalContent();

return Disposable.Create(() =>
{
UnitTestsUIContentHelper.RestoreOriginalContent();
UnitTestsUIContentHelper.UseActualWindowRoot = false;
});
}
#endif
}
}
41 changes: 23 additions & 18 deletions src/Uno.Toolkit.UI/Controls/SafeArea/SafeArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,6 @@ private static Rect GetVisibleBounds(Rect? safeAreaOverride = null, bool withSof
// the InputRect to align with the VisibleBounds Rect.
if (totalOffset > 0)
{


var navBarOffset = (totalOffset - statusBarOffset);

inputRect.Height -= navBarOffset;
Expand Down Expand Up @@ -562,10 +560,9 @@ private void ApplyInsets(Thickness insets)
{
return;
}

if (_insetMode == InsetMode.Padding
&& !PaddingHelper.GetPadding(owner).Equals(insets)
&& PaddingHelper.SetPadding(owner, insets))
if (_insetMode == InsetMode.Padding &&
!PaddingHelper.GetPadding(owner).Equals(insets) &&
PaddingHelper.SetPadding(owner, insets))
{
_appliedPadding = insets;
LogApplyInsets();
Expand All @@ -580,6 +577,11 @@ private void ApplyInsets(Thickness insets)
}
}

#if __ANDROID__
// Dispatching on Android prevents issues where layout/render changes, occurring
// during the initial loading of the view, are not always properly picked up by the layouting/rendering engine.
owner.GetDispatcherCompat().Schedule(owner.InvalidateMeasure);
#endif
void LogApplyInsets()
{
if (_log.IsEnabled(LogLevel.Debug))
Expand Down Expand Up @@ -652,21 +654,24 @@ internal void OnInsetModeChanged(InsetMode oldValue, InsetMode newValue)

if (Owner is { } owner)
{
if (oldValue == InsetMode.Margin)
{
_appliedMargin = new Thickness(0);
owner.Margin = _originalMargin;
}
else if (oldValue == InsetMode.Padding)
{
_appliedPadding = new Thickness(0);
PaddingHelper.SetPadding(owner, _originalPadding);
}
if (oldValue == InsetMode.Margin)
{
_appliedMargin = new Thickness(0);
owner.Margin = _originalMargin;
}
else if (oldValue == InsetMode.Padding)
{
_appliedPadding = new Thickness(0);
PaddingHelper.SetPadding(owner, _originalPadding);
}
#if __ANDROID__
// Dispatching on Android prevents issues where layout/render changes, occurring
// during the initial loading of the view, are not always properly picked up by the layouting/rendering engine.
owner.GetDispatcherCompat().Schedule(owner.InvalidateMeasure);
#endif
}

UpdateInsets();
}
}

}
}
22 changes: 12 additions & 10 deletions src/Uno.Toolkit.UI/Helpers/DispatcherCompat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,7 @@ public void Invoke(Priority priority, _Handler handler)
}
else
{
#if IS_WINUI
_impl.TryEnqueue(RemapPriority(priority), handler);
#else
_ = _impl.RunAsync(RemapPriority(priority), handler);
#endif
Schedule(priority, handler);
}
}

Expand All @@ -80,11 +76,7 @@ public Task RunAsync(Priority priority, _Handler handler)
{
var tcs = new TaskCompletionSource<object>();

#if IS_WINUI
_impl.TryEnqueue(RemapPriority(priority), () =>
#else
_ = _impl.RunAsync(RemapPriority(priority), () =>
#endif
Schedule(priority, () =>
{
try
{
Expand All @@ -100,4 +92,14 @@ public Task RunAsync(Priority priority, _Handler handler)
return tcs.Task;
}
}

public void Schedule(_Handler handler) => Schedule(default, handler);
public void Schedule(Priority priority, _Handler handler)
{
#if IS_WINUI
_impl.TryEnqueue(RemapPriority(priority), handler);
#else
_ = _impl.RunAsync(RemapPriority(priority), handler);
#endif
}
}

0 comments on commit 251424c

Please sign in to comment.