-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Xaml UI Hosting #15223
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
Xaml UI Hosting #15223
Changes from all commits
28b1471
7cb5b7e
ffa1c03
b7cbe82
ed1e67c
0a95df7
6861056
b3d5b4f
c90b1da
9357561
805ba4d
46dc340
9889e8c
284c423
522cf31
529423b
9b6aa17
b9036c3
11c54ea
6b92ff5
b179f47
713b950
c2aa6d4
572a024
8392fc5
9aa90f6
b477234
c298c47
e0baeb1
b9f8621
8075851
fe8e41e
bc34500
0e025a4
d07d6cb
2b9836d
577d5af
7b4cc7a
9879fb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "prerelease", | ||
| "comment": "Introduce xamlhost component", | ||
| "packageName": "react-native-windows", | ||
| "email": "[email protected]", | ||
| "dependentChangeType": "patch" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| <Application | ||
| x:Class="Microsoft.ReactNative.Xaml.XamlApplication" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> | ||
| </Application> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |||||||
|
|
||||||||
| #include <Fabric/FabricUIManagerModule.h> | ||||||||
| #include <winrt/Microsoft.UI.Input.h> | ||||||||
| #include "CompositionDynamicAutomationProvider.h" | ||||||||
| #include "CompositionRootAutomationProvider.h" | ||||||||
| #include "ReactNativeIsland.h" | ||||||||
| #include "Theme.h" | ||||||||
|
|
@@ -275,7 +276,7 @@ facebook::react::Point RootComponentView::getClientOffset() const noexcept { | |||||||
| return {}; | ||||||||
| } | ||||||||
|
|
||||||||
| winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixels) noexcept { | ||||||||
| winrt::IUnknown RootComponentView::UiaProviderFromPoint(const POINT &ptPixels, const POINT &ptScreen) noexcept { | ||||||||
| facebook::react::Point ptDips{ | ||||||||
| static_cast<facebook::react::Float>(ptPixels.x) / m_layoutMetrics.pointScaleFactor, | ||||||||
| static_cast<facebook::react::Float>(ptPixels.y) / m_layoutMetrics.pointScaleFactor}; | ||||||||
|
|
@@ -295,7 +296,41 @@ winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixel | |||||||
| if (view == nullptr) | ||||||||
| return nullptr; | ||||||||
|
|
||||||||
| return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)->EnsureUiaProvider(); | ||||||||
| auto uiaProvider = | ||||||||
| winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)->EnsureUiaProvider(); | ||||||||
|
|
||||||||
| // TODO: Avoid exposing CompositionDynamicAutomationProvider in RootComponentView | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please file a follow-up task for this and paste its link here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #15317 - I already created a task and adding pending sub tasks to it. Will add this here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, please add the task to the comment too.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||
| // TODO: Avoid exposing CompositionDynamicAutomationProvider in RootComponentView | |
| // TODO: Avoid exposing CompositionDynamicAutomationProvider in RootComponentView. | |
| // See tracking issue: https://github.com/microsoft/react-native-windows/issues/XXXX |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
|
|
||
| #include "DocString.h" | ||
|
|
||
| namespace Microsoft.ReactNative.Xaml { | ||
| [webhosthidden] | ||
| interface IXamlControl { | ||
| DOC_STRING( | ||
| "Native components that want to be Xaml-based can implement IXamlControl to allow their object to be parented to a XamlHost.") | ||
| Microsoft.UI.Xaml.UIElement GetXamlElement(); | ||
| }; | ||
| } // namespace Microsoft.ReactNative.Xaml |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #include "pch.h" | ||
| #include "XamlApplication.h" | ||
| #include "Xaml.XamlApplication.g.cpp" | ||
|
|
||
| #include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h" | ||
|
|
||
| namespace winrt::Microsoft::ReactNative::Xaml::implementation { | ||
| using namespace ::winrt::Microsoft::UI::Xaml; | ||
| using namespace ::winrt::Microsoft::UI::Xaml::Markup; | ||
| using namespace ::winrt::Windows::UI::Xaml::Interop; | ||
| XamlApplication::XamlApplication() { | ||
| s_current = *this; | ||
|
|
||
| // TODO: It's probably not a good idea to only load the controls pri file, there are other ones too. | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| auto resourceManager = | ||
| winrt::Microsoft::Windows::ApplicationModel::Resources::ResourceManager(L"Microsoft.UI.Xaml.Controls.pri"); | ||
|
|
||
| this->ResourceManagerRequested([resourceManager](auto &&, ResourceManagerRequestedEventArgs args) { | ||
| args.CustomResourceManager(resourceManager); | ||
| }); | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread(); | ||
sundaramramaswamy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| m_providers.push_back( | ||
| winrt::make_self<winrt::Microsoft::ReactNative::implementation::XamlMetaDataProvider>() | ||
| .as<winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider>()); // Default generated provider | ||
| m_providers.push_back(winrt::Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider()); | ||
|
|
||
| auto winUIResources = winrt::Microsoft::UI::Xaml::Controls::XamlControlsResources(); | ||
| Resources().MergedDictionaries().Append(winUIResources); | ||
| } | ||
|
|
||
| XamlApplication::~XamlApplication() { | ||
| s_current = nullptr; | ||
| } | ||
|
|
||
| void XamlApplication::AddMetadataProvider( | ||
| winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider) { | ||
| m_providers.push_back(otherProvider); | ||
| } | ||
|
|
||
| winrt::Microsoft::UI::Xaml::Markup::IXamlType XamlApplication::GetXamlType( | ||
| winrt::Windows::UI::Xaml::Interop::TypeName const &type) { | ||
| for (const auto &provider : m_providers) { | ||
| if (auto result = provider.GetXamlType(type)) { | ||
| return result; | ||
| } | ||
| } | ||
| return nullptr; | ||
| } | ||
|
|
||
| winrt::Microsoft::UI::Xaml::Markup::IXamlType XamlApplication::GetXamlType(hstring const &fullName) { | ||
| for (const auto &provider : m_providers) { | ||
| if (auto result = provider.GetXamlType(fullName)) { | ||
| return result; | ||
| } | ||
| } | ||
|
|
||
| return nullptr; | ||
| } | ||
| com_array<winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> XamlApplication::GetXmlnsDefinitions() { | ||
| std::vector<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> allDefinitions; | ||
| for (const auto &provider : m_providers) { | ||
| const auto &definitions = provider.GetXmlnsDefinitions(); | ||
| allDefinitions.insert(allDefinitions.cend(), definitions.cbegin(), definitions.cend()); | ||
| } | ||
| return winrt::com_array<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition>( | ||
| allDefinitions.begin(), allDefinitions.end()); | ||
| } | ||
|
|
||
| winrt::Microsoft::ReactNative::Xaml::XamlApplication XamlApplication::s_current{nullptr}; | ||
| } // namespace winrt::Microsoft::ReactNative::Xaml::implementation | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #pragma once | ||
| #include "Xaml.XamlApplication.g.h" | ||
|
|
||
| #include <winrt/Microsoft.UI.Composition.h> | ||
| #include <winrt/Microsoft.UI.Dispatching.h> | ||
| #include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h> | ||
| #include <winrt/Microsoft.UI.Xaml.Controls.h> | ||
| #include <winrt/Microsoft.Windows.ApplicationModel.Resources.h> | ||
| #include <winrt/Windows.Foundation.h> | ||
|
|
||
| #include "winrt/Microsoft.UI.Xaml.Hosting.h" | ||
| #include "winrt/Microsoft.UI.Xaml.Interop.h" | ||
| #include "winrt/Microsoft.UI.Xaml.Markup.h" | ||
| #include "winrt/Microsoft.UI.Xaml.h" | ||
|
|
||
| #include "winrt/Windows.UI.Xaml.Interop.h" | ||
|
|
||
| #include "XamlMetaDataProvider.h" | ||
|
|
||
| namespace winrt::Microsoft::ReactNative::Xaml::implementation { | ||
| struct XamlApplication : XamlApplicationT<XamlApplication> { | ||
| XamlApplication(); | ||
| ~XamlApplication(); | ||
|
|
||
| static void EnsureCreated() { | ||
| if (Current() == nullptr) { | ||
| s_current = winrt::make<winrt::Microsoft::ReactNative::Xaml::implementation::XamlApplication>(); | ||
| } | ||
| } | ||
|
|
||
| static winrt::Microsoft::ReactNative::Xaml::XamlApplication Current() { | ||
| return s_current; | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| void AddMetadataProvider(winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider); | ||
| winrt::Microsoft::UI::Xaml::Markup::IXamlType GetXamlType(winrt::Windows::UI::Xaml::Interop::TypeName const &type); | ||
| winrt::Microsoft::UI::Xaml::Markup::IXamlType GetXamlType(hstring const &fullName); | ||
| com_array<winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions(); | ||
|
|
||
| private: | ||
| static winrt::Microsoft::ReactNative::Xaml::XamlApplication s_current; | ||
| std::vector<winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider> m_providers; | ||
| }; | ||
| } // namespace winrt::Microsoft::ReactNative::Xaml::implementation | ||
| namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation { | ||
| struct XamlApplication : XamlApplicationT<XamlApplication, implementation::XamlApplication> {}; | ||
| } // namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| #include "DocString.h" | ||
|
|
||
| namespace Microsoft.ReactNative.Xaml { | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| [webhosthidden][default_interface] runtimeclass XamlApplication : Microsoft.UI.Xaml.Application, | ||
| Microsoft.UI.Xaml.Markup.IXamlMetadataProvider { | ||
| DOC_STRING("Initializes a new XamlApplication instance for RNW-hosted WinUI/XAML.") | ||
| XamlApplication(); | ||
|
|
||
| DOC_STRING("Ensures the XamlApplication singleton exists.") | ||
| static void EnsureCreated(); | ||
|
|
||
| DOC_STRING("Gets the process-wide XamlApplication singleton.") | ||
| static XamlApplication Current { | ||
| get; | ||
| }; | ||
|
|
||
| DOC_STRING("Adds an additional XAML metadata provider to the application.") | ||
| void AddMetadataProvider(Microsoft.UI.Xaml.Markup.IXamlMetadataProvider otherProvider); | ||
| } | ||
| } // namespace Microsoft.ReactNative.Xaml | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
| #include "pch.h" | ||
|
|
||
| #include "XamlApplication.h" | ||
| #include "XamlHost.h" | ||
|
|
||
| #if defined(RNW_NEW_ARCH) | ||
|
|
||
| #include "..\codegen\react\components\rnwcore\XamlHost.g.h" | ||
|
|
||
| namespace winrt::Microsoft::ReactNative { | ||
|
|
||
| struct XamlHostComponentView : public winrt::implements<XamlHostComponentView, winrt::IInspectable>, | ||
| ::Microsoft::ReactNativeSpecs::BaseXamlHost<XamlHostComponentView> { | ||
| void InitializeContentIsland( | ||
| const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept { | ||
| winrt::Microsoft::ReactNative::Xaml::implementation::XamlApplication::EnsureCreated(); | ||
|
|
||
| m_xamlIsland = winrt::Microsoft::UI::Xaml::XamlIsland{}; | ||
|
|
||
| islandView.Connect(m_xamlIsland.ContentIsland()); | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| void MountChildComponentView( | ||
| const winrt::Microsoft::ReactNative::ComponentView & /*view*/, | ||
| const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept override { | ||
| // Add the xaml child to the m_xamlIsland here. | ||
| auto childXamlControl = args.Child().UserData().as<winrt::Microsoft::ReactNative::Xaml::IXamlControl>(); | ||
| if (childXamlControl) { | ||
| auto xamlElement = childXamlControl.GetXamlElement(); | ||
| m_xamlIsland.Content(xamlElement); | ||
| } | ||
| } | ||
|
|
||
| void UnmountChildComponentView( | ||
| const winrt::Microsoft::ReactNative::ComponentView & /*view*/, | ||
| const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &) noexcept override { | ||
| m_xamlIsland.Content(nullptr); | ||
| } | ||
|
|
||
| private: | ||
| winrt::Microsoft::UI::Xaml::XamlIsland m_xamlIsland{nullptr}; | ||
| }; | ||
|
|
||
| } // namespace winrt::Microsoft::ReactNative | ||
|
|
||
| void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { | ||
| ::Microsoft::ReactNativeSpecs::RegisterXamlHostNativeComponent<winrt::Microsoft::ReactNative::XamlHostComponentView>( | ||
| packageBuilder, | ||
| [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { | ||
| builder.SetContentIslandComponentViewInitializer( | ||
| [](const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept { | ||
| auto userData = winrt::make_self<winrt::Microsoft::ReactNative::XamlHostComponentView>(); | ||
| userData->InitializeContentIsland(islandView); | ||
| islandView.UserData(*userData); | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| #endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3) | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| #pragma once | ||
|
|
||
| #if defined(RNW_NEW_ARCH) | ||
|
|
||
| void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); | ||
|
|
||
| #endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3) | ||
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
sharath2727 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.