diff --git a/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json b/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json
new file mode 100644
index 00000000000..31db8d104ea
--- /dev/null
+++ b/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Introduce xamlhost component",
+ "packageName": "react-native-windows",
+ "email": "10109130+sharath2727@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/sample-app-fabric/windows/SampleAppFabric.sln b/packages/sample-app-fabric/windows/SampleAppFabric.sln
index 1eabd0cabef..66b1574ab2d 100644
--- a/packages/sample-app-fabric/windows/SampleAppFabric.sln
+++ b/packages/sample-app-fabric/windows/SampleAppFabric.sln
@@ -36,62 +36,50 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\..\..\vnext\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}"
EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9
- ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9
- ..\..\..\vnext\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9
- ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9
- ..\..\..\vnext\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9
- ..\..\..\vnext\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
- ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
- ..\..\..\vnext\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
- ..\..\..\vnext\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
- Debug|ARM64 = Debug|ARM64
+ Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
- Release|ARM64 = Release|ARM64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.Build.0 = Debug|ARM64
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.Deploy.0 = Debug|ARM64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x64.ActiveCfg = Debug|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x64.Build.0 = Debug|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x64.Deploy.0 = Debug|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x86.ActiveCfg = Debug|x86
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x86.Build.0 = Debug|x86
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|x86.Deploy.0 = Debug|x86
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.Build.0 = Debug|ARM64
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.ActiveCfg = Release|ARM64
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.Build.0 = Release|ARM64
+ {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.Deploy.0 = Release|ARM64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x64.ActiveCfg = Release|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x64.Build.0 = Release|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x64.Deploy.0 = Release|x64
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x86.ActiveCfg = Release|x86
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x86.Build.0 = Release|x86
{7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|x86.Deploy.0 = Release|x86
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.ActiveCfg = Release|ARM64
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.Build.0 = Release|ARM64
- {7E2B86E3-E6B0-409D-812E-0D81DFFACA9D}.Release|ARM64.Deploy.0 = Release|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.Deploy.0 = Debug|ARM64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x64.ActiveCfg = Debug|x64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x64.Build.0 = Debug|x64
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x64.Deploy.0 = Debug|x64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x86.ActiveCfg = Debug|Win32
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x86.Build.0 = Debug|Win32
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|x86.Deploy.0 = Debug|Win32
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.Build.0 = Debug|ARM64
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.Build.0 = Release|ARM64
+ {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.Deploy.0 = Release|ARM64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x64.ActiveCfg = Release|x64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x64.Build.0 = Release|x64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x64.Deploy.0 = Release|x64
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x86.ActiveCfg = Release|Win32
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x86.Build.0 = Release|Win32
{E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|x86.Deploy.0 = Release|Win32
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.ActiveCfg = Release|ARM64
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.Build.0 = Release|ARM64
- {E278ABE5-5A88-48C5-A949-CA00B489643F}.Release|ARM64.Deploy.0 = Release|ARM64
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64
@@ -104,6 +92,20 @@ Global
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.ActiveCfg = Debug|x64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.Build.0 = Debug|x64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.ActiveCfg = Debug|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Build.0 = Debug|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Deploy.0 = Debug|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.Build.0 = Release|ARM64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.ActiveCfg = Release|x64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.Build.0 = Release|x64
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.ActiveCfg = Release|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Build.0 = Release|Win32
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Deploy.0 = Release|Win32
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64
@@ -140,26 +142,13 @@ Global
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.Build.0 = Debug|ARM64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.ActiveCfg = Debug|x64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.Build.0 = Debug|x64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.ActiveCfg = Debug|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Build.0 = Debug|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Deploy.0 = Debug|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.ActiveCfg = Release|ARM64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.Build.0 = Release|ARM64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.ActiveCfg = Release|x64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.Build.0 = Release|x64
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.ActiveCfg = Release|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Build.0 = Release|Win32
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
+ {14B93DC8-FD93-4A6D-81CB-8BC96644501C} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
{C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
{F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
@@ -168,9 +157,19 @@ Global
{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
{EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
- {14B93DC8-FD93-4A6D-81CB-8BC96644501C} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9
+ ..\..\..\vnext\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9
+ ..\..\..\vnext\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9
+ ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9
+ ..\..\..\vnext\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9
+ ..\..\..\vnext\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
+ ..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
+ ..\..\..\vnext\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
+ ..\..\..\vnext\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
+ EndGlobalSection
EndGlobal
diff --git a/vnext/Microsoft.ReactNative/App.xaml b/vnext/Microsoft.ReactNative/App.xaml
new file mode 100644
index 00000000000..038e5a57397
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/App.xaml
@@ -0,0 +1,5 @@
+
+
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
index 6ce1074a63c..a54aae50a14 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
@@ -161,6 +161,13 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetFocus(void) {
return UiaSetFocusHelper(m_view);
}
+winrt::IUnknown CompositionDynamicAutomationProvider::TryGetChildSiteLinkAutomationProvider() {
+ if (m_childSiteLink) {
+ return m_childSiteLink.AutomationProvider().as();
+ }
+ return nullptr;
+}
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal) {
if (pRetVal == nullptr)
return E_POINTER;
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
index 7009a6e21b8..5049a52c4b3 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
@@ -98,6 +98,14 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
void AddToSelectionItems(winrt::com_ptr &item);
void RemoveFromSelectionItems(winrt::com_ptr &item);
+ void SetChildSiteLink(winrt::Microsoft::UI::Content::ChildSiteLink childSiteLink) {
+ m_childSiteLink = childSiteLink;
+ }
+
+ // If this object is for a ChildSiteLink, returns the ChildSiteLink's automation provider.
+ // This will be a provider object from the hosted framework (for example, WinUI).
+ winrt::IUnknown TryGetChildSiteLinkAutomationProvider();
+
private:
::Microsoft::ReactNative::ReactTaggedView m_view;
winrt::com_ptr m_textProvider;
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp
index 6ead642c857..e254eb4c367 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp
@@ -219,7 +219,8 @@ HRESULT __stdcall CompositionRootAutomationProvider::ElementProviderFromPoint(
auto local = rootView->ConvertScreenToLocal({static_cast(x), static_cast(y)});
auto provider = rootView->UiaProviderFromPoint(
{static_cast(local.X * rootView->LayoutMetrics().PointScaleFactor),
- static_cast(local.Y * rootView->LayoutMetrics().PointScaleFactor)});
+ static_cast(local.Y * rootView->LayoutMetrics().PointScaleFactor)},
+ {static_cast(x), static_cast(y)});
auto spFragment = provider.try_as();
if (spFragment) {
*pRetVal = spFragment.detach();
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp
index 57aa7d14656..1310d8e7b4c 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp
@@ -178,14 +178,12 @@ ContentIslandComponentView::~ContentIslandComponentView() noexcept {
void ContentIslandComponentView::MountChildComponentView(
const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
uint32_t index) noexcept {
- assert(false);
base_type::MountChildComponentView(childComponentView, index);
}
void ContentIslandComponentView::UnmountChildComponentView(
const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
uint32_t index) noexcept {
- assert(false);
base_type::UnmountChildComponentView(childComponentView, index);
}
@@ -212,6 +210,25 @@ void ContentIslandComponentView::prepareForRecycle() noexcept {
Super::prepareForRecycle();
}
+facebook::react::Tag ContentIslandComponentView::hitTest(
+ facebook::react::Point pt,
+ facebook::react::Point &localPt,
+ bool ignorePointerEvents) const noexcept {
+ facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
+
+ // This is similar to ViewComponentView::hitTest, but we don't want to hit test the children of this node,
+ // because the child ComponentView is kind of a dummy representation of the XamlElement and doesn't do anything.
+ // So, we just hit test the ContentIsland itself to make the UIA ElementProviderFromPoint call work.
+ // TODO: Will this cause a problem -- does this function need to do something different for non-UIA scenarios?
+ if (ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
+ ptLocal.y <= m_layoutMetrics.frame.size.height) {
+ localPt = ptLocal;
+ return Tag();
+ }
+
+ return -1;
+}
+
void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept {
// This automation mode must be set before connecting the child ContentIsland.
// It puts the child content into a mode where it won't own its own framework root. Instead, the child island's
@@ -262,6 +279,12 @@ void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept {
args.AutomationProvider(nullptr);
args.Handled(true);
});
+
+ if (m_uiaProvider) {
+ auto providerImpl =
+ m_uiaProvider.as();
+ providerImpl->SetChildSiteLink(m_childSiteLink);
+ }
}
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h
index f530baa3400..d9b374ffbfb 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h
@@ -51,6 +51,9 @@ struct ContentIslandComponentView : ContentIslandComponentViewT
#include
+#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(ptPixels.x) / m_layoutMetrics.pointScaleFactor,
static_cast(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(view)->EnsureUiaProvider();
+ auto uiaProvider =
+ winrt::get_self(view)->EnsureUiaProvider();
+
+ // TODO: Avoid exposing CompositionDynamicAutomationProvider in RootComponentView
+ auto dynamicProvider =
+ uiaProvider.try_as();
+ if (dynamicProvider) {
+ if (auto childProvider = dynamicProvider->TryGetChildSiteLinkAutomationProvider()) {
+ // ChildProvider is the the automation provider from the ChildSiteLink. In the case of WinUI, this
+ // is a pointer to WinUI's internal CUIAHostWindow object.
+ // It seems odd, but even though this node doesn't behave as a fragment root in our case (the real fragment root
+ // is the RootComponentView's UIA provider), we still use its IRawElementProviderFragmentRoot -- just so
+ // we can do the ElementProviderFromPoint call. (this was recommended by the team who did the initial
+ // architecture work).
+ if (auto fragmentRoot = childProvider.try_as()) {
+ com_ptr frag;
+ // WinUI then does its own hitTest inside the XAML tree.
+ fragmentRoot->ElementProviderFromPoint(
+ ptScreen
+ .x, // Note since we're going through IRawElementProviderFragment the coordinates are in screen space.
+ ptScreen.y,
+ frag.put());
+ // We return the specific child provider(frag) when hosted XAML has an element
+ // under the cursor. This satisfies the UIA "element at point" contract and exposes
+ // the control’s patterns/properties. If the hosted tree finds nothing, we fall back
+ // to the RNW container’s provider (uiaProvider) to keep the island accessible.
+ // (A Microsoft_UI_Xaml!CUIAWrapper object)
+ if (frag) {
+ return frag.as();
+ }
+ }
+ }
+ }
+
+ return uiaProvider;
}
float RootComponentView::FontSizeMultiplier() const noexcept {
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h
index 3a037fc6d61..83f633d212e 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h
@@ -64,7 +64,7 @@ struct RootComponentView : RootComponentViewT
true
false
+ true
diff --git a/vnext/Microsoft.ReactNative/XamlApplication.cpp b/vnext/Microsoft.ReactNative/XamlApplication.cpp
new file mode 100644
index 00000000000..74b0d0b3992
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/XamlApplication.cpp
@@ -0,0 +1,73 @@
+#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.
+ auto resourceManager =
+ winrt::Microsoft::Windows::ApplicationModel::Resources::ResourceManager(L"Microsoft.UI.Xaml.Controls.pri");
+
+ this->ResourceManagerRequested([resourceManager](auto &&, ResourceManagerRequestedEventArgs args) {
+ args.CustomResourceManager(resourceManager);
+ });
+ winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
+
+ m_providers.push_back(
+ winrt::make_self()
+ .as()); // 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 XamlApplication::GetXmlnsDefinitions() {
+ std::vector<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> allDefinitions;
+ for (const auto &provider : m_providers) {
+ auto definitionsCurrentProvider = provider.GetXmlnsDefinitions();
+ for (const auto &definition : definitionsCurrentProvider) {
+ allDefinitions.insert(allDefinitions.begin(), definition);
+ }
+ }
+ 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
diff --git a/vnext/Microsoft.ReactNative/XamlApplication.h b/vnext/Microsoft.ReactNative/XamlApplication.h
new file mode 100644
index 00000000000..cb3211ee0e0
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/XamlApplication.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "Xaml.XamlApplication.g.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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();
+
+ static void EnsureCreated() {
+ if (Current() == nullptr) {
+ s_current = winrt::make();
+ }
+ }
+
+ static winrt::Microsoft::ReactNative::Xaml::XamlApplication Current() {
+ return s_current;
+ }
+
+ 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 GetXmlnsDefinitions();
+
+ private:
+ static winrt::Microsoft::ReactNative::Xaml::XamlApplication s_current;
+ std::vector m_providers;
+};
+} // namespace winrt::Microsoft::ReactNative::Xaml::implementation
+namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation {
+struct XamlApplication : XamlApplicationT {};
+} // namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation
diff --git a/vnext/Microsoft.ReactNative/XamlApplication.idl b/vnext/Microsoft.ReactNative/XamlApplication.idl
new file mode 100644
index 00000000000..5a23009d917
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/XamlApplication.idl
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.ReactNative.Xaml {
+[webhosthidden][default_interface] runtimeclass XamlApplication : Microsoft.UI.Xaml.Application,
+ Microsoft.UI.Xaml.Markup.IXamlMetadataProvider {
+ XamlApplication();
+
+ static void EnsureCreated();
+
+ static XamlApplication Current {
+ get;
+ };
+
+ void AddMetadataProvider(Microsoft.UI.Xaml.Markup.IXamlMetadataProvider otherProvider);
+}
+} // namespace Microsoft.ReactNative.Xaml
diff --git a/vnext/Microsoft.ReactNative/XamlHost.cpp b/vnext/Microsoft.ReactNative/XamlHost.cpp
new file mode 100644
index 00000000000..5b6873b9bbf
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/XamlHost.cpp
@@ -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,
+ ::Microsoft::ReactNativeSpecs::BaseXamlHost {
+ 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());
+ }
+
+ 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();
+ 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(
+ packageBuilder,
+ [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) {
+ builder.SetContentIslandComponentViewInitializer(
+ [](const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept {
+ auto userData = winrt::make_self();
+ userData->InitializeContentIsland(islandView);
+ islandView.UserData(*userData);
+ });
+ });
+}
+
+#endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
diff --git a/vnext/Microsoft.ReactNative/XamlHost.h b/vnext/Microsoft.ReactNative/XamlHost.h
new file mode 100644
index 00000000000..7abc42b8241
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/XamlHost.h
@@ -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)
diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems
index 8fda1683eec..339abc0bd8a 100644
--- a/vnext/Shared/Shared.vcxitems
+++ b/vnext/Shared/Shared.vcxitems
@@ -245,6 +245,16 @@
true
$(ReactNativeWindowsDir)Microsoft.ReactNative\ReactNativeAppBuilder.idl
Code
+
+
+ true
+ $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl
+ Code
+
+
+ true
+ $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl
+ Code
@@ -350,6 +360,16 @@
true
$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\ReactNativeAppBuilder.idl
Code
+
+
+ true
+ $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl
+ Code
+
+
+ true
+ $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl
+ Code
$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\IJSValueReader.idl
@@ -711,6 +731,8 @@
+
+
@@ -726,4 +748,7 @@
NotUsing
+
+
+
diff --git a/vnext/fmt/packages.lock.json b/vnext/fmt/packages.lock.json
new file mode 100644
index 00000000000..a31237b580e
--- /dev/null
+++ b/vnext/fmt/packages.lock.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "dependencies": {
+ "native,Version=v0.0": {},
+ "native,Version=v0.0/win10-arm": {},
+ "native,Version=v0.0/win10-arm-aot": {},
+ "native,Version=v0.0/win10-arm64-aot": {},
+ "native,Version=v0.0/win10-x64": {},
+ "native,Version=v0.0/win10-x64-aot": {},
+ "native,Version=v0.0/win10-x86": {},
+ "native,Version=v0.0/win10-x86-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts b/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts
new file mode 100644
index 00000000000..a69cfafe0be
--- /dev/null
+++ b/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts
@@ -0,0 +1,13 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ * @format
+ * @flow
+ */
+///
+import type {ViewProps} from 'react-native';
+export interface XamlHostProps extends ViewProps {
+ label: string;
+}
+declare const _default: import('react-native/Libraries/Utilities/codegenNativeComponent').NativeComponentType;
+export default _default;
diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js
new file mode 100644
index 00000000000..723810b17a4
--- /dev/null
+++ b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js
@@ -0,0 +1,7 @@
+/**
+ * @format
+ * @flow
+ */
+
+import XamlHost from '../../../src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent';
+export default XamlHost;
diff --git a/vnext/src-win/index.windows.js b/vnext/src-win/index.windows.js
index 14ac2344540..8f368fe05fe 100644
--- a/vnext/src-win/index.windows.js
+++ b/vnext/src-win/index.windows.js
@@ -372,6 +372,9 @@ module.exports = {
get AppTheme() {
return require('./Libraries/AppTheme/AppTheme').AppTheme;
},
+ get XamlHost() {
+ return require('./Libraries/Components/Xaml/XamlHost').default;
+ },
} as ReactNativePublicAPI;
if (__DEV__) {
diff --git a/vnext/src-win/index.windows.js.flow b/vnext/src-win/index.windows.js.flow
index 6942181c0c3..d601455ba73 100644
--- a/vnext/src-win/index.windows.js.flow
+++ b/vnext/src-win/index.windows.js.flow
@@ -469,6 +469,7 @@ export {HandledEventPhase } from './Libraries/Components/View/ViewPropTypes'
export {default as ViewWindows} from './Libraries/Components/View/View';
export {AppTheme} from './Libraries/AppTheme/AppTheme';
+export {default as XamlHost} from './Libraries/Components/Xaml/XamlHost';
// End Windows Specific exports
// #endregion
diff --git a/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js b/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js
new file mode 100644
index 00000000000..4b0fc158fd8
--- /dev/null
+++ b/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ * @format
+ * @flow
+ */
+
+'use strict';
+
+import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
+import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
+import type {HostComponent} from '../../../../../src/private/types/HostComponent';
+
+type XamlHostProps = $ReadOnly<{|
+ ...ViewProps,
+|}>;
+
+type NativeType = HostComponent;
+
+export default (codegenNativeComponent('XamlHost'): NativeType);