From 07f14fe326c5878de750de9902299e0352f6b1dd Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Fri, 7 Feb 2025 14:09:48 +0100 Subject: [PATCH 1/8] test: Add sample for window metrics --- .../UITests.Shared/UITests.Shared.projitems | 13 +++-- .../WindowTests/Window_Metrics.xaml | 41 ++++++++++++++++ .../WindowTests/Window_Metrics.xaml.cs | 49 +++++++++++++++++++ 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml create mode 100644 src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems index 3c8961e891a9..cc910cf44e98 100644 --- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems +++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems @@ -1374,6 +1374,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -2389,7 +2393,7 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -6556,6 +6560,9 @@ Window_SetBackground.xaml + + Window_Metrics.xaml + XamlRoot_Properties.xaml @@ -7214,7 +7221,7 @@ PersonPictureLateBindingPage.xaml - + Pivot_CustomContent_Automated.xaml @@ -9926,4 +9933,4 @@ - + \ No newline at end of file diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml new file mode 100644 index 000000000000..192611d25aab --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs new file mode 100644 index 000000000000..f8cb33e8d67f --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Uno.UI.Samples.Controls; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; + +namespace UITests.Windows_UI_Xaml.WindowTests +{ + [Sample("Windowing")] + public sealed partial class Window_Metrics : UserControl + { + private Window _window; + + public Window_Metrics() + { + this.InitializeComponent(); + + _window = SamplesApp.App.MainWindow; + ExtendsIntoTitleBarCheckBox.IsChecked = _window.ExtendsContentIntoTitleBar; + ExtendsIntoTitleBarCheckBox.Checked += (s, e) => _window.ExtendsContentIntoTitleBar = true; + ExtendsIntoTitleBarCheckBox.Unchecked += (s, e) => _window.ExtendsContentIntoTitleBar = false; + + this.Loaded += Window_Metrics_Loaded; + } + + private void Window_Metrics_Loaded(object sender, RoutedEventArgs e) => GetMetricsClick(); + + private void GetMetricsClick() + { + AppWindowSize.Text = $"{_window.AppWindow.Size.Width} x {_window.AppWindow.Size.Height}"; + AppWindowPosition.Text = $"{_window.AppWindow.Position.X}, {_window.AppWindow.Position.Y}"; + AppWindowClientSize.Text = $"{_window.AppWindow.ClientSize.Width} x {_window.AppWindow.ClientSize.Height}"; + WindowBounds.Text = $"{_window.Bounds.X}, {_window.Bounds.Y}, {_window.Bounds.Width}, {_window.Bounds.Height}"; + XamlRootSize.Text = $"{XamlRoot.Size.Width} x {XamlRoot.Size.Height}"; + TitleBarHeight.Text = $"{_window.AppWindow.TitleBar.Height}"; + } + } +} From fdced3e4e5f9f42611e645dd08ecbba042306c3e Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Fri, 7 Feb 2025 14:10:04 +0100 Subject: [PATCH 2/8] chore: Target Android 35 for Samples app Android --- .../SamplesApp.netcoremobile/Android/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SamplesApp/SamplesApp.netcoremobile/Android/AndroidManifest.xml b/src/SamplesApp/SamplesApp.netcoremobile/Android/AndroidManifest.xml index 4615ce237cbf..45315d50a1aa 100644 --- a/src/SamplesApp/SamplesApp.netcoremobile/Android/AndroidManifest.xml +++ b/src/SamplesApp/SamplesApp.netcoremobile/Android/AndroidManifest.xml @@ -1,6 +1,6 @@  - + From 05eeefe67bb5f5e37cdb9e0236a52c386fbfe6b2 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Fri, 7 Feb 2025 17:15:43 +0100 Subject: [PATCH 3/8] fix: Adjust Window VisibleBounds calculation --- .../Native/NativeWindowWrapper.Android.cs | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs b/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs index 94be61b1230e..8396891b1a37 100644 --- a/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs +++ b/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs @@ -72,24 +72,24 @@ internal bool IsStatusBarTranslucent() internal void RaiseNativeSizeChanged() { - var (windowSize, visibleBounds, trueVisibleBounds) = GetVisualBounds(); + var (windowSize, visibleBounds) = GetVisualBounds(); Bounds = new Rect(default, windowSize); VisibleBounds = visibleBounds; Size = new((int)(windowSize.Width * RasterizationScale), (int)(windowSize.Height * RasterizationScale)); - if (_previousTrueVisibleBounds != trueVisibleBounds) + if (_previousTrueVisibleBounds != visibleBounds) { - _previousTrueVisibleBounds = trueVisibleBounds; + _previousTrueVisibleBounds = visibleBounds; // TODO: Adjust when multiple windows are supported on Android #13827 - ApplicationView.GetForCurrentView()?.SetTrueVisibleBounds(trueVisibleBounds); + ApplicationView.GetForCurrentView()?.SetTrueVisibleBounds(visibleBounds); } } protected override void ShowCore() => RemovePreDrawListener(); - private (Size windowSize, Rect visibleBounds, Rect trueVisibleBounds) GetVisualBounds() + private (Size windowSize, Rect visibleBounds) GetVisualBounds() { if (ContextHelper.Current is not Activity activity) { @@ -99,28 +99,44 @@ internal void RaiseNativeSizeChanged() var windowInsets = GetWindowInsets(activity); var insetsTypes = WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.DisplayCutout(); // == WindowInsets.Type.StatusBars() | WindowInsets.Type.NavigationBars() | WindowInsets.Type.CaptionBar(); + Rect windowBounds; + Rect visibleBounds; - var opaqueInsetsTypes = insetsTypes; - if (IsStatusBarTranslucent()) + if ((int)Android.OS.Build.VERSION.SdkInt < 35) { - opaqueInsetsTypes &= ~WindowInsetsCompat.Type.StatusBars(); + var opaqueInsetsTypes = insetsTypes; + if (IsStatusBarTranslucent()) + { + opaqueInsetsTypes &= ~WindowInsetsCompat.Type.StatusBars(); + } + if (IsNavigationBarTranslucent()) + { + opaqueInsetsTypes &= ~WindowInsetsCompat.Type.NavigationBars(); + } + + var insets = windowInsets?.GetInsets(insetsTypes).ToThickness() ?? default; + var opaqueInsets = windowInsets?.GetInsets(opaqueInsetsTypes).ToThickness() ?? default; + var translucentInsets = insets.Minus(opaqueInsets); + + // The native display size does not include any insets, so we remove the "opaque" insets under which we cannot draw anything + windowBounds = new Rect(default, GetDisplaySize().Subtract(opaqueInsets)); + + // The visible bounds is the windows bounds on which we remove also translucentInsets + visibleBounds = windowBounds.DeflateBy(translucentInsets); } - if (IsNavigationBarTranslucent()) + else { - opaqueInsetsTypes &= ~WindowInsetsCompat.Type.NavigationBars(); - } + var insets = windowInsets?.GetInsets(insetsTypes).ToThickness() ?? default; - var insets = windowInsets?.GetInsets(insetsTypes).ToThickness() ?? default; - var opaqueInsets = windowInsets?.GetInsets(opaqueInsetsTypes).ToThickness() ?? default; - var translucentInsets = insets.Minus(opaqueInsets); - - // The native display size does not include any insets, so we remove the "opaque" insets under which we cannot draw anything - var windowBounds = new Rect(default, GetDisplaySize().Subtract(opaqueInsets)); + // Edge-to-edge is default on Android 15 and above + windowBounds = new Rect(default, GetDisplaySize()); + visibleBounds = windowBounds.DeflateBy(insets); + } - // The visible bounds is the windows bounds on which we remove also translucentInsets - var visibleBounds = windowBounds.DeflateBy(translucentInsets); + var windowBoundsLogical = windowBounds.PhysicalToLogicalPixels(); + var visibleBoundsLogical = visibleBounds.PhysicalToLogicalPixels(); - return (windowBounds.PhysicalToLogicalPixels().Size, visibleBounds.PhysicalToLogicalPixels(), visibleBounds.PhysicalToLogicalPixels()); + return (windowBoundsLogical.Size, visibleBoundsLogical); } private bool IsNavigationBarTranslucent() From ebf6ac5513a59a97c86c512e0eda73ae230036d7 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Fri, 7 Feb 2025 17:16:06 +0100 Subject: [PATCH 4/8] chore: Improve window metrics sample --- .../WindowTests/Window_Metrics.xaml | 37 ++++++++++------- .../WindowTests/Window_Metrics.xaml.cs | 41 ++++++++++--------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml index 192611d25aab..3cb198573e9d 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml @@ -6,36 +6,43 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:UITests.Windows_UI_Xaml.WindowTests" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:ui="using:Uno.UI.Toolkit" d:DesignHeight="300" d:DesignWidth="400" mc:Ignorable="d"> - - - + + + - + - + - + - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs index f8cb33e8d67f..fdcdf051b647 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs @@ -1,19 +1,8 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Uno.UI.Samples.Controls; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; +using Uno.UI.Samples.Controls; +using Uno.UI.Toolkit; namespace UITests.Windows_UI_Xaml.WindowTests { @@ -38,12 +27,26 @@ public Window_Metrics() private void GetMetricsClick() { - AppWindowSize.Text = $"{_window.AppWindow.Size.Width} x {_window.AppWindow.Size.Height}"; - AppWindowPosition.Text = $"{_window.AppWindow.Position.X}, {_window.AppWindow.Position.Y}"; - AppWindowClientSize.Text = $"{_window.AppWindow.ClientSize.Width} x {_window.AppWindow.ClientSize.Height}"; - WindowBounds.Text = $"{_window.Bounds.X}, {_window.Bounds.Y}, {_window.Bounds.Width}, {_window.Bounds.Height}"; - XamlRootSize.Text = $"{XamlRoot.Size.Width} x {XamlRoot.Size.Height}"; - TitleBarHeight.Text = $"{_window.AppWindow.TitleBar.Height}"; + AppWindowSize.Text = GetSafe(() => $"{_window.AppWindow.Size.Width:F2} x {_window.AppWindow.Size.Height:F2}"); + AppWindowPosition.Text = GetSafe(() => $"{_window.AppWindow.Position.X:F2}, {_window.AppWindow.Position.Y:F2}"); + AppWindowClientSize.Text = GetSafe(() => $"{_window.AppWindow.ClientSize.Width:F2} x {_window.AppWindow.ClientSize.Height:F2}"); + WindowBounds.Text = GetSafe(() => $"{_window.Bounds.X:F2}, {_window.Bounds.Y:F2}, {_window.Bounds.Width:F2}, {_window.Bounds.Height:F2}"); + XamlRootSize.Text = GetSafe(() => $"{XamlRoot.Size.Width:F2} x {XamlRoot.Size.Height:F2}"); + TitleBarHeight.Text = GetSafe(() => $"{_window.AppWindow.TitleBar.Height:F2}"); + var padding = VisibleBoundsPadding.WindowPadding; + VisibleBoundsPaddingValue.Text = GetSafe(() => $"{padding.Left:F2}, {padding.Top:F2}, {padding.Right:F2}, {padding.Bottom:F2}"); + } + + private string GetSafe(Func getter) + { + try + { + return getter(); + } + catch (Exception) + { + return "N/A"; + } } } } From 5a7033fb1f6e708befa7b42ab69cc4535766dd55 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Fri, 7 Feb 2025 17:18:14 +0100 Subject: [PATCH 5/8] chore: Adjust formatting --- .../WindowTests/Window_Metrics.xaml.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs index fdcdf051b647..208a20702c40 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs @@ -27,14 +27,14 @@ public Window_Metrics() private void GetMetricsClick() { - AppWindowSize.Text = GetSafe(() => $"{_window.AppWindow.Size.Width:F2} x {_window.AppWindow.Size.Height:F2}"); - AppWindowPosition.Text = GetSafe(() => $"{_window.AppWindow.Position.X:F2}, {_window.AppWindow.Position.Y:F2}"); - AppWindowClientSize.Text = GetSafe(() => $"{_window.AppWindow.ClientSize.Width:F2} x {_window.AppWindow.ClientSize.Height:F2}"); - WindowBounds.Text = GetSafe(() => $"{_window.Bounds.X:F2}, {_window.Bounds.Y:F2}, {_window.Bounds.Width:F2}, {_window.Bounds.Height:F2}"); - XamlRootSize.Text = GetSafe(() => $"{XamlRoot.Size.Width:F2} x {XamlRoot.Size.Height:F2}"); - TitleBarHeight.Text = GetSafe(() => $"{_window.AppWindow.TitleBar.Height:F2}"); + AppWindowSize.Text = GetSafe(() => $"{_window.AppWindow.Size.Width:0.##} x {_window.AppWindow.Size.Height:0.##}"); + AppWindowPosition.Text = GetSafe(() => $"{_window.AppWindow.Position.X:0.##}, {_window.AppWindow.Position.Y:0.##}"); + AppWindowClientSize.Text = GetSafe(() => $"{_window.AppWindow.ClientSize.Width:0.##} x {_window.AppWindow.ClientSize.Height:0.##}"); + WindowBounds.Text = GetSafe(() => $"{_window.Bounds.X:0.##}, {_window.Bounds.Y:0.##}, {_window.Bounds.Width:0.##}, {_window.Bounds.Height:0.##}"); + XamlRootSize.Text = GetSafe(() => $"{XamlRoot.Size.Width:0.##} x {XamlRoot.Size.Height:0.##}"); + TitleBarHeight.Text = GetSafe(() => $"{_window.AppWindow.TitleBar.Height:0.##}"); var padding = VisibleBoundsPadding.WindowPadding; - VisibleBoundsPaddingValue.Text = GetSafe(() => $"{padding.Left:F2}, {padding.Top:F2}, {padding.Right:F2}, {padding.Bottom:F2}"); + VisibleBoundsPaddingValue.Text = GetSafe(() => $"{padding.Left:0.##}, {padding.Top:0.##}, {padding.Right:0.##}, {padding.Bottom:0.##}"); } private string GetSafe(Func getter) From e6a64dd1db697fdc264001cd9f2f15953f0057c5 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Mon, 10 Feb 2025 11:24:36 +0100 Subject: [PATCH 6/8] chore: Additional logging --- .../Native/NativeWindowWrapper.Android.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs b/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs index 8396891b1a37..c6f52471dd7b 100644 --- a/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs +++ b/src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.Android.cs @@ -6,6 +6,7 @@ using AndroidX.AppCompat.App; using AndroidX.Core.View; using Uno.Disposables; +using Uno.Foundation.Logging; using Uno.UI.Extensions; using Windows.ApplicationModel.Core; using Windows.Foundation; @@ -119,7 +120,7 @@ internal void RaiseNativeSizeChanged() var translucentInsets = insets.Minus(opaqueInsets); // The native display size does not include any insets, so we remove the "opaque" insets under which we cannot draw anything - windowBounds = new Rect(default, GetDisplaySize().Subtract(opaqueInsets)); + windowBounds = new Rect(default, GetWindowSize().Subtract(opaqueInsets)); // The visible bounds is the windows bounds on which we remove also translucentInsets visibleBounds = windowBounds.DeflateBy(translucentInsets); @@ -128,11 +129,21 @@ internal void RaiseNativeSizeChanged() { var insets = windowInsets?.GetInsets(insetsTypes).ToThickness() ?? default; + if (this.Log().IsEnabled(LogLevel.Debug)) + { + this.Log().LogDebug($"Insets: {insets}"); + } + // Edge-to-edge is default on Android 15 and above - windowBounds = new Rect(default, GetDisplaySize()); + windowBounds = new Rect(default, GetWindowSize()); visibleBounds = windowBounds.DeflateBy(insets); } + if (this.Log().IsEnabled(LogLevel.Debug)) + { + this.Log().LogDebug($"WindowBounds: {windowBounds}, VisibleBounds {visibleBounds}"); + } + var windowBoundsLogical = windowBounds.PhysicalToLogicalPixels(); var visibleBoundsLogical = visibleBounds.PhysicalToLogicalPixels(); @@ -167,7 +178,7 @@ private WindowInsetsCompat GetWindowInsets(Activity activity) return null; } - private Size GetDisplaySize() + private Size GetWindowSize() { if (ContextHelper.Current is not Activity activity) { @@ -182,13 +193,6 @@ private Size GetDisplaySize() displaySize = new Size(windowMetrics.Bounds.Width(), windowMetrics.Bounds.Height()); } else - { - SetDisplaySizeLegacy(); - } - - return displaySize; - - void SetDisplaySizeLegacy() { using var realMetrics = new DisplayMetrics(); @@ -200,6 +204,8 @@ void SetDisplaySizeLegacy() displaySize = new Size(realMetrics.WidthPixels, realMetrics.HeightPixels); } + + return displaySize; } protected override IDisposable ApplyFullScreenPresenter() From c6ea5e6fa044629a04b836771cdf49254b18fffc Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Mon, 10 Feb 2025 12:35:24 +0100 Subject: [PATCH 7/8] fix: Apply correct status bar color when theme changes on Android --- src/Uno.UI/UI/Xaml/Application.Android.cs | 11 ++ src/Uno.UI/UI/Xaml/Application.cs | 8 +- .../UI/Xaml/ApplicationActivity.Android.cs | 2 + .../StatusBar/StatusBar.Android.cs | 126 ++++++++++++------ 4 files changed, 105 insertions(+), 42 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Application.Android.cs b/src/Uno.UI/UI/Xaml/Application.Android.cs index ecf0ad9beccd..408f4006fcba 100644 --- a/src/Uno.UI/UI/Xaml/Application.Android.cs +++ b/src/Uno.UI/UI/Xaml/Application.Android.cs @@ -8,6 +8,8 @@ using Windows.Foundation.Metadata; using Windows.Globalization; using Microsoft.UI.Xaml.Controls.Primitives; +using Windows.UI.ViewManagement; +using Colors = Microsoft.UI.Colors; namespace Microsoft.UI.Xaml; @@ -28,4 +30,13 @@ static partial void StartPartial(ApplicationInitializationCallback callback) /// See - https://stackoverflow.com/a/3987733/732221 /// private DateTimeOffset GetSuspendingOffset() => DateTimeOffset.Now.AddSeconds(5); + + partial void ApplySystemOverlaysTheming() + { + var requestedTheme = InternalRequestedTheme; + + StatusBar.GetForCurrentView().ForegroundColor = requestedTheme == ApplicationTheme.Dark + ? Colors.White + : Colors.Black; + } } diff --git a/src/Uno.UI/UI/Xaml/Application.cs b/src/Uno.UI/UI/Xaml/Application.cs index 87c5a3bd6b31..82c5e18e6897 100644 --- a/src/Uno.UI/UI/Xaml/Application.cs +++ b/src/Uno.UI/UI/Xaml/Application.cs @@ -442,7 +442,13 @@ private void SetRequestedTheme(ApplicationTheme requestedTheme) internal void UpdateResourceBindingsForHotReload() => OnResourcesChanged(ResourceUpdateReason.HotReload); - internal void OnRequestedThemeChanged() => OnResourcesChanged(ResourceUpdateReason.ThemeResource); + internal void OnRequestedThemeChanged() + { + ApplySystemOverlaysTheming(); + OnResourcesChanged(ResourceUpdateReason.ThemeResource); + } + + partial void ApplySystemOverlaysTheming(); private void UpdateRootElementBackground() { diff --git a/src/Uno.UI/UI/Xaml/ApplicationActivity.Android.cs b/src/Uno.UI/UI/Xaml/ApplicationActivity.Android.cs index c04f8a0a4193..63915806b36d 100644 --- a/src/Uno.UI/UI/Xaml/ApplicationActivity.Android.cs +++ b/src/Uno.UI/UI/Xaml/ApplicationActivity.Android.cs @@ -70,6 +70,8 @@ public override void OnAttachedToWindow() { base.OnAttachedToWindow(); + StatusBar.GetForCurrentView().UpdateSystemUiVisibility(); + // Cannot call this in ctor: see // https://stackoverflow.com/questions/10593022/monodroid-error-when-calling-constructor-of-custom-view-twodscrollview#10603714 RaiseConfigurationChanges(); diff --git a/src/Uno.UWP/UI/ViewManagement/StatusBar/StatusBar.Android.cs b/src/Uno.UWP/UI/ViewManagement/StatusBar/StatusBar.Android.cs index 44fb17eaa566..f009a9ed0db7 100644 --- a/src/Uno.UWP/UI/ViewManagement/StatusBar/StatusBar.Android.cs +++ b/src/Uno.UWP/UI/ViewManagement/StatusBar/StatusBar.Android.cs @@ -1,10 +1,12 @@ using System.Threading.Tasks; using Android.App; using Android.Views; +using AndroidX.Core.View; using Uno.Foundation.Logging; using Uno.UI; using Windows.Foundation; using Windows.Graphics.Display; +using Windows.Storage; using Windows.UI.Core; namespace Windows.UI.ViewManagement @@ -14,7 +16,7 @@ public sealed partial class StatusBar private StatusBarForegroundType? _foregroundType; private bool? _isShown; - private readonly DisplayInformation _displayInformation = DisplayInformation.GetForCurrentViewSafe(); // TODO Uno: Avoid using this #16404. + private DisplayInformation _displayInformation; private int? _statusBarHeightResourceId; @@ -77,73 +79,115 @@ public Rect GetOccludedRect() return occludedRect; } - private double PhysicalToLogicalPixels(int physicalPixels) => physicalPixels / _displayInformation.RawPixelsPerViewPixel; - - public IAsyncAction ShowAsync() + private double PhysicalToLogicalPixels(int physicalPixels) { - return AsyncAction.FromTask(ct => - { - CoreDispatcher.CheckThreadAccess(); - _isShown = true; - UpdateSystemUiVisibility(); - Showing?.Invoke(this, null); - return Task.CompletedTask; - }); + _displayInformation ??= DisplayInformation.GetForCurrentViewSafe(); // TODO Uno: Avoid using this #16404 + return physicalPixels / _displayInformation.RawPixelsPerViewPixel; } - public IAsyncAction HideAsync() + public IAsyncAction ShowAsync() => SetVisibilityAsyncCore(true); + + public IAsyncAction HideAsync() => SetVisibilityAsyncCore(false); + + private IAsyncAction SetVisibilityAsyncCore(bool visible) { return AsyncAction.FromTask(ct => { CoreDispatcher.CheckThreadAccess(); - _isShown = false; + _isShown = visible; UpdateSystemUiVisibility(); - Hiding?.Invoke(this, null); + + if (visible) + { + Showing?.Invoke(this, null); + } + else + { + Hiding?.Invoke(this, null); + } + return Task.CompletedTask; }); } - private void UpdateSystemUiVisibility() + internal void UpdateSystemUiVisibility() { -#pragma warning disable 618 - var activity = ContextHelper.Current as Activity; - var decorView = activity.Window.DecorView; -#pragma warning disable CA1422 // Validate platform compatibility - var uiOptions = (int)decorView.SystemUiVisibility; -#pragma warning restore CA1422 // Validate platform compatibility - var newUiOptions = (int)uiOptions; + if (!ContextHelper.TryGetCurrent(out var context) || context is not Activity activity) + { + // The API was used too early in application lifecycle + return; + } + + var decorView = activity.Window?.DecorView; - if (_isShown.HasValue) + if (activity is null || decorView is null) { - if (_isShown.Value) - { - newUiOptions &= ~(int)SystemUiFlags.Fullscreen; - } - else + // The API was used too early in application lifecycle + return; + } + + if ((int)Android.OS.Build.VERSION.SdkInt >= 30) + { + var insetsController = WindowCompat.GetInsetsController(activity.Window, decorView); + if (insetsController != null) { - newUiOptions |= (int)SystemUiFlags.Fullscreen; + if (_isShown.HasValue) + { + if (_isShown.Value) + { + insetsController.Show(WindowInsetsCompat.Type.StatusBars()); + } + else + { + insetsController.Hide(WindowInsetsCompat.Type.StatusBars()); + } + } + + // A bit confusingly, "appearance light" refers to light theme, so in dark foreground is used! + insetsController.AppearanceLightStatusBars = _foregroundType == StatusBarForegroundType.Dark; } } - - if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M) + else { - if (_foregroundType == StatusBarForegroundType.Dark) +#pragma warning disable 618 +#pragma warning disable CA1422 // Validate platform compatibility + var uiOptions = (int)decorView.SystemUiVisibility; +#pragma warning restore CA1422 // Validate platform compatibility + var newUiOptions = (int)uiOptions; + + if (_isShown.HasValue) { - // Dark text to show up on your light status bar - newUiOptions |= (int)SystemUiFlags.LightStatusBar; + if (_isShown.Value) + { + newUiOptions &= ~(int)SystemUiFlags.Fullscreen; + } + else + { + newUiOptions |= (int)SystemUiFlags.Fullscreen; + } } - else if (_foregroundType == StatusBarForegroundType.Light) + + if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M) { - // Light text to show up on your dark status bar - newUiOptions &= ~(int)SystemUiFlags.LightStatusBar; + if (_foregroundType == StatusBarForegroundType.Dark) + { + // Dark text to show up on your light status bar + newUiOptions |= (int)SystemUiFlags.LightStatusBar; + } + else if (_foregroundType == StatusBarForegroundType.Light) + { + // Light text to show up on your dark status bar + newUiOptions &= ~(int)SystemUiFlags.LightStatusBar; + } } - } #pragma warning disable CA1422 // Validate platform compatibility - decorView.SystemUiVisibility = (StatusBarVisibility)newUiOptions; + decorView.SystemUiVisibility = (StatusBarVisibility)newUiOptions; #pragma warning restore CA1422 // Validate platform compatibility - activity.OnConfigurationChanged(activity.Resources.Configuration); #pragma warning restore 618 + } + + activity.OnConfigurationChanged(activity.Resources.Configuration); } private int StatusBarHeightResourceId => From d2aba26042ef9789b0956f5eb245fa809bb497fa Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Mon, 10 Feb 2025 20:12:01 +0100 Subject: [PATCH 8/8] chore: Adjust for UWP build --- .../Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs index 208a20702c40..2f295590ffac 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/WindowTests/Window_Metrics.xaml.cs @@ -27,12 +27,14 @@ public Window_Metrics() private void GetMetricsClick() { +#if HAS_UNO_WINUI // AppWindow APIs are only available in WinUI flavor of Uno Platform AppWindowSize.Text = GetSafe(() => $"{_window.AppWindow.Size.Width:0.##} x {_window.AppWindow.Size.Height:0.##}"); AppWindowPosition.Text = GetSafe(() => $"{_window.AppWindow.Position.X:0.##}, {_window.AppWindow.Position.Y:0.##}"); AppWindowClientSize.Text = GetSafe(() => $"{_window.AppWindow.ClientSize.Width:0.##} x {_window.AppWindow.ClientSize.Height:0.##}"); + TitleBarHeight.Text = GetSafe(() => $"{_window.AppWindow.TitleBar.Height:0.##}"); +#endif WindowBounds.Text = GetSafe(() => $"{_window.Bounds.X:0.##}, {_window.Bounds.Y:0.##}, {_window.Bounds.Width:0.##}, {_window.Bounds.Height:0.##}"); XamlRootSize.Text = GetSafe(() => $"{XamlRoot.Size.Width:0.##} x {XamlRoot.Size.Height:0.##}"); - TitleBarHeight.Text = GetSafe(() => $"{_window.AppWindow.TitleBar.Height:0.##}"); var padding = VisibleBoundsPadding.WindowPadding; VisibleBoundsPaddingValue.Text = GetSafe(() => $"{padding.Left:0.##}, {padding.Top:0.##}, {padding.Right:0.##}, {padding.Bottom:0.##}"); }