From 43e4b88f7cbc574a9fee8a5da194876bf5a468ef Mon Sep 17 00:00:00 2001 From: Dan Siegel Date: Thu, 24 Aug 2023 09:49:00 -0600 Subject: [PATCH 1/3] fix: adding window handler initialization (cherry picked from commit 0af3d7b35f09d324be3313341edaf2d27839e5c9) --- samples/MauiEmbedding/MauiEmbedding/App.cs | 2 +- .../Internals/EmbeddedWindowHandler.cs | 14 +++ .../MauiEmbedding.android.cs | 1 + .../MauiEmbedding.apple.cs | 5 +- src/Uno.Extensions.Maui.UI/MauiEmbedding.cs | 99 +++++++++++++++---- .../MauiEmbedding.windows.cs | 1 + .../Uno.Extensions.Maui.WinUI.csproj | 4 + 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 src/Uno.Extensions.Maui.UI/Internals/EmbeddedWindowHandler.cs diff --git a/samples/MauiEmbedding/MauiEmbedding/App.cs b/samples/MauiEmbedding/MauiEmbedding/App.cs index 0df30fb288..22b6fdafd3 100644 --- a/samples/MauiEmbedding/MauiEmbedding/App.cs +++ b/samples/MauiEmbedding/MauiEmbedding/App.cs @@ -13,6 +13,7 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args) var builder = this.CreateBuilder(args) // Add navigation support for toolkit controls such as TabBar and NavigationView .UseToolkitNavigation() + .UseMauiEmbedding(maui => maui.UseCustomLibrary()) .Configure(host => host #if DEBUG // Switch to Development environment when running in DEBUG @@ -61,7 +62,6 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args) // TODO: Register your services //services.AddSingleton(); }) - .UseMauiEmbedding(this, maui => maui.UseCustomLibrary()) .UseNavigation(RegisterRoutes) ); MainWindow = builder.Window; diff --git a/src/Uno.Extensions.Maui.UI/Internals/EmbeddedWindowHandler.cs b/src/Uno.Extensions.Maui.UI/Internals/EmbeddedWindowHandler.cs new file mode 100644 index 0000000000..3e8484cdda --- /dev/null +++ b/src/Uno.Extensions.Maui.UI/Internals/EmbeddedWindowHandler.cs @@ -0,0 +1,14 @@ +namespace Uno.Extensions.Maui.Internals; + +internal class EmbeddedWindowHandler : IElementHandler +{ + public object? PlatformView { get; set; } + public IElement? VirtualView { get; set; } + public IMauiContext? MauiContext { get; set; } + + public void DisconnectHandler() { } + public void Invoke(string command, object? args = null) { } + public void SetMauiContext(IMauiContext mauiContext) => MauiContext = mauiContext; + public void SetVirtualView(IElement view) => VirtualView = view; + public void UpdateValue(string property) { } +} diff --git a/src/Uno.Extensions.Maui.UI/MauiEmbedding.android.cs b/src/Uno.Extensions.Maui.UI/MauiEmbedding.android.cs index 11141ef293..099a8a3f1d 100644 --- a/src/Uno.Extensions.Maui.UI/MauiEmbedding.android.cs +++ b/src/Uno.Extensions.Maui.UI/MauiEmbedding.android.cs @@ -42,5 +42,6 @@ private static void InitializeMauiEmbeddingApp(this MauiApp mauiApp, Application Microsoft.Maui.ApplicationModel.Platform.Init(androidApp); androidApp.SetApplicationHandler(iApp, rootContext); + InitializeApplicationMainPage(iApp); } } diff --git a/src/Uno.Extensions.Maui.UI/MauiEmbedding.apple.cs b/src/Uno.Extensions.Maui.UI/MauiEmbedding.apple.cs index cac3bb7ee6..0950db62bf 100644 --- a/src/Uno.Extensions.Maui.UI/MauiEmbedding.apple.cs +++ b/src/Uno.Extensions.Maui.UI/MauiEmbedding.apple.cs @@ -1,4 +1,4 @@ -using UIKit; +using UIKit; using Uno.Extensions.Maui.Platform; namespace Uno.Extensions.Maui; @@ -26,8 +26,9 @@ private static void InitializeMauiEmbeddingApp(this MauiApp mauiApp, Application throw new MauiEmbeddingException(Properties.Resources.TheApplicationMustInheritFromEmbeddingApplication); } - // TODO: Evaluate getting the Root View Controller for a Platform.Init for Maui + Microsoft.Maui.ApplicationModel.Platform.Init(() => app.Window!.RootViewController!); embeddingApp.InitializeApplication(mauiApp.Services, iApp); app.SetApplicationHandler(iApp, rootContext); + InitializeApplicationMainPage(iApp); } } diff --git a/src/Uno.Extensions.Maui.UI/MauiEmbedding.cs b/src/Uno.Extensions.Maui.UI/MauiEmbedding.cs index 6f9fd9edc7..4921f32d1a 100644 --- a/src/Uno.Extensions.Maui.UI/MauiEmbedding.cs +++ b/src/Uno.Extensions.Maui.UI/MauiEmbedding.cs @@ -1,5 +1,5 @@ using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Maui; +using Uno.Extensions.Hosting; namespace Uno.Extensions.Maui; @@ -13,51 +13,65 @@ public static partial class MauiEmbedding /// /// The updated app builder. /// The IHost builder. - /// The Uno app. /// Optional lambda to configure the Maui app builder. - public static IHostBuilder UseMauiEmbedding(this IHostBuilder builder, Microsoft.UI.Xaml.Application app, Action? configure = null) => - builder.UseMauiEmbedding(app, configure); + public static IApplicationBuilder UseMauiEmbedding(this IApplicationBuilder builder, Action? configure = null) => + builder.UseMauiEmbedding(configure); /// /// Registers Maui embedding in the Uno Platform app builder. /// /// The updated app builder. /// The IHost builder. - /// The Uno app. /// Optional lambda to configure the Maui app builder. - public static IHostBuilder UseMauiEmbedding(this IHostBuilder builder, Microsoft.UI.Xaml.Application app, Action? configure = null) + public static IApplicationBuilder UseMauiEmbedding(this IApplicationBuilder builder, Action? configure = null) where TApp : MauiApplication { - app.UseMauiEmbedding(configure); + builder.App.UseMauiEmbedding(builder.Window, configure); return builder; } - private class MauiHostProviderFactory : IServiceProviderFactory - { - public IServiceProvider CreateBuilder(IServiceCollection services) => services.BuildServiceProvider(); - public IServiceProvider CreateServiceProvider(IServiceProvider containerBuilder) => containerBuilder; - } + /// + /// Registers Maui embedding in the Uno Platform app builder. + /// + /// The updated app builder. + /// The IHost builder. + /// The Uno app. + /// The Main Application Window. + /// Optional lambda to configure the Maui app builder. + public static IHostBuilder UseMauiEmbedding(this IHostBuilder builder, Microsoft.UI.Xaml.Application app, Microsoft.UI.Xaml.Window window, Action? configure = null) => + builder.UseMauiEmbedding(app, window, configure); - private class UnoHostProviderFactory : IServiceProviderFactory + /// + /// Registers Maui embedding in the Uno Platform app builder. + /// + /// The updated app builder. + /// The IHost builder. + /// The Uno app. + /// The Main Application Window. + /// Optional lambda to configure the Maui app builder. + public static IHostBuilder UseMauiEmbedding(this IHostBuilder builder, Microsoft.UI.Xaml.Application app, Microsoft.UI.Xaml.Window window, Action? configure = null) + where TApp : MauiApplication { - public IServiceCollection CreateBuilder(IServiceCollection services) => throw new NotImplementedException(); - public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder) => containerBuilder.BuildServiceProvider(); + app.UseMauiEmbedding(window, configure); + return builder; } /// /// Registers Maui embedding with WinUI3 and WPF application builder. /// /// The Uno app. + /// The Main Application Window. /// Optional lambda to configure the Maui app builder. - public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsoft.UI.Xaml.Application app, Action? configure = null) => - app.UseMauiEmbedding(configure); + public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsoft.UI.Xaml.Application app, Microsoft.UI.Xaml.Window window, Action? configure = null) => + app.UseMauiEmbedding(window, configure); /// /// Registers Maui embedding with WinUI3 and WPF application builder. /// /// The Uno app. + /// The Main Application Window. /// Optional lambda to configure the Maui app builder. - public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsoft.UI.Xaml.Application app, Action? configure = null) + public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsoft.UI.Xaml.Application app, Microsoft.UI.Xaml.Window window, Action? configure = null) where TApp : MauiApplication { #if MAUI_EMBEDDING @@ -65,7 +79,8 @@ public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsof .UseMauiEmbedding() .RegisterPlatformServices(app); - mauiAppBuilder.Services.AddSingleton(_ => app) + mauiAppBuilder.Services.AddSingleton(app) + .AddSingleton(window) .AddSingleton(); // HACK: https://github.com/dotnet/maui/pull/16758 @@ -80,6 +95,8 @@ public static Microsoft.UI.Xaml.Application UseMauiEmbedding(this Microsof return app; } +#if MAUI_EMBEDDING + private static void InitializeScopedServices(this IMauiContext scopedContext) { var scopedServices = scopedContext.Services.GetServices(); @@ -90,6 +107,50 @@ private static void InitializeScopedServices(this IMauiContext scopedContext) } } + private static void InitializeApplicationMainPage(IApplication iApp) + { + if (iApp is not MauiApplication app || app.Handler?.MauiContext is null) + { + // NOTE: This method is supposed to be called immediately after we initialize the Application Handler + // This should never actually happen but is required due to nullability + return; + } + + var context = app.Handler.MauiContext; + + // Create an Application Main Page and initialize a Handler with the Maui Context + var page = new ContentPage(); + app.MainPage = page; + _ = page.ToPlatform(context); + + // Create a Maui Window and initialize a Handler shim. This will expose the actual Application Window + var virtualWindow = new Microsoft.Maui.Controls.Window(page); + virtualWindow.Handler = new EmbeddedWindowHandler + { +#if IOS || MACCATALYST + PlatformView = context.Services.GetRequiredService().Window, +#elif ANDROID + PlatformView = context.Services.GetRequiredService(), +#elif WINDOWS + PlatformView = context.Services.GetRequiredService(), +#endif + VirtualView = virtualWindow, + MauiContext = context + }; + + app.SetCoreWindow(virtualWindow); + } + + private static void SetCoreWindow(this IApplication app, Microsoft.Maui.Controls.Window window) + { + if(app.Windows is List windows) + { + windows.Add(window); + } + } + +#endif + // NOTE: This was part of the POC and is out of scope for the MVP. Keeping it in case we want to add it back later. /* public static MauiAppBuilder MapControl(this MauiAppBuilder builder) diff --git a/src/Uno.Extensions.Maui.UI/MauiEmbedding.windows.cs b/src/Uno.Extensions.Maui.UI/MauiEmbedding.windows.cs index f5e110da3e..a7ba5aa705 100644 --- a/src/Uno.Extensions.Maui.UI/MauiEmbedding.windows.cs +++ b/src/Uno.Extensions.Maui.UI/MauiEmbedding.windows.cs @@ -38,5 +38,6 @@ private static void InitializeMauiEmbeddingApp(this MauiApp mauiApp, Application embeddingApp.InitializeApplication(mauiApp.Services, iApp); app.SetApplicationHandler(iApp, rootContext); + InitializeApplicationMainPage(iApp); } } diff --git a/src/Uno.Extensions.Maui.UI/Uno.Extensions.Maui.WinUI.csproj b/src/Uno.Extensions.Maui.UI/Uno.Extensions.Maui.WinUI.csproj index f442a85b28..9938879aa5 100644 --- a/src/Uno.Extensions.Maui.UI/Uno.Extensions.Maui.WinUI.csproj +++ b/src/Uno.Extensions.Maui.UI/Uno.Extensions.Maui.WinUI.csproj @@ -58,6 +58,10 @@ + + + + From 24acb0072146bc66da4aaf6b8309a38e2a2c34f5 Mon Sep 17 00:00:00 2001 From: Dan Siegel Date: Thu, 24 Aug 2023 09:49:38 -0600 Subject: [PATCH 2/3] chore: invalidate measure on resize (cherry picked from commit 2f6cb288d44b0575f60fc9d01c05fb1250bedbae) --- src/Uno.Extensions.Maui.UI/MauiHost.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Uno.Extensions.Maui.UI/MauiHost.cs b/src/Uno.Extensions.Maui.UI/MauiHost.cs index 06aa0cad13..ad9dd2cc6c 100644 --- a/src/Uno.Extensions.Maui.UI/MauiHost.cs +++ b/src/Uno.Extensions.Maui.UI/MauiHost.cs @@ -95,6 +95,12 @@ public MauiHost() DataContextChanged += OnDataContextChanged; Unloaded += OnMauiContentUnloaded; ActualThemeChanged += OnActualThemeChanged; + SizeChanged += OnSizeChanged; + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + EmbeddedView?.PlatformSizeChanged(); } private void OnActualThemeChanged(FrameworkElement sender, object args) From 48d3c027620c3ef95d100de80cb24260b9ad8255 Mon Sep 17 00:00:00 2001 From: Dan Siegel Date: Thu, 24 Aug 2023 13:11:24 -0600 Subject: [PATCH 3/3] chore: update Maui View property name (cherry picked from commit c0be32d9339dce68a8e1a4f4d4aebe75227253f9) --- src/Uno.Extensions.Maui.UI/MauiHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Uno.Extensions.Maui.UI/MauiHost.cs b/src/Uno.Extensions.Maui.UI/MauiHost.cs index ad9dd2cc6c..4edbcb6b22 100644 --- a/src/Uno.Extensions.Maui.UI/MauiHost.cs +++ b/src/Uno.Extensions.Maui.UI/MauiHost.cs @@ -100,7 +100,7 @@ public MauiHost() private void OnSizeChanged(object sender, SizeChangedEventArgs e) { - EmbeddedView?.PlatformSizeChanged(); + VisualElement?.PlatformSizeChanged(); } private void OnActualThemeChanged(FrameworkElement sender, object args)