Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Unsingleton window factory on iOS #19222

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2584,7 +2584,7 @@ public async Task ValidateFootprint()
#if __IOS__
await RunOnUIThread(() =>
{
expectedCommandBarWidth = NativeWindowWrapper.Instance.GetWindowSize().Width;
expectedCommandBarWidth = WindowHelper.XamlRoot.HostWindow!.NativeWindowWrapper!.GetWindowSize().Width;
});
#endif
double expectedCommandBarCompactClosedHeight = 48;
Expand Down
43 changes: 0 additions & 43 deletions src/Uno.UI/UI/Xaml/Application.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ public partial class Application : UIApplicationDelegate
partial void InitializePartial()
{
SetCurrentLanguage();

SubscribeBackgroundNotifications();
}

public Application(NativeHandle handle) : base(handle)
Expand Down Expand Up @@ -189,47 +187,6 @@ private bool TryGetUserActivityFromLaunchOptions(NSDictionary launchOptions, out
return userActivity != null;
}

private void SubscribeBackgroundNotifications()
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.DidEnterBackgroundNotification, OnEnteredBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.WillEnterForegroundNotification, OnLeavingBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.DidActivateNotification, OnActivated);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.WillDeactivateNotification, OnDeactivated);
}
else
{
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidEnterBackgroundNotification, OnEnteredBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillEnterForegroundNotification, OnLeavingBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidBecomeActiveNotification, OnActivated);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillResignActiveNotification, OnDeactivated);
}
}

private void OnEnteredBackground(NSNotification notification)
{
NativeWindowWrapper.Instance.OnNativeVisibilityChanged(false);

RaiseEnteredBackground(() => RaiseSuspending());
}

private void OnLeavingBackground(NSNotification notification)
{
RaiseResuming();
RaiseLeavingBackground(() => NativeWindowWrapper.Instance.OnNativeVisibilityChanged(true));
}

private void OnActivated(NSNotification notification)
{
NativeWindowWrapper.Instance.OnNativeActivated(CoreWindowActivationState.CodeActivated);
}

private void OnDeactivated(NSNotification notification)
{
NativeWindowWrapper.Instance.OnNativeActivated(CoreWindowActivationState.Deactivated);
}

private void SetCurrentLanguage()
{
// net6.0-iOS does not automatically set the thread and culture info
Expand Down
4 changes: 4 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Flyout/FlyoutBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ private protected virtual void ShowAtCore(FrameworkElement placementTarget, Flyo
XamlRoot = placementTarget?.XamlRoot;
_popup.XamlRoot = XamlRoot;
_popup.PlacementTarget = placementTarget;
UpdatePopupPanelSizePartial();

if (showOptions != null)
{
Expand Down Expand Up @@ -483,6 +484,8 @@ private protected virtual void ShowAtCore(FrameworkElement placementTarget, Flyo
});
}

partial void UpdatePopupPanelSizePartial();

private void SetTargetPosition(Point targetPoint)
{
m_isTargetPositionSet = true;
Expand Down Expand Up @@ -542,6 +545,7 @@ protected internal virtual void Open()
{
_popup.XamlRoot = XamlRoot;
}
UpdatePopupPanelSizePartial();

_popup.IsOpen = true;

Expand Down
9 changes: 8 additions & 1 deletion src/Uno.UI/UI/Xaml/Controls/Flyout/FlyoutBase.iOSmacOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ partial void InitializePopupPanelPartial()
NSViewResizingMask.MinYMargin |
NSViewResizingMask.MaxYMargin,
#endif
Frame = new CGRect(CGPoint.Empty, NativeWindowWrapper.Instance.GetWindowSize())
};
}

partial void UpdatePopupPanelSizePartial()
{
if (XamlRoot?.HostWindow is { } window)
{
_popup.PopupPanel.Frame = new CGRect(CGPoint.Empty, window.NativeWindowWrapper.GetWindowSize());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ protected override void InitializePopupPanel()
Visibility = Visibility.Collapsed,
Background = SolidColorBrushHelper.Transparent,
AutoresizingMask = UIViewAutoresizing.All,
Frame = new CGRect(CGPoint.Empty, NativeWindowWrapper.Instance.GetWindowSize())
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ partial class ContentManager
{
static partial void AttachToWindowPlatform(UIElement rootElement, Microsoft.UI.Xaml.Window window)
{
if (window.NativeWindowWrapper is not NativeWindowWrapper nativeWindowWrapper)
{
throw new InvalidOperationException("The window must be initialized before attaching the root element.");
}

if (rootElement.Superview is null)
{
NativeWindowWrapper.Instance.MainController.View!.AddSubview(rootElement);
nativeWindowWrapper.MainController.View!.AddSubview(rootElement);
}
rootElement.Frame = NativeWindowWrapper.Instance.MainController.View!.Bounds;
rootElement.Frame = nativeWindowWrapper.MainController.View!.Bounds;
rootElement.AutoresizingMask = UIViewAutoresizing.All;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public BaseWindowImplementation(Window window)

protected Window Window { get; }

protected INativeWindowWrapper? NativeWindowWrapper { get; private set; }
public INativeWindowWrapper? NativeWindowWrapper { get; private set; }

public abstract CoreWindow? CoreWindow { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace Uno.UI.Xaml.Controls;

internal interface IWindowImplementation
{
INativeWindowWrapper? NativeWindowWrapper { get; }

bool Visible { get; }

string Title { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#nullable enable
#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;

namespace Uno.UI.Xaml.Controls;

internal partial class NativeWindowFactory
{
public static bool SupportsClosingCancellation => false;

public static bool SupportsMultipleWindows => false;

private static INativeWindowWrapper? CreateWindowPlatform(Microsoft.UI.Xaml.Window window, XamlRoot xamlRoot) =>
new NativeWindowWrapper(window, xamlRoot);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#nullable enable
#if !__SKIA__
#if !__SKIA__ && !__IOS__

using System;
using Uno.Foundation.Extensibility;
Expand Down
4 changes: 4 additions & 0 deletions src/Uno.UI/UI/Xaml/Window/Native/INativeWindowWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ internal interface INativeWindowWrapper : INativeAppWindow
void Close();

void ExtendContentIntoTitleBar(bool extend);

#if __IOS__ || __MACOS__
Size GetWindowSize();
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace Uno.UI.Xaml.Controls;

internal class NativeWindowWrapper : NativeWindowWrapperBase
internal class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

Expand Down
67 changes: 51 additions & 16 deletions src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapper.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,33 @@
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.Graphics;
using MUXWindow = Microsoft.UI.Xaml.Window;
using NativeWindow = Uno.UI.Controls.Window;
using Microsoft.UI.Xaml;
using static Microsoft.UI.Xaml.Controls.Primitives.LoopingSelectorItem;

namespace Uno.UI.Xaml.Controls;

internal class NativeWindowWrapper : NativeWindowWrapperBase
internal class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

private Uno.UI.Controls.Window _nativeWindow;
private NativeWindow _nativeWindow;

private RootViewController _mainController;
private NSObject _orientationRegistration;
private readonly DisplayInformation _displayInformation;

public NativeWindowWrapper()
public NativeWindowWrapper(MUXWindow window, XamlRoot xamlRoot)
{
_nativeWindow = new Uno.UI.Controls.Window();
_nativeWindow = new NativeWindow();

_mainController = Microsoft.UI.Xaml.Window.ViewControllerGenerator?.Invoke() ?? new RootViewController();
_mainController = MUXWindow.ViewControllerGenerator?.Invoke() ?? new RootViewController();
_mainController.View.BackgroundColor = UIColor.Clear;
_mainController.NavigationBarHidden = true;

ObserveOrientationAndSize();

SubscribeBackgroundNotifications();

#if __MACCATALYST__
_nativeWindow.SetOwner(CoreWindow.GetForCurrentThreadSafe());
#endif
Expand All @@ -41,9 +45,7 @@ public NativeWindowWrapper()
DispatchDpiChanged();
}

public override Uno.UI.Controls.Window NativeWindow => _nativeWindow;

internal static NativeWindowWrapper Instance => _instance.Value;
public override NativeWindow NativeWindow => _nativeWindow;

private void DispatchDpiChanged() =>
RasterizationScale = (float)_displayInformation.RawPixelsPerViewPixel;
Expand All @@ -58,8 +60,6 @@ protected override void ShowCore()

internal void OnNativeVisibilityChanged(bool visible) => IsVisible = visible;

internal void OnNativeActivated(CoreWindowActivationState state) => ActivationState = state;

internal void OnNativeClosed() => RaiseClosing(); // TODO: Handle closing cancellation when multiwindow is supported #13847

internal void RaiseNativeSizeChanged()
Expand Down Expand Up @@ -99,16 +99,16 @@ private void ObserveOrientationAndSize()
RaiseNativeSizeChanged();
}

internal Size GetWindowSize()
public override Size GetWindowSize()
{
var nativeFrame = NativeWindow?.Frame ?? CGRect.Empty;

return new Size(nativeFrame.Width, nativeFrame.Height);
}

private void SetVisibleBounds(UIKit.UIWindow keyWindow, Windows.Foundation.Size windowSize)
private void SetVisibleBounds(UIWindow keyWindow, Size windowSize)
{
var windowBounds = new Windows.Foundation.Rect(default, windowSize);
var windowBounds = new Rect(default, windowSize);

var inset = UseSafeAreaInsets
? keyWindow.SafeAreaInsets
Expand All @@ -123,7 +123,7 @@ private void SetVisibleBounds(UIKit.UIWindow keyWindow, Windows.Foundation.Size

inset.Top = (nfloat)Math.Max(inset.Top, statusBarHeight);

var newVisibleBounds = new Windows.Foundation.Rect(
var newVisibleBounds = new Rect(
x: windowBounds.Left + inset.Left,
y: windowBounds.Top + inset.Top,
width: windowBounds.Width - inset.Right - inset.Left,
Expand All @@ -141,4 +141,39 @@ protected override IDisposable ApplyFullScreenPresenter()
UIApplication.SharedApplication.StatusBarHidden = true;
return Disposable.Create(() => UIApplication.SharedApplication.StatusBarHidden = false);
}

private void SubscribeBackgroundNotifications()
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.DidEnterBackgroundNotification, OnEnteredBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.WillEnterForegroundNotification, OnLeavingBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.DidActivateNotification, OnActivated);
NSNotificationCenter.DefaultCenter.AddObserver(UIScene.WillDeactivateNotification, OnDeactivated);
}
else
{
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidEnterBackgroundNotification, OnEnteredBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillEnterForegroundNotification, OnLeavingBackground);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidBecomeActiveNotification, OnActivated);
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillResignActiveNotification, OnDeactivated);
}
}

private void OnEnteredBackground(NSNotification notification)
{
OnNativeVisibilityChanged(false);

Application.Current.RaiseEnteredBackground(() => Application.Current.RaiseSuspending());
}

private void OnLeavingBackground(NSNotification notification)
{
Application.Current.RaiseResuming();
Application.Current.RaiseLeavingBackground(() => OnNativeVisibilityChanged(true));
}

private void OnActivated(NSNotification notification) => ActivationState = CoreWindowActivationState.CodeActivated;

private void OnDeactivated(NSNotification notification) => ActivationState = CoreWindowActivationState.Deactivated;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

namespace Uno.UI.Xaml.Controls;

internal class NativeWindowWrapper : NativeWindowWrapperBase
internal class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Uno.UI.Xaml.Controls;

internal partial class NativeWindowWrapper : NativeWindowWrapperBase
internal partial class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Uno.UI.Xaml.Controls;

internal partial class NativeWindowWrapper : NativeWindowWrapperBase
internal partial class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Uno.UI.Xaml.Controls;

internal partial class NativeWindowWrapper : NativeWindowWrapperBase
internal partial class NativeWindowWrapper : NativeWindowWrapperBase, INativeWindowWrapper
{
private static readonly Lazy<NativeWindowWrapper> _instance = new(() => new NativeWindowWrapper());

Expand Down
4 changes: 4 additions & 0 deletions src/Uno.UI/UI/Xaml/Window/Native/NativeWindowWrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,8 @@ public virtual void Resize(SizeInt32 size)
public void Destroy() { }

public void Hide() { }

#if __IOS__ || __MACOS__
public abstract Size GetWindowSize();
#endif
}
2 changes: 2 additions & 0 deletions src/Uno.UI/UI/Xaml/Window/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ internal Window(WindowType windowType)
global::Windows.Graphics.Display.DisplayInformation.GetOrCreateForWindowId(AppWindow.Id);
}

internal INativeWindowWrapper? NativeWindowWrapper => _windowImplementation.NativeWindowWrapper;

internal static Window GetFromAppWindow(AppWindow appWindow)
{
if (!_appWindowMap.TryGetValue(appWindow, out var window))
Expand Down
Loading