Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
28b1471
initial workspace launching sample app fabric without xaml
sharath2727 Oct 8, 2025
7cb5b7e
XamlHost Definition, declaration and Codegen components
sharath2727 Oct 8, 2025
ffa1c03
Introduce XamlApplication that enables to host xaml ui
sharath2727 Oct 8, 2025
b7cbe82
Introduce xamlhost component
sharath2727 Oct 9, 2025
ed1e67c
Register XamlHostComponentView
sharath2727 Oct 9, 2025
0a95df7
Using XamlHost in Sample App and hardcoding button in xamlisland
sharath2727 Oct 9, 2025
6861056
Accessibility Validated on hardcoded xaml control
sharath2727 Oct 9, 2025
b3d5b4f
Cleaned up
sharath2727 Nov 4, 2025
c90b1da
Change files
sharath2727 Nov 4, 2025
9357561
yarn format
sharath2727 Nov 4, 2025
805ba4d
yarn lint fix
sharath2727 Nov 4, 2025
46dc340
Merge branch 'main' into user/sharath227/xamlislandprototypework
sharath2727 Nov 4, 2025
9889e8c
Microsoft.ReactNative.Xaml namespace and lint fixes
sharath2727 Nov 5, 2025
284c423
Merge branch 'main' into user/sharath227/xamlislandprototypework
sharath2727 Nov 5, 2025
522cf31
rework index.windows.js and js.flow
sharath2727 Nov 5, 2025
529423b
Introduce IXamlProvider
sharath2727 Nov 6, 2025
9b6aa17
Yarn issue
sharath2727 Nov 6, 2025
b9036c3
Avoid compiling xaml for office solution
sharath2727 Nov 7, 2025
11c54ea
yarn format fix
sharath2727 Nov 7, 2025
6b92ff5
Merge branch 'main' into user/sharath227/xamlislandprototypework
sharath2727 Nov 7, 2025
b179f47
Update shared vcxitems filter
sharath2727 Nov 7, 2025
713b950
Merge branch 'main' into user/sharath227/xamlislandprototypework
sharath2727 Nov 10, 2025
c2aa6d4
Fix overrides
sharath2727 Nov 10, 2025
572a024
Fixed formatting errors
sharath2727 Nov 10, 2025
8392fc5
fix winrt document generation error
sharath2727 Nov 10, 2025
9aa90f6
Handle winrt document generation failure gracefully
sharath2727 Nov 10, 2025
b477234
Optimize GetXmlnsDefinitions Implementation
sharath2727 Nov 11, 2025
c298c47
Merge branch 'main' into user/sharath227/xamlislandprototypework
sharath2727 Nov 11, 2025
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
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Introduce xamlhost component",
"packageName": "react-native-windows",
"email": "[email protected]",
"dependentChangeType": "patch"
}
81 changes: 40 additions & 41 deletions packages/sample-app-fabric/windows/SampleAppFabric.sln
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these changes for? Please drop them if unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this got auto-generated.

Copy link
Contributor

@sundaramramaswamy sundaramramaswamy Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it's unneeded i.e. your changes will build with no changes to the solution file too, then by include it? Please unstage and drop this file from the PR. It'd be noise otherwise. If these changes are needed for your PR to work, then we need to understand what changed in this file.

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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}
Expand All @@ -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
6 changes: 6 additions & 0 deletions vnext/Microsoft.ReactNative/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Application
x:Class="Microsoft.ReactNative.XamlApplication"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.ReactNative">
</Application>
Original file line number Diff line number Diff line change
Expand Up @@ -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<winrt::IUnknown>();
}
return nullptr;
}

HRESULT __stdcall CompositionDynamicAutomationProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal) {
if (pRetVal == nullptr)
return E_POINTER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
void AddToSelectionItems(winrt::com_ptr<IRawElementProviderSimple> &item);
void RemoveFromSelectionItems(winrt::com_ptr<IRawElementProviderSimple> &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<ITextProvider2> m_textProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ HRESULT __stdcall CompositionRootAutomationProvider::ElementProviderFromPoint(
auto local = rootView->ConvertScreenToLocal({static_cast<float>(x), static_cast<float>(y)});
auto provider = rootView->UiaProviderFromPoint(
{static_cast<LONG>(local.X * rootView->LayoutMetrics().PointScaleFactor),
static_cast<LONG>(local.Y * rootView->LayoutMetrics().PointScaleFactor)});
static_cast<LONG>(local.Y * rootView->LayoutMetrics().PointScaleFactor)},
{static_cast<LONG>(x), static_cast<LONG>(y)});
auto spFragment = provider.try_as<IRawElementProviderFragment>();
if (spFragment) {
*pRetVal = spFragment.detach();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious of Andrew's thoughts on the best way to handle ContentIslandComponentView::hitTest

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this override? What kinds of components are you putting in the ContentIslandComponentView? I'd expect that the components you'd be putting in the XamlHost view would be Xaml components. And those should not inherit from ViewComponent, so they would be ignored by the default hit test, no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We added this to make the UIA "ElementProviderFromPoint" hit test work correctly. When the RootComponentView gets a ElementProviderFromPoint call (UiaProviderFromPoint), it runs a hit test. With this change, we've made the logic so that if the RN hittest hits an island, we make a second call to UIA ElementProviderFromPoint on that ContentIsland. This is how we hit the content inside the island.

My concern here was that I don't know if hittest is used for other things, and if that could cause trouble.

Copy link
Contributor

@acoates-ms acoates-ms Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that, but this function should be doing the same thing as the base does?

With the exception that this implementation is not correctly handling the pointerEvents property.

The base implementation of this function in ViewComponentView::hitTest should already do the same as this function, no?

And then I'd expect the Xaml elements that are children of the ContentIslandComponentView to not be ViewComponentView's, and so they'd use the base of ComponentView::hitTest, which would ensure that they do not hitTest by default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so maybe the problem is that the Xaml element children are deriving from ViewComponentViews (or some other type) and they shouldn't be. I haven't worked with this code for a while, so I'm just going off what I see in the comments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if the Xaml element was deriving from ViewComponentViews that would be wrong, and would require this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let remove this change, and ensure that the Xaml elements are not deriving from ViewComponentViews.
We dont have an example of an actual XamlElement in this PR, correct?

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
Expand Down Expand Up @@ -262,6 +279,12 @@ void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept {
args.AutomationProvider(nullptr);
args.Handled(true);
});

if (m_uiaProvider) {
auto providerImpl =
m_uiaProvider.as<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>();
providerImpl->SetChildSiteLink(m_childSiteLink);
}
}

} // namespace winrt::Microsoft::ReactNative::Composition::implementation
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
ReactCompositionViewComponentBuilder *builder);
~ContentIslandComponentView() noexcept;

virtual facebook::react::Tag
hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents) const noexcept override;

private:
void OnMounted() noexcept;
void OnUnmounted() noexcept;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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};
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, please add the task to the comment too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto dynamicProvider =
uiaProvider.try_as<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>();
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<IRawElementProviderFragmentRoot>()) {
com_ptr<IRawElementProviderFragment> 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<winrt::IUnknown>();
}
}
}
}

return uiaProvider;
}

float RootComponentView::FontSizeMultiplier() const noexcept {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
facebook::react::LayoutMetrics const &layoutMetrics,
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;

winrt::Windows::Foundation::IInspectable UiaProviderFromPoint(const POINT &ptPixels) noexcept;
winrt::Windows::Foundation::IUnknown UiaProviderFromPoint(const POINT &ptPixels, const POINT &ptScreen) noexcept;

RootComponentView(
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
Expand Down
8 changes: 8 additions & 0 deletions vnext/Microsoft.ReactNative/IReactPackageProvider.idl
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,12 @@ namespace Microsoft.ReactNative
void CreatePackage(IReactPackageBuilder packageBuilder);
};

[webhosthidden]
interface IXamlControl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this into a Microsoft.ReactNative.Xaml namespace? I'd like the try to keep any Xaml specific stuff out of core to ensure we have nice layering.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

{
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
Loading
Loading