diff --git a/change/@react-native-windows-codegen-fc9a80b3-b16a-458c-b6e9-230a3d4f14f2.json b/change/@react-native-windows-codegen-fc9a80b3-b16a-458c-b6e9-230a3d4f14f2.json new file mode 100644 index 00000000000..a9cde0171dd --- /dev/null +++ b/change/@react-native-windows-codegen-fc9a80b3-b16a-458c-b6e9-230a3d4f14f2.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Add ability to override UpdateLayoutMetrics and VisualToMountChildrenInto", + "packageName": "@react-native-windows/codegen", + "email": "30809111+acoates-ms@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/change/react-native-windows-2e9f4c25-c40a-4434-9c2c-0d6672969f47.json b/change/react-native-windows-2e9f4c25-c40a-4434-9c2c-0d6672969f47.json new file mode 100644 index 00000000000..a5ff2420272 --- /dev/null +++ b/change/react-native-windows-2e9f4c25-c40a-4434-9c2c-0d6672969f47.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Add ability to override UpdateLayoutMetrics and VisualToMountChildrenInto", + "packageName": "react-native-windows", + "email": "30809111+acoates-ms@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts b/packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts index 956125944cb..60e750a4fb8 100644 --- a/packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts +++ b/packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts @@ -29,6 +29,7 @@ type FilesOutput = Map; const headerTemplate = `/* * This file is auto-generated from ::_COMPONENT_NAME_::NativeComponent spec file in flow / TypeScript. */ +// clang-format off #pragma once #include @@ -99,6 +100,13 @@ struct Base::_COMPONENT_NAME_:: { m_props = newProps; } + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + // UpdateState will only be called if this method is overridden virtual void UpdateState( const winrt::Microsoft::ReactNative::ComponentView &/*view*/, @@ -167,6 +175,13 @@ void Register::_COMPONENT_NAME_::NativeComponent( userData->UpdateProps(view, newProps ? newProps.as<::_COMPONENT_NAME_::Props>() : nullptr, oldProps ? oldProps.as<::_COMPONENT_NAME_::Props>() : nullptr); }); + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { auto userData = view.UserData().as(); diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/DrawingIsland.g.h b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/DrawingIsland.g.h index 45ec6c970b6..abda2cdd76a 100644 --- a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/DrawingIsland.g.h +++ b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/DrawingIsland.g.h @@ -2,6 +2,7 @@ /* * This file is auto-generated from DrawingIslandNativeComponent spec file in flow / TypeScript. */ +// clang-format off #pragma once #include @@ -53,6 +54,13 @@ struct BaseDrawingIsland { m_props = newProps; } + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + // UpdateState will only be called if this method is overridden virtual void UpdateState( const winrt::Microsoft::ReactNative::ComponentView &/*view*/, @@ -117,6 +125,13 @@ void RegisterDrawingIslandNativeComponent( userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); }); + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { auto userData = view.UserData().as(); diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/MovingLight.g.h b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/MovingLight.g.h index 940b2d5476b..d71058de9a0 100644 --- a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/MovingLight.g.h +++ b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/MovingLight.g.h @@ -2,6 +2,7 @@ /* * This file is auto-generated from MovingLightNativeComponent spec file in flow / TypeScript. */ +// clang-format off #pragma once #include @@ -94,6 +95,13 @@ struct BaseMovingLight { m_props = newProps; } + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + // UpdateState will only be called if this method is overridden virtual void UpdateState( const winrt::Microsoft::ReactNative::ComponentView &/*view*/, @@ -170,6 +178,13 @@ void RegisterMovingLightNativeComponent( userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); }); + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { auto userData = view.UserData().as(); diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp index d5ee055cb54..c7cad679f72 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp @@ -22,11 +22,12 @@ struct RootComponentView; namespace winrt::Microsoft::ReactNative::implementation { -ComponentView::ComponentView(facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext) - : m_tag(tag), m_reactContext(reactContext) {} - -void ComponentView::MarkAsCustomComponent() noexcept { - m_customComponent = true; +ComponentView::ComponentView( + facebook::react::Tag tag, + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder) + : m_tag(tag), m_reactContext(reactContext) { + m_builder.copy_from(builder); } std::vector @@ -52,18 +53,15 @@ void ComponentView::MountChildComponentView( uint32_t index) noexcept { m_children.InsertAt(index, childComponentView); winrt::get_self(childComponentView)->parent(*this); - if (m_mountChildComponentViewHandler) { - m_mountChildComponentViewHandler(*this, winrt::make(childComponentView, index)); + if (m_builder && m_builder->MountChildComponentViewHandler()) { + m_builder->MountChildComponentViewHandler()( + *this, winrt::make(childComponentView, index)); } if (m_mounted) { winrt::get_self(childComponentView)->onMounted(); } } -void ComponentView::MountChildComponentViewHandler(const MountChildComponentViewDelegate &handler) noexcept { - m_mountChildComponentViewHandler = handler; -} - void ComponentView::onMounted() noexcept { assert(!m_mounted); m_mounted = true; @@ -89,16 +87,14 @@ void ComponentView::Mounted(winrt::event_token const &token) noexcept { void ComponentView::UnmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - if (m_mountChildComponentViewHandler) { - m_mountChildComponentViewHandler(*this, winrt::make(childComponentView, index)); + if (m_builder && m_builder->UnmountChildComponentViewHandler()) { + m_builder->UnmountChildComponentViewHandler()( + *this, winrt::make(childComponentView, index)); } m_children.RemoveAt(index); winrt::get_self(childComponentView)->parent(nullptr); winrt::get_self(childComponentView)->onUnmounted(); } -void ComponentView::UnmountChildComponentViewHandler(const UnmountChildComponentViewDelegate &handler) noexcept { - m_unmountChildComponentViewHandler = handler; -} void ComponentView::onUnmounted() noexcept { if (!m_mounted) @@ -148,15 +144,11 @@ uint32_t UnmountChildComponentViewArgs::Index() const noexcept { void ComponentView::updateProps( facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept { - if (m_updatePropsDelegate) { - m_updatePropsDelegate(*this, userProps(props), oldProps ? userProps(oldProps) : nullptr); + if (m_builder && m_builder->UpdatePropsHandler()) { + m_builder->UpdatePropsHandler()(*this, userProps(props), oldProps ? userProps(oldProps) : nullptr); } } -void ComponentView::UpdatePropsHandler(const UpdatePropsDelegate &handler) noexcept { - m_updatePropsDelegate = handler; -} - const winrt::Microsoft::ReactNative::IComponentProps ComponentView::userProps( facebook::react::Props::Shared const &props) noexcept { const auto &abiProps = @@ -165,28 +157,20 @@ const winrt::Microsoft::ReactNative::IComponentProps ComponentView::userProps( } void ComponentView::updateEventEmitter(facebook::react::EventEmitter::Shared const &eventEmitter) noexcept { - if (m_updateEventEmitterHandler) { - m_updateEventEmitterHandler(*this, winrt::make(eventEmitter)); + if (m_builder && m_builder->UpdateEventEmitterHandler()) { + m_builder->UpdateEventEmitterHandler()(*this, winrt::make(eventEmitter)); } } -void ComponentView::UpdateEventEmitterHandler(const UpdateEventEmitterDelegate &handler) noexcept { - m_updateEventEmitterHandler = handler; -} - void ComponentView::updateState( facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept { // Avoid new-ing up a new AbiComponentState on every state change if we are not a custom component - if (m_updateStateDelegate) { - m_updateStateDelegate(*this, winrt::make<::Microsoft::ReactNative::AbiComponentState>(state)); + if (m_builder && m_builder->UpdateStateHandler()) { + m_builder->UpdateStateHandler()(*this, winrt::make<::Microsoft::ReactNative::AbiComponentState>(state)); } } -void ComponentView::UpdateStateHandler(const UpdateStateDelegate &handler) noexcept { - m_updateStateDelegate = handler; -} - LayoutMetricsChangedArgs::LayoutMetricsChangedArgs( const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) @@ -216,6 +200,10 @@ void ComponentView::updateLayoutMetrics( layoutMetrics.frame.size.height}, layoutMetrics.pointScaleFactor}; + if (m_builder && m_builder->UpdateLayoutMetricsHandler()) { + m_builder->UpdateLayoutMetricsHandler()(*this, newMetrics, oldMetrics); + } + m_layoutMetrics = layoutMetrics; m_layoutMetricsChangedEvent(*this, winrt::make(newMetrics, oldMetrics)); @@ -240,13 +228,9 @@ void ComponentView::LayoutMetricsChanged(winrt::event_token const &token) noexce m_layoutMetricsChangedEvent.remove(token); } -void ComponentView::FinalizeUpdateHandler(const UpdateFinalizerDelegate &handler) noexcept { - m_finalizeUpdateHandler = handler; -} - void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept { - if (m_finalizeUpdateHandler) { - m_finalizeUpdateHandler(*this, updateMask); + if (m_builder && m_builder->FinalizeUpdateHandler()) { + m_builder->FinalizeUpdateHandler()(*this, updateMask); } } @@ -257,13 +241,9 @@ facebook::react::Props::Shared ComponentView::props() noexcept { return {}; } -void ComponentView::CustomCommandHandler(const HandleCommandDelegate &handler) noexcept { - m_customCommandHandler = handler; -} - void ComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept { - if (m_customCommandHandler) { - m_customCommandHandler(*this, args); + if (m_builder && m_builder->CustomCommandHandler()) { + m_builder->CustomCommandHandler()(*this, args); } } diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h index 7caabb9000e..45f22c34c1d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -80,7 +81,10 @@ struct UnmountChildComponentViewArgs : public UnmountChildComponentViewArgsT { - ComponentView(facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext); + ComponentView( + facebook::react::Tag tag, + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder); virtual std::vector supplementalComponentDescriptorProviders() noexcept; virtual void updateProps( @@ -115,7 +119,6 @@ struct ComponentView virtual void onGettingFocus(const winrt::Microsoft::ReactNative::GettingFocusEventArgs &args) noexcept; virtual void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept; virtual void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept; - void MarkAsCustomComponent() noexcept; virtual void onMounted() noexcept; bool isMounted() noexcept; virtual void onUnmounted() noexcept; @@ -223,14 +226,6 @@ struct ComponentView void UserData(const winrt::IInspectable &userData) noexcept; winrt::IInspectable UserData() const noexcept; - void CustomCommandHandler(const HandleCommandDelegate &handler) noexcept; - void UpdatePropsHandler(const UpdatePropsDelegate &handler) noexcept; - void UpdateStateHandler(const UpdateStateDelegate &handler) noexcept; - void UpdateEventEmitterHandler(const UpdateEventEmitterDelegate &handler) noexcept; - void MountChildComponentViewHandler(const MountChildComponentViewDelegate &handler) noexcept; - void UnmountChildComponentViewHandler(const UnmountChildComponentViewDelegate &handler) noexcept; - void FinalizeUpdateHandler(const UpdateFinalizerDelegate &handler) noexcept; - virtual void MountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept; @@ -258,7 +253,7 @@ struct ComponentView const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept; protected: - bool m_customComponent : 1 {false}; // Is a user custom component, and so needs to call external override functions + winrt::com_ptr m_builder; bool m_mounted : 1 {false}; const facebook::react::Tag m_tag; winrt::IInspectable m_userData; @@ -270,14 +265,6 @@ struct ComponentView winrt::Windows::Foundation::Collections::IVector m_children{ winrt::single_threaded_vector()}; - UpdatePropsDelegate m_updatePropsDelegate{nullptr}; - UpdateStateDelegate m_updateStateDelegate{nullptr}; - HandleCommandDelegate m_customCommandHandler{nullptr}; - UpdateFinalizerDelegate m_finalizeUpdateHandler{nullptr}; - MountChildComponentViewDelegate m_mountChildComponentViewHandler{nullptr}; - UnmountChildComponentViewDelegate m_unmountChildComponentViewHandler{nullptr}; - UpdateEventEmitterDelegate m_updateEventEmitterHandler{nullptr}; - winrt::event< winrt::Windows::Foundation::EventHandler> m_keyDownEvent; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index a8468fd2f14..ee8fca97d80 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -53,8 +53,9 @@ ComponentView::ComponentView( const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext, - ComponentViewFeatures flags) - : base_type(tag, reactContext), m_compContext(compContext), m_flags(flags) { + ComponentViewFeatures flags, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder) + : base_type(tag, reactContext, builder), m_compContext(compContext), m_flags(flags) { m_outerVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a // CreateContainerVisual in ICompositionContext } @@ -933,24 +934,15 @@ ViewComponentView::ViewComponentView( const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext, - ComponentViewFeatures flags) - : base_type(compContext, tag, reactContext, flags), + ComponentViewFeatures flags, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder) + : base_type(compContext, tag, reactContext, flags, builder), m_props(defaultProps ? defaultProps : ViewComponentView::defaultProps()) {} winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ViewComponentView::createVisual() noexcept { return m_compContext.CreateSpriteVisual(); } -void ViewComponentView::CreateVisualHandler( - const winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate &handler) { - m_createVisualHandler = handler; -} - -winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate ViewComponentView::CreateVisualHandler() - const noexcept { - return m_createVisualHandler; -} - void ViewComponentView::CreateInternalVisualHandler( const winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate &handler) { m_createInternalVisualHandler = handler; @@ -965,10 +957,10 @@ void ViewComponentView::ensureVisual() noexcept { if (!m_visual) { if (m_createInternalVisualHandler) { m_visual = m_createInternalVisualHandler(*this); - } else if (m_createVisualHandler) { + } else if (m_builder && m_builder->CreateVisualHandler()) { m_visual = winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::CreateVisual( - m_createVisualHandler(*this)); + m_builder->CreateVisualHandler()(*this)); } else { m_visual = createVisual(); } @@ -986,6 +978,8 @@ winrt::Microsoft::ReactNative::ComponentView ViewComponentView::Create( winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ViewComponentView::VisualToMountChildrenInto() noexcept { + if (m_builder && m_builder->VisualToMountChildrenIntoHandler()) + return m_builder->VisualToMountChildrenIntoHandler()(*this); return Visual(); } @@ -1233,7 +1227,7 @@ winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewProps() noexcept winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewPropsInner() noexcept { // If we have AbiViewProps, then we dont need to new up a props wrapper - if (m_customComponent) { + if (m_builder) { const auto &abiViewProps = *std::static_pointer_cast(m_props); return abiViewProps.ViewProps(); } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h index 29f1412878d..ee7c13e9a67 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h @@ -35,7 +35,8 @@ struct ComponentView : public ComponentViewT< const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext, - ComponentViewFeatures flags); + ComponentViewFeatures flags, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder); virtual ~ComponentView(); virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept { @@ -208,7 +209,8 @@ struct ViewComponentView : public ViewComponentViewT< const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext, - ComponentViewFeatures flags); + ComponentViewFeatures flags, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder = nullptr); virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept; @@ -226,7 +228,6 @@ struct ViewComponentView : public ViewComponentViewT< bool m_hasNonVisualChildren{false}; facebook::react::SharedViewProps m_props; winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_visual{nullptr}; - winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate m_createVisualHandler{nullptr}; winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate m_createInternalVisualHandler{ nullptr}; }; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp index 84b10002bd8..70f73d834fa 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp @@ -22,8 +22,15 @@ namespace winrt::Microsoft::ReactNative::Composition::implementation { ContentIslandComponentView::ContentIslandComponentView( const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) - : base_type(ViewComponentView::defaultProps(), compContext, tag, reactContext, ComponentViewFeatures::Default) { + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + ReactCompositionViewComponentBuilder *builder) + : base_type( + ViewComponentView::defaultProps(), + compContext, + tag, + reactContext, + ComponentViewFeatures::Default, + builder) { m_mountedToken = Mounted([](const winrt::IInspectable &, const winrt::Microsoft::ReactNative::ComponentView &view) { view.as()->OnMounted(); }); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h index 3dc0259a3f2..ae252c9bb61 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h @@ -40,7 +40,8 @@ struct ContentIslandComponentView : ContentIslandComponentViewT #include #include +#include "CompositionContextHelper.h" #include "DynamicWriter.h" #include "ReactHost/MsoUtils.h" @@ -52,24 +53,6 @@ LayoutHandler ReactCompositionViewComponentBuilder::LayoutHandler() const noexce void ReactCompositionViewComponentBuilder::InitializeComponentView( const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { auto self = winrt::get_self(view); - self->MarkAsCustomComponent(); - if (m_customCommandHandler) - self->CustomCommandHandler(m_customCommandHandler); - if (m_finalizeUpdateHandler) - self->FinalizeUpdateHandler(m_finalizeUpdateHandler); - if (m_updatePropsHandler) - self->UpdatePropsHandler(m_updatePropsHandler); - if (m_updateStateHandler) - self->UpdateStateHandler(m_updateStateHandler); - if (m_updateEventEmitterHandler) - self->UpdateEventEmitterHandler(m_updateEventEmitterHandler); - if (m_mountChildComponentViewHandler) - self->MountChildComponentViewHandler(m_mountChildComponentViewHandler); - if (m_unmountChildComponentViewHandler) - self->UnmountChildComponentViewHandler(m_unmountChildComponentViewHandler); - if (m_createVisualHandler) - view.as()->CreateVisualHandler( - m_createVisualHandler); } void ReactCompositionViewComponentBuilder::SetComponentViewInitializer( @@ -78,8 +61,9 @@ void ReactCompositionViewComponentBuilder::SetComponentViewInitializer( const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context, - ComponentViewFeatures) { - auto view = winrt::make(tag, reactContext); + ComponentViewFeatures, + ReactCompositionViewComponentBuilder &builder) { + auto view = winrt::make(tag, reactContext, &builder); initializer(view); return view; }; @@ -94,9 +78,10 @@ void ReactCompositionViewComponentBuilder::SetViewComponentViewInitializer( const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context, - ComponentViewFeatures features) { + ComponentViewFeatures features, + ReactCompositionViewComponentBuilder &builder) { auto view = winrt::make( - implementation::ViewComponentView::defaultProps(), context, tag, reactContext, features); + implementation::ViewComponentView::defaultProps(), context, tag, reactContext, features, &builder); initializer(view); return view; }; @@ -108,14 +93,15 @@ void ReactCompositionViewComponentBuilder::SetViewComponentViewInitializer( void ReactCompositionViewComponentBuilder::SetContentIslandComponentViewInitializer( const ComponentIslandComponentViewInitializer &initializer) noexcept { - m_fnCreateView = - [initializer]( - const IReactContext &reactContext, - int32_t tag, - const Experimental::ICompositionContext &context, - ComponentViewFeatures) -> winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView { + m_fnCreateView = [initializer]( + const IReactContext &reactContext, + int32_t tag, + const Experimental::ICompositionContext &context, + ComponentViewFeatures /*features*/, + ReactCompositionViewComponentBuilder &builder) + -> winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView { auto view = winrt::make( - context, tag, reactContext); + context, tag, reactContext, &builder); initializer(view); return view; }; @@ -166,46 +152,108 @@ void ReactCompositionViewComponentBuilder::SetCustomCommandHandler(HandleCommand m_customCommandHandler = impl; } +const HandleCommandDelegate &ReactCompositionViewComponentBuilder::CustomCommandHandler() const noexcept { + return m_customCommandHandler; +} + void ReactCompositionViewComponentBuilder::SetFinalizeUpdateHandler(UpdateFinalizerDelegate impl) noexcept { m_finalizeUpdateHandler = impl; } +const UpdateFinalizerDelegate &ReactCompositionViewComponentBuilder::FinalizeUpdateHandler() const noexcept { + return m_finalizeUpdateHandler; +} + void ReactCompositionViewComponentBuilder::SetUpdatePropsHandler(UpdatePropsDelegate impl) noexcept { m_updatePropsHandler = impl; } +const winrt::Microsoft::ReactNative::UpdatePropsDelegate &ReactCompositionViewComponentBuilder::UpdatePropsHandler() + const noexcept { + return m_updatePropsHandler; +} + void ReactCompositionViewComponentBuilder::SetUpdateStateHandler(UpdateStateDelegate impl) noexcept { m_updateStateHandler = impl; } +const winrt::Microsoft::ReactNative::UpdateStateDelegate &ReactCompositionViewComponentBuilder::UpdateStateHandler() + const noexcept { + return m_updateStateHandler; +} + void ReactCompositionViewComponentBuilder::SetUpdateEventEmitterHandler(UpdateEventEmitterDelegate impl) noexcept { m_updateEventEmitterHandler = impl; } +const UpdateEventEmitterDelegate &ReactCompositionViewComponentBuilder::UpdateEventEmitterHandler() const noexcept { + return m_updateEventEmitterHandler; +} + void ReactCompositionViewComponentBuilder::SetMountChildComponentViewHandler( MountChildComponentViewDelegate impl) noexcept { m_mountChildComponentViewHandler = impl; } +const MountChildComponentViewDelegate &ReactCompositionViewComponentBuilder::MountChildComponentViewHandler() + const noexcept { + return m_mountChildComponentViewHandler; +} + void ReactCompositionViewComponentBuilder::SetUnmountChildComponentViewHandler( UnmountChildComponentViewDelegate impl) noexcept { m_unmountChildComponentViewHandler = impl; } +const UnmountChildComponentViewDelegate &ReactCompositionViewComponentBuilder::UnmountChildComponentViewHandler() + const noexcept { + return m_unmountChildComponentViewHandler; +} + void ReactCompositionViewComponentBuilder::SetCreateVisualHandler(CreateVisualDelegate impl) noexcept { m_createVisualHandler = impl; } +const CreateVisualDelegate &ReactCompositionViewComponentBuilder::CreateVisualHandler() const noexcept { + return m_createVisualHandler; +} + void ReactCompositionViewComponentBuilder::SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept { m_features = viewFeatures; } +void ReactCompositionViewComponentBuilder::SetVisualToMountChildrenIntoHandler( + VisualToMountChildrenIntoDelegate impl) noexcept { + m_visualToMountChildrenIntoHandler = [impl](const winrt::Microsoft::ReactNative::ComponentView &view) { + return winrt::Microsoft::ReactNative::Composition::Experimental::implementation::MicrosoftCompositionContextHelper:: + CreateVisual(impl(view)); + }; +} + +void ReactCompositionViewComponentBuilder::SetIVisualToMountChildrenIntoHandler( + winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate impl) noexcept { + m_visualToMountChildrenIntoHandler = impl; +} + +const winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate & +ReactCompositionViewComponentBuilder::VisualToMountChildrenIntoHandler() const noexcept { + return m_visualToMountChildrenIntoHandler; +} + +void ReactCompositionViewComponentBuilder::SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl) noexcept { + m_updateLayoutMetricsHandler = impl; +} + +const UpdateLayoutMetricsDelegate &ReactCompositionViewComponentBuilder::UpdateLayoutMetricsHandler() const noexcept { + return m_updateLayoutMetricsHandler; +} + winrt::Microsoft::ReactNative::ComponentView ReactCompositionViewComponentBuilder::CreateView( const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context) noexcept { assert(m_fnCreateView); - auto view = m_fnCreateView(reactContext, tag, context, m_features); + auto view = m_fnCreateView(reactContext, tag, context, m_features, *this); InitializeComponentView(view); return view; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h index 220884bd6c6..618aae06e5d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h @@ -44,6 +44,10 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< void SetContentIslandComponentViewInitializer(const ComponentIslandComponentViewInitializer &initializer) noexcept; void SetCreateVisualHandler(CreateVisualDelegate impl) noexcept; void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept; + void SetVisualToMountChildrenIntoHandler(VisualToMountChildrenIntoDelegate impl) noexcept; + void SetIVisualToMountChildrenIntoHandler( + winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate impl) noexcept; + void SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl) noexcept; public: IComponentProps CreateProps(ViewProps props, const IComponentProps &cloneFrom) noexcept; @@ -60,6 +64,18 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< facebook::react::Tag tag, const Experimental::ICompositionContext &context) noexcept; + const UpdateFinalizerDelegate &FinalizeUpdateHandler() const noexcept; + const HandleCommandDelegate &CustomCommandHandler() const noexcept; + const winrt::Microsoft::ReactNative::UpdatePropsDelegate &UpdatePropsHandler() const noexcept; + const winrt::Microsoft::ReactNative::UpdateStateDelegate &UpdateStateHandler() const noexcept; + const UpdateEventEmitterDelegate &UpdateEventEmitterHandler() const noexcept; + const MountChildComponentViewDelegate &MountChildComponentViewHandler() const noexcept; + const UnmountChildComponentViewDelegate &UnmountChildComponentViewHandler() const noexcept; + const UpdateLayoutMetricsDelegate &UpdateLayoutMetricsHandler() const noexcept; + const CreateVisualDelegate &CreateVisualHandler() const noexcept; + const winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate & + VisualToMountChildrenIntoHandler() const noexcept; + private: void InitializeComponentView(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept; @@ -74,7 +90,8 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context, - ComponentViewFeatures features)> + ComponentViewFeatures features, + ReactCompositionViewComponentBuilder &builder)> m_fnCreateView; std::function m_descriptorConstructorFactory; winrt::Microsoft::ReactNative::HandleCommandDelegate m_customCommandHandler; @@ -86,6 +103,9 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< winrt::Microsoft::ReactNative::UnmountChildComponentViewDelegate m_unmountChildComponentViewHandler; winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate m_createVisualHandler; + winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate + m_visualToMountChildrenIntoHandler; + UpdateLayoutMetricsDelegate m_updateLayoutMetricsHandler; }; } // namespace winrt::Microsoft::ReactNative::Composition diff --git a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl index 021103285d9..2edf2b822aa 100644 --- a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +++ b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl @@ -25,6 +25,29 @@ namespace Microsoft.ReactNative.Composition [webhosthidden] delegate Microsoft.UI.Composition.Visual CreateVisualDelegate(Microsoft.ReactNative.ComponentView view); + [experimental] + delegate void UpdateLayoutMetricsDelegate(Microsoft.ReactNative.ComponentView source, Microsoft.ReactNative.LayoutMetrics newLayoutMetrics, Microsoft.ReactNative.LayoutMetrics oldLayoutMetrics); + + [experimental] + [webhosthidden] + delegate Microsoft.UI.Composition.Visual VisualToMountChildrenIntoDelegate(Microsoft.ReactNative.ComponentView view); + + namespace Experimental { + [experimental] + [webhosthidden] + DOC_STRING("This type will be removed in future versions") + delegate Microsoft.ReactNative.Composition.Experimental.IVisual IVisualToMountChildrenIntoDelegate(Microsoft.ReactNative.ComponentView view); + + [experimental] + [webhosthidden] + DOC_STRING("This interface is for use when running react-native-windows using a custom compositor. " + "This interface will be removed in future versions") + interface IReactCompositionViewComponentInternalBuilder + { + void SetIVisualToMountChildrenIntoHandler(IVisualToMountChildrenIntoDelegate impl); + }; + } + [webhosthidden] [experimental] DOC_STRING(".") @@ -34,6 +57,8 @@ namespace Microsoft.ReactNative.Composition void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer); void SetCreateVisualHandler(CreateVisualDelegate impl); void SetViewFeatures(ComponentViewFeatures viewFeatures); + void SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl); + void SetVisualToMountChildrenIntoHandler(VisualToMountChildrenIntoDelegate impl); }; } // namespace Microsoft.ReactNative