From 370afa484bc60c292fe1214ec51d2a12471f0c22 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Thu, 1 Feb 2024 13:55:58 -0800 Subject: [PATCH 01/17] save state --- .../WindowsModalHostViewComponentView.cpp | 79 +++++++++++++++---- .../Modal/WindowsModalHostViewComponentView.h | 8 +- .../Views/UnimplementedViewManager.cpp | 2 + 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index f2278420dbb..ac3928578f4 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -10,35 +10,38 @@ #include "../CompositionDynamicAutomationProvider.h" #include "Composition/AutoDraw.h" #include "Unicode.h" +#include "WinUser.h" namespace winrt::Microsoft::ReactNative::Composition::implementation { -winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create( - const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext, - facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept { - return winrt::make(compContext, tag, reactContext); -} WindowsModalHostComponentView::WindowsModalHostComponentView( const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext) - : Super(compContext, tag, reactContext, CompositionComponentViewFeatures::Default) { - m_props = std::make_shared(); + : base_type( + compContext, + tag, + reactContext, + (CompositionComponentViewFeatures::Default & ~CompositionComponentViewFeatures::NativeBorder)) { + static auto const defaultProps = std::make_shared(); + m_props = defaultProps; m_visual = compContext.CreateSpriteVisual(); } +winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create( + const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext, + facebook::react::Tag tag, + winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept { + return winrt::make(compContext, tag, reactContext); +} + void WindowsModalHostComponentView::mountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView & /*childComponentView*/, - uint32_t /*index*/) noexcept { - // assert(false); -} + uint32_t /*index*/) noexcept {} void WindowsModalHostComponentView::unmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView & /*childComponentView*/, - uint32_t /*index*/) noexcept { - // assert(false); -} + uint32_t /*index*/) noexcept {} void WindowsModalHostComponentView::handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept { Super::handleCommand(commandName, arg); @@ -47,6 +50,17 @@ void WindowsModalHostComponentView::handleCommand(std::string const &commandName void WindowsModalHostComponentView::updateProps( facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept { + const auto &oldModalProps = *std::static_pointer_cast(m_props); + const auto &newModalProps = *std::static_pointer_cast(props); + + if (oldModalProps.visible != newModalProps.visible) { + // todo + } + + // update BaseComponentView props + updateTransformProps(oldModalProps, newModalProps, m_visual); + Super::updateProps(props, oldProps); + m_props = std::static_pointer_cast(props); } @@ -57,9 +71,11 @@ void WindowsModalHostComponentView::updateLayoutMetrics( OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None); } + CreateDialogA(); // TODO: RedBox placeholder for Modal (taken from unimplementedNativeViewComponent) - if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || - m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) { + // if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != + // layoutMetrics.pointScaleFactor) { // layout is never set? + if (true) { // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was // rendered float width = std::max(m_layoutMetrics.frame.size.width, 200.0f); @@ -87,7 +103,7 @@ void WindowsModalHostComponentView::updateLayoutMetrics( { ::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(drawingSurface, &offset); if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) { - d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Red, 0.3f)); + d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Blue, 0.3f)); assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS); const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f; float oldDpiX, oldDpiY; @@ -95,7 +111,36 @@ void WindowsModalHostComponentView::updateLayoutMetrics( d2dDeviceContext->SetDpi(dpi, dpi); float offsetX = static_cast(offset.x / m_layoutMetrics.pointScaleFactor); + offsetX = 2.0f; float offsetY = static_cast(offset.y / m_layoutMetrics.pointScaleFactor); + + winrt::com_ptr spTextFormat; + winrt::check_hresult(::Microsoft::ReactNative::DWriteFactory()->CreateTextFormat( + L"Segoe UI", + nullptr, // Font collection (nullptr sets it to use the system font collection). + DWRITE_FONT_WEIGHT_REGULAR, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 12, + L"", + spTextFormat.put())); + + winrt::com_ptr textBrush; + winrt::check_hresult( + d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), textBrush.put())); + + const D2D1_RECT_F rect = { + static_cast(offset.x), static_cast(offset.y), width + offset.x, height + offset.y}; + + auto label = ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("Modal")); + d2dDeviceContext->DrawText( + label.c_str(), + static_cast(label.length()), + spTextFormat.get(), + rect, + textBrush.get(), + D2D1_DRAW_TEXT_OPTIONS_NONE, + DWRITE_MEASURING_MODE_NATURAL); } } } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index 21b0ff5d639..f6b6cde1bff 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -15,8 +15,10 @@ namespace winrt::Microsoft::ReactNative::Composition::implementation { struct WindowsModalHostComponentView - : WindowsModalHostComponentViewT { - using Super = WindowsModalHostComponentViewT; + : public winrt::Microsoft::ReactNative::Composition::implementation:: + WindowsModalHostComponentViewT { + using Super = winrt::Microsoft::ReactNative::Composition::implementation:: + WindowsModalHostComponentViewT; [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create( const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext, @@ -52,8 +54,8 @@ struct WindowsModalHostComponentView winrt::Microsoft::ReactNative::ReactContext const &reactContext); private: + std::shared_ptr m_props; winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr}; - facebook::react::SharedViewProps m_props; }; } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp index a89e29687aa..82cc3816f14 100644 --- a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp +++ b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp @@ -59,9 +59,11 @@ const wchar_t *UnimplementedViewManager::GetName() const { void UnimplementedViewManager::GetNativeProps(const winrt::Microsoft::ReactNative::IJSValueWriter &writer) const { Super::GetNativeProps(writer); + // Modal View Props (Todo: fix so these aren't in UnimplementedView) winrt::Microsoft::ReactNative::WriteProperty(writer, L"animationType", L"string"); winrt::Microsoft::ReactNative::WriteProperty(writer, L"presentationStyle", L"string"); winrt::Microsoft::ReactNative::WriteProperty(writer, L"focusable", L"boolean"); + winrt::Microsoft::ReactNative::WriteProperty(writer, L"visible", L"boolean"); } ShadowNode *UnimplementedViewManager::createShadow() const { From fa304517274ecc38b7baf02491b36ecb223264a6 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Thu, 1 Feb 2024 13:56:32 -0800 Subject: [PATCH 02/17] save --- .../Composition/Modal/WindowsModalHostViewComponentView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index ac3928578f4..a6bc5be43dd 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -71,7 +71,7 @@ void WindowsModalHostComponentView::updateLayoutMetrics( OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None); } - CreateDialogA(); + //CreateDialogA(); // TODO: RedBox placeholder for Modal (taken from unimplementedNativeViewComponent) // if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != // layoutMetrics.pointScaleFactor) { // layout is never set? From f1ae96beb9f0d002ea7d9392796a9c79c2876c01 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Tue, 6 Feb 2024 10:24:46 -0800 Subject: [PATCH 03/17] save state --- .../WindowsModalHostViewComponentView.cpp | 133 +++++++++++++++++- .../Modal/WindowsModalHostViewComponentView.h | 12 ++ 2 files changed, 139 insertions(+), 6 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index a6bc5be43dd..41b14c0fc07 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -12,6 +12,14 @@ #include "Unicode.h" #include "WinUser.h" +// Testing +#include +#include +#include +#include "ReactNativeHost.h" +#include "IReactContext.h" +#include "ReactHost/ReactInstanceWin.h" + namespace winrt::Microsoft::ReactNative::Composition::implementation { WindowsModalHostComponentView::WindowsModalHostComponentView( @@ -25,6 +33,7 @@ WindowsModalHostComponentView::WindowsModalHostComponentView( (CompositionComponentViewFeatures::Default & ~CompositionComponentViewFeatures::NativeBorder)) { static auto const defaultProps = std::make_shared(); m_props = defaultProps; + m_context = reactContext; // save context m_visual = compContext.CreateSpriteVisual(); } @@ -35,6 +44,119 @@ winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Crea return winrt::make(compContext, tag, reactContext); } +// Testing - Trying to get a new window to show up, code taken from LogBox + +constexpr PCWSTR c_logBoxWindowClassName = L"MS_REACTNATIVE_MODAL"; +constexpr auto CompHostProperty = L"CompHost"; +const int LOGBOX_DEFAULT_WIDTH = 700; +const int LOGBOX_DEFAULT_HEIGHT = 1000; + +void WindowsModalHostComponentView::ShowOnUIThread() noexcept { + auto host = React::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); + if (!host) {return;} + + RegisterWndClass(); + + if (!m_hwnd) { + auto CompositionHwndHost = React::CompositionHwndHost(); + winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; + viewOptions.ComponentName(L"LogBox"); + CompositionHwndHost.ReactViewHost( + winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions)); + HINSTANCE hInstance = GetModuleHandle(NULL); + winrt::impl::abi::type *pHost{nullptr}; + winrt::com_ptr<::IUnknown> spunk; + CompositionHwndHost.as(spunk); + spunk->AddRef(); // Will be stored in windowData + + m_hwnd = CreateWindow( + c_logBoxWindowClassName, + L"React-Native Modal", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + LOGBOX_DEFAULT_WIDTH, + LOGBOX_DEFAULT_HEIGHT, + nullptr, + nullptr, + hInstance, + spunk.get()); + } + + ShowWindow(m_hwnd, SW_NORMAL); + BringWindowToTop(m_hwnd); + SetFocus(m_hwnd); +} + +void WindowsModalHostComponentView::HideOnUIThread() noexcept { + if (m_hwnd) { + ::ShowWindow(m_hwnd, SW_HIDE); + } +} + +LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { + auto data = reinterpret_cast<::IUnknown *>(GetProp(hwnd, CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) + winrt::com_ptr spunk; // What is this?? + React::CompositionHwndHost host{nullptr}; // This gets set in following if statement + + if (data) { // if we get the data + winrt::check_hresult(data->QueryInterface(winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host + auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); // is this just checking that we got a CompositionHwndHost? + if (result) + return result; + } + + switch (message) { + case WM_NCCREATE: { // sent before WM_CREATE, lparam should be identical to members of CreateWindowEx + auto createStruct = reinterpret_cast(lparam); //CreateStruct + auto windowData = static_cast<::IUnknown *>(createStruct->lpCreateParams); + SetProp(hwnd, CompHostProperty, reinterpret_cast<::IUnknown *>(windowData)); // adds new properties to window + break; + } + case WM_CREATE: { // recieves after window is created but before visible + host.Initialize((uint64_t)hwnd); + break; + } + case WM_CLOSE: { + // Just hide the window instead of destroying it + ::ShowWindow(hwnd, SW_HIDE); + return 0; + } + case WM_DESTROY: { + data->Release(); + SetProp(hwnd, CompHostProperty, nullptr); + } + } + + return DefWindowProc(hwnd, message, wparam, lparam); +} + +void WindowsModalHostComponentView::RegisterWndClass() noexcept { + static bool registered = false; + if (registered) // isn't this always going to be false?? + return; + + HINSTANCE hInstance = GetModuleHandle(NULL); + + WNDCLASSEXW wcex = {}; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = &LogBoxWndProc; + wcex.cbClsExtra = DLGWINDOWEXTRA; + wcex.cbWndExtra = sizeof(winrt::impl::abi::type *); + wcex.hInstance = hInstance; + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszClassName = c_logBoxWindowClassName; + ATOM classId = RegisterClassEx(&wcex); + WINRT_VERIFY(classId); + winrt::check_win32(!classId); + + registered = true; +} + +// Testing + void WindowsModalHostComponentView::mountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView & /*childComponentView*/, uint32_t /*index*/) noexcept {} @@ -53,7 +175,8 @@ void WindowsModalHostComponentView::updateProps( const auto &oldModalProps = *std::static_pointer_cast(m_props); const auto &newModalProps = *std::static_pointer_cast(props); - if (oldModalProps.visible != newModalProps.visible) { + if (newModalProps.visible == true) { + //ShowOnUIThread(); // todo } @@ -71,11 +194,9 @@ void WindowsModalHostComponentView::updateLayoutMetrics( OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None); } - //CreateDialogA(); - // TODO: RedBox placeholder for Modal (taken from unimplementedNativeViewComponent) - // if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != - // layoutMetrics.pointScaleFactor) { // layout is never set? - if (true) { + // TODO: RedBox placeholder for Modal (taken from unimplementedNativeViewComponent) - Need to Debug why this doesn't work :( + if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) { // layout is never set? + //if (true) { // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was // rendered float width = std::max(m_layoutMetrics.frame.size.width, 200.0f); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index f6b6cde1bff..743c3f21b7e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -53,9 +53,21 @@ struct WindowsModalHostComponentView facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext); + // Testing + void ShowOnUIThread() noexcept; + void HideOnUIThread() noexcept; + static void RegisterWndClass() noexcept; + + // Testing + private: std::shared_ptr m_props; winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr}; + + // Testing + HWND m_hwnd{nullptr}; + winrt::Microsoft::ReactNative::ReactContext m_context; + // Testing }; } // namespace winrt::Microsoft::ReactNative::Composition::implementation From 6d0415ee5ff694b9ec104afca18f0e34b899d72c Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Tue, 6 Feb 2024 16:42:31 -0800 Subject: [PATCH 04/17] blue box gets shown on modal --- .../WindowsModalHostViewComponentView.cpp | 24 +++++++++---------- .../Modal/WindowsModalHostViewComponentView.h | 11 ++++----- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 41b14c0fc07..0f68b5af3ec 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -1,4 +1,3 @@ - // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. @@ -7,10 +6,9 @@ #include "WindowsModalHostViewComponentView.h" #include -#include "../CompositionDynamicAutomationProvider.h" #include "Composition/AutoDraw.h" +#include "../CompositionDynamicAutomationProvider.h" #include "Unicode.h" -#include "WinUser.h" // Testing #include @@ -19,6 +17,7 @@ #include "ReactNativeHost.h" #include "IReactContext.h" #include "ReactHost/ReactInstanceWin.h" +// Testing namespace winrt::Microsoft::ReactNative::Composition::implementation { @@ -165,10 +164,6 @@ void WindowsModalHostComponentView::unmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView & /*childComponentView*/, uint32_t /*index*/) noexcept {} -void WindowsModalHostComponentView::handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept { - Super::handleCommand(commandName, arg); -} - void WindowsModalHostComponentView::updateProps( facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept { @@ -183,7 +178,6 @@ void WindowsModalHostComponentView::updateProps( // update BaseComponentView props updateTransformProps(oldModalProps, newModalProps, m_visual); Super::updateProps(props, oldProps); - m_props = std::static_pointer_cast(props); } @@ -194,9 +188,8 @@ void WindowsModalHostComponentView::updateLayoutMetrics( OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None); } - // TODO: RedBox placeholder for Modal (taken from unimplementedNativeViewComponent) - Need to Debug why this doesn't work :( - if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) { // layout is never set? - //if (true) { + if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || + m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) { // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was // rendered float width = std::max(m_layoutMetrics.frame.size.width, 200.0f); @@ -232,7 +225,6 @@ void WindowsModalHostComponentView::updateLayoutMetrics( d2dDeviceContext->SetDpi(dpi, dpi); float offsetX = static_cast(offset.x / m_layoutMetrics.pointScaleFactor); - offsetX = 2.0f; float offsetY = static_cast(offset.y / m_layoutMetrics.pointScaleFactor); winrt::com_ptr spTextFormat; @@ -252,8 +244,10 @@ void WindowsModalHostComponentView::updateLayoutMetrics( const D2D1_RECT_F rect = { static_cast(offset.x), static_cast(offset.y), width + offset.x, height + offset.y}; + // const D2D1_RECT_F rect = {0.f, 0.f, width, height}; - auto label = ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("Modal")); + auto label = + ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("This is a Modal")); d2dDeviceContext->DrawText( label.c_str(), static_cast(label.length()), @@ -283,6 +277,10 @@ winrt::Microsoft::ReactNative::Composition::IVisual WindowsModalHostComponentVie return m_visual; } +winrt::Microsoft::ReactNative::Composition::IVisual WindowsModalHostComponentView::OuterVisual() const noexcept { + return m_visual; +} + facebook::react::Tag WindowsModalHostComponentView::hitTest( facebook::react::Point pt, facebook::react::Point &localPt, diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index 743c3f21b7e..5dde17cac3b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -1,4 +1,3 @@ - // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. @@ -31,21 +30,22 @@ struct WindowsModalHostComponentView void unmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept override; - void handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept override; - void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept - override; + void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept override; + + void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept + override; void updateLayoutMetrics( facebook::react::LayoutMetrics const &layoutMetrics, facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override; void prepareForRecycle() noexcept override; facebook::react::SharedViewProps viewProps() noexcept override; bool focusable() const noexcept override; - facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents) const noexcept override; winrt::Microsoft::ReactNative::Composition::IVisual Visual() const noexcept override; + winrt::Microsoft::ReactNative::Composition::IVisual OuterVisual() const noexcept override; virtual std::string DefaultControlType() const noexcept; WindowsModalHostComponentView( @@ -57,7 +57,6 @@ struct WindowsModalHostComponentView void ShowOnUIThread() noexcept; void HideOnUIThread() noexcept; static void RegisterWndClass() noexcept; - // Testing private: From cb604297549deb6571569f2d3e3cc3ef28edf3c7 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Fri, 9 Feb 2024 10:35:16 -0800 Subject: [PATCH 05/17] clean up code and comments --- .../WindowsModalHostViewComponentView.cpp | 147 +++++++++--------- .../Modal/WindowsModalHostViewComponentView.h | 6 +- 2 files changed, 77 insertions(+), 76 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 0f68b5af3ec..54a86bd67b5 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -6,18 +6,16 @@ #include "WindowsModalHostViewComponentView.h" #include -#include "Composition/AutoDraw.h" #include "../CompositionDynamicAutomationProvider.h" +#include "Composition/AutoDraw.h" #include "Unicode.h" -// Testing #include #include #include -#include "ReactNativeHost.h" #include "IReactContext.h" #include "ReactHost/ReactInstanceWin.h" -// Testing +#include "ReactNativeHost.h" namespace winrt::Microsoft::ReactNative::Composition::implementation { @@ -43,48 +41,50 @@ winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Crea return winrt::make(compContext, tag, reactContext); } -// Testing - Trying to get a new window to show up, code taken from LogBox - -constexpr PCWSTR c_logBoxWindowClassName = L"MS_REACTNATIVE_MODAL"; +// constants for creating a new windows (code mostly taken from LogBox) +constexpr PCWSTR c_modalWindowClassName = L"MS_REACTNATIVE_MODAL"; constexpr auto CompHostProperty = L"CompHost"; -const int LOGBOX_DEFAULT_WIDTH = 700; -const int LOGBOX_DEFAULT_HEIGHT = 1000; +const int MODAL_DEFAULT_WIDTH = 500; +const int MODAL_DEFAULT_HEIGHT = 500; +// creates a new modal window void WindowsModalHostComponentView::ShowOnUIThread() noexcept { auto host = React::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); - if (!host) {return;} - - RegisterWndClass(); - - if (!m_hwnd) { - auto CompositionHwndHost = React::CompositionHwndHost(); - winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; - viewOptions.ComponentName(L"LogBox"); - CompositionHwndHost.ReactViewHost( - winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions)); - HINSTANCE hInstance = GetModuleHandle(NULL); - winrt::impl::abi::type *pHost{nullptr}; - winrt::com_ptr<::IUnknown> spunk; - CompositionHwndHost.as(spunk); - spunk->AddRef(); // Will be stored in windowData - - m_hwnd = CreateWindow( - c_logBoxWindowClassName, - L"React-Native Modal", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - LOGBOX_DEFAULT_WIDTH, - LOGBOX_DEFAULT_HEIGHT, - nullptr, - nullptr, - hInstance, - spunk.get()); - } + if (!host) { + return; + } + + RegisterWndClass(); // creates and register a windows class + + if (!m_hwnd) { + auto CompositionHwndHost = React::CompositionHwndHost(); + winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; + viewOptions.ComponentName(L"Modal"); + CompositionHwndHost.ReactViewHost( + winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions)); + HINSTANCE hInstance = GetModuleHandle(NULL); + winrt::impl::abi::type *pHost{nullptr}; + winrt::com_ptr<::IUnknown> spunk; + CompositionHwndHost.as(spunk); + spunk->AddRef(); // Will be stored in windowData + + m_hwnd = CreateWindow( + c_modalWindowClassName, + L"React-Native Modal", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + MODAL_DEFAULT_WIDTH, + MODAL_DEFAULT_HEIGHT, + nullptr, + nullptr, + hInstance, + spunk.get()); + } - ShowWindow(m_hwnd, SW_NORMAL); - BringWindowToTop(m_hwnd); - SetFocus(m_hwnd); + ShowWindow(m_hwnd, SW_NORMAL); + BringWindowToTop(m_hwnd); + SetFocus(m_hwnd); } void WindowsModalHostComponentView::HideOnUIThread() noexcept { @@ -93,27 +93,33 @@ void WindowsModalHostComponentView::HideOnUIThread() noexcept { } } +// Windows Procedure - callback function used for handling all messages (generated by NTUser or manual calls to +// SendMessage) LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { - auto data = reinterpret_cast<::IUnknown *>(GetProp(hwnd, CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) - winrt::com_ptr spunk; // What is this?? - React::CompositionHwndHost host{nullptr}; // This gets set in following if statement - - if (data) { // if we get the data - winrt::check_hresult(data->QueryInterface(winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host - auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); // is this just checking that we got a CompositionHwndHost? + auto data = reinterpret_cast<::IUnknown *>(GetProp( + hwnd, + CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) + winrt::com_ptr spunk; + React::CompositionHwndHost host{nullptr}; + + if (data) { + winrt::check_hresult(data->QueryInterface( + winrt::guid_of(), + winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host + auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); if (result) return result; } switch (message) { case WM_NCCREATE: { // sent before WM_CREATE, lparam should be identical to members of CreateWindowEx - auto createStruct = reinterpret_cast(lparam); //CreateStruct + auto createStruct = reinterpret_cast(lparam); // CreateStruct auto windowData = static_cast<::IUnknown *>(createStruct->lpCreateParams); SetProp(hwnd, CompHostProperty, reinterpret_cast<::IUnknown *>(windowData)); // adds new properties to window break; } case WM_CREATE: { // recieves after window is created but before visible - host.Initialize((uint64_t)hwnd); + // host.Initialize((uint64_t)hwnd); // this line currently breaks Modal and LogBox break; } case WM_CLOSE: { @@ -121,7 +127,7 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp ::ShowWindow(hwnd, SW_HIDE); return 0; } - case WM_DESTROY: { + case WM_DESTROY: { // called when we want to destroy the window data->Release(); SetProp(hwnd, CompHostProperty, nullptr); } @@ -130,32 +136,33 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp return DefWindowProc(hwnd, message, wparam, lparam); } +// Creates and Register a new window class void WindowsModalHostComponentView::RegisterWndClass() noexcept { static bool registered = false; - if (registered) // isn't this always going to be false?? + if (registered) return; - HINSTANCE hInstance = GetModuleHandle(NULL); + HINSTANCE hInstance = + GetModuleHandle(NULL); // returns a handle to the file used to create the calling process (.exe file) - WNDCLASSEXW wcex = {}; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = &LogBoxWndProc; - wcex.cbClsExtra = DLGWINDOWEXTRA; - wcex.cbWndExtra = sizeof(winrt::impl::abi::type *); + WNDCLASSEXW wcex = {}; // contains window class information + wcex.cbSize = sizeof(WNDCLASSEX); // size of windows class (bytes) + wcex.style = CS_HREDRAW | CS_VREDRAW; // class style (redraw window on size adjustment) + wcex.lpfnWndProc = &LogBoxWndProc; // pointer to windows procedure + wcex.cbClsExtra = DLGWINDOWEXTRA; // extra bytes to allocate + wcex.cbWndExtra = + sizeof(winrt::impl::abi::type *); // extra bytes to allocate wcex.hInstance = hInstance; - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wcex.lpszClassName = c_logBoxWindowClassName; - ATOM classId = RegisterClassEx(&wcex); - WINRT_VERIFY(classId); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); // handle to class cursor + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // background color + wcex.lpszClassName = c_modalWindowClassName; // specify resource name + ATOM classId = RegisterClassEx(&wcex); // register new windows class + WINRT_VERIFY(classId); // 0 = fail winrt::check_win32(!classId); registered = true; } -// Testing - void WindowsModalHostComponentView::mountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView & /*childComponentView*/, uint32_t /*index*/) noexcept {} @@ -170,9 +177,9 @@ void WindowsModalHostComponentView::updateProps( const auto &oldModalProps = *std::static_pointer_cast(m_props); const auto &newModalProps = *std::static_pointer_cast(props); + // currently Modal only gets Destroyed by closing the window if (newModalProps.visible == true) { - //ShowOnUIThread(); - // todo + ShowOnUIThread(); } // update BaseComponentView props @@ -244,10 +251,8 @@ void WindowsModalHostComponentView::updateLayoutMetrics( const D2D1_RECT_F rect = { static_cast(offset.x), static_cast(offset.y), width + offset.x, height + offset.y}; - // const D2D1_RECT_F rect = {0.f, 0.f, width, height}; - auto label = - ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("This is a Modal")); + auto label = ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("This is a Modal")); d2dDeviceContext->DrawText( label.c_str(), static_cast(label.length()), diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index 5dde17cac3b..70230ec9997 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -53,20 +53,16 @@ struct WindowsModalHostComponentView facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext); - // Testing + // Used for creating new window void ShowOnUIThread() noexcept; void HideOnUIThread() noexcept; static void RegisterWndClass() noexcept; - // Testing private: std::shared_ptr m_props; winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr}; - - // Testing HWND m_hwnd{nullptr}; winrt::Microsoft::ReactNative::ReactContext m_context; - // Testing }; } // namespace winrt::Microsoft::ReactNative::Composition::implementation From 71b6dd99557b43cb3b9ea3d8c2b9d3e5d877d393 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Fri, 9 Feb 2024 11:09:29 -0800 Subject: [PATCH 06/17] add parent hwnd --- .../Modal/WindowsModalHostViewComponentView.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 54a86bd67b5..18f2d2dc339 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -68,6 +68,10 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { CompositionHwndHost.as(spunk); spunk->AddRef(); // Will be stored in windowData + // get the root hwnd + auto roothwnd = reinterpret_cast( + winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_context.Properties().Handle())); + m_hwnd = CreateWindow( c_modalWindowClassName, L"React-Native Modal", @@ -76,7 +80,7 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { CW_USEDEFAULT, MODAL_DEFAULT_WIDTH, MODAL_DEFAULT_HEIGHT, - nullptr, + roothwnd, // parent nullptr, hInstance, spunk.get()); @@ -196,7 +200,7 @@ void WindowsModalHostComponentView::updateLayoutMetrics( } if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || - m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) { + m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor || m_layoutMetrics.frame.size.width == 0) { // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was // rendered float width = std::max(m_layoutMetrics.frame.size.width, 200.0f); From 76a5e31c0b4a386500cb37ed6cc9f2e69e5aa631 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Fri, 9 Feb 2024 11:14:28 -0800 Subject: [PATCH 07/17] Change files --- ...ative-windows-a2827b9b-c897-4b58-89e9-6bbb230ed98c.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-a2827b9b-c897-4b58-89e9-6bbb230ed98c.json diff --git a/change/react-native-windows-a2827b9b-c897-4b58-89e9-6bbb230ed98c.json b/change/react-native-windows-a2827b9b-c897-4b58-89e9-6bbb230ed98c.json new file mode 100644 index 00000000000..21cbcbf2325 --- /dev/null +++ b/change/react-native-windows-a2827b9b-c897-4b58-89e9-6bbb230ed98c.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "add window to Modal", + "packageName": "react-native-windows", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} From 047d852f204415f04c9efcfcf28c996794f049f0 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Mon, 12 Feb 2024 13:29:20 -0800 Subject: [PATCH 08/17] revert merge change --- .../Microsoft.ReactNative/packages.lock.json | 112 +++++++----------- 1 file changed, 42 insertions(+), 70 deletions(-) diff --git a/vnext/Microsoft.ReactNative/packages.lock.json b/vnext/Microsoft.ReactNative/packages.lock.json index de5eaf68319..246528c8a70 100644 --- a/vnext/Microsoft.ReactNative/packages.lock.json +++ b/vnext/Microsoft.ReactNative/packages.lock.json @@ -24,21 +24,21 @@ "Microsoft.SourceLink.Common": "1.1.1" } }, + "Microsoft.UI.Xaml": { + "type": "Direct", + "requested": "[2.8.0, )", + "resolved": "2.8.0", + "contentHash": "vxdHxTr63s5KVtNddMFpgvjBjUH50z7seq/5jLWmmSuf8poxg+sXrywkofUdE8ZstbpO9y3FL/IXXUcPYbeesA==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.1264.42" + } + }, "Microsoft.Windows.CppWinRT": { "type": "Direct", "requested": "[2.0.211028.7, )", "resolved": "2.0.211028.7", "contentHash": "JBGI0c3WLoU6aYJRy9Qo0MLDQfObEp+d4nrhR95iyzf7+HOgjRunHDp/6eGFREd7xq3OI1mll9ecJrMfzBvlyg==" }, - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } - }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "1.1.1", @@ -49,10 +49,10 @@ "resolved": "1.1.1", "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" }, - "Microsoft.Windows.SDK.BuildTools": { + "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "10.0.22621.756", - "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA==" + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" }, "common": { "type": "Project" @@ -63,8 +63,8 @@ "folly": { "type": "Project", "dependencies": { - "Fmt": "[1.0.0, )", - "boost": "[1.76.0, )" + "boost": "[1.76.0, )", + "fmt": "[1.0.0, )" } }, "reactcommon": { @@ -76,80 +76,52 @@ } }, "native,Version=v0.0/win10-arm": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-arm-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-arm64-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x64": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x64-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x86": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x86-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.231202003-experimental1, )", - "resolved": "1.5.231202003-experimental1", - "contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } } } From 74103078ebc84a85b2fa4bb3763a77114e42e1a5 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Mon, 12 Feb 2024 16:03:04 -0800 Subject: [PATCH 09/17] fix paths --- .../Modal/WindowsModalHostViewComponentView.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index f1cd1e944b1..63c36f51cbc 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -43,7 +43,8 @@ const int MODAL_DEFAULT_HEIGHT = 500; // creates a new modal window void WindowsModalHostComponentView::ShowOnUIThread() noexcept { - auto host = React::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); + auto host = + winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); if (!host) { return; } @@ -51,7 +52,7 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { RegisterWndClass(); // creates and register a windows class if (!m_hwnd) { - auto CompositionHwndHost = React::CompositionHwndHost(); + auto CompositionHwndHost = winrt::Microsoft::ReactNative::CompositionHwndHost(); winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; viewOptions.ComponentName(L"Modal"); CompositionHwndHost.ReactViewHost( @@ -98,11 +99,11 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp hwnd, CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) winrt::com_ptr spunk; - React::CompositionHwndHost host{nullptr}; + winrt::Microsoft::ReactNative::CompositionHwndHost host{nullptr}; if (data) { winrt::check_hresult(data->QueryInterface( - winrt::guid_of(), + winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); if (result) From 65ca4e68ea48c0a2ab8dbbcc4750f1e5c7053074 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 21 Feb 2024 14:03:41 -0800 Subject: [PATCH 10/17] address feedback --- .../WindowsModalHostViewComponentView.cpp | 35 ++++++++++++------- .../Views/UnimplementedViewManager.cpp | 6 ++-- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index e0ccbaa035a..afe679cda2e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -61,7 +61,6 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { winrt::impl::abi::type *pHost{nullptr}; winrt::com_ptr<::IUnknown> spunk; CompositionHwndHost.as(spunk); - spunk->AddRef(); // Will be stored in windowData // get the root hwnd auto roothwnd = reinterpret_cast( @@ -79,6 +78,15 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { nullptr, hInstance, spunk.get()); + + // Check if window creation succeeded + if (!m_hwnd) { + spunk.detach(); + return; + } + + spunk->AddRef(); // Will be stored in windowData + spunk.detach(); } ShowWindow(m_hwnd, SW_NORMAL); @@ -94,11 +102,10 @@ void WindowsModalHostComponentView::HideOnUIThread() noexcept { // Windows Procedure - callback function used for handling all messages (generated by NTUser or manual calls to // SendMessage) -LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { +LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { auto data = reinterpret_cast<::IUnknown *>(GetProp( hwnd, CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) - winrt::com_ptr spunk; winrt::Microsoft::ReactNative::CompositionHwndHost host{nullptr}; if (data) { @@ -106,8 +113,9 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); - if (result) + if (result) { return result; + } } switch (message) { @@ -118,7 +126,7 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp break; } case WM_CREATE: { // recieves after window is created but before visible - // host.Initialize((uint64_t)hwnd); // this line currently breaks Modal and LogBox + // host.Initialize((uint64_t)hwnd); cause Modal to throw a not registered error break; } case WM_CLOSE: { @@ -129,6 +137,7 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp case WM_DESTROY: { // called when we want to destroy the window data->Release(); SetProp(hwnd, CompHostProperty, nullptr); + break; } } @@ -138,16 +147,17 @@ LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp // Creates and Register a new window class void WindowsModalHostComponentView::RegisterWndClass() noexcept { static bool registered = false; - if (registered) + if (registered) { return; + } HINSTANCE hInstance = GetModuleHandle(NULL); // returns a handle to the file used to create the calling process (.exe file) - WNDCLASSEXW wcex = {}; // contains window class information - wcex.cbSize = sizeof(WNDCLASSEX); // size of windows class (bytes) + WNDCLASSEX wcex = {}; // contains window class information + wcex.cbSize = sizeof(wcex); // size of windows class (bytes) wcex.style = CS_HREDRAW | CS_VREDRAW; // class style (redraw window on size adjustment) - wcex.lpfnWndProc = &LogBoxWndProc; // pointer to windows procedure + wcex.lpfnWndProc = &ModalBoxWndProc; // pointer to windows procedure wcex.cbClsExtra = DLGWINDOWEXTRA; // extra bytes to allocate wcex.cbWndExtra = sizeof(winrt::impl::abi::type *); // extra bytes to allocate @@ -165,14 +175,14 @@ void WindowsModalHostComponentView::RegisterWndClass() noexcept { void WindowsModalHostComponentView::MountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); + // assert(false); base_type::MountChildComponentView(childComponentView, index); } void WindowsModalHostComponentView::UnmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); + // assert(false); base_type::UnmountChildComponentView(childComponentView, index); } @@ -189,7 +199,7 @@ void WindowsModalHostComponentView::updateProps( const auto &newModalProps = *std::static_pointer_cast(props); // currently Modal only gets Destroyed by closing the window - if (newModalProps.visible == true) { + if (newModalProps.visible) { ShowOnUIThread(); } @@ -206,6 +216,7 @@ void WindowsModalHostComponentView::updateLayoutMetrics( OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None); } + // Temparary placeholder for Modal, draws on main hwnd if (m_layoutMetrics.frame.size != layoutMetrics.frame.size || m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor || m_layoutMetrics.frame.size.width == 0) { // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was diff --git a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp index 82cc3816f14..4e8fe4ac357 100644 --- a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp +++ b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp @@ -55,11 +55,13 @@ UnimplementedViewManager::UnimplementedViewManager(const Mso::React::IReactConte const wchar_t *UnimplementedViewManager::GetName() const { return m_name.c_str(); } +s -void UnimplementedViewManager::GetNativeProps(const winrt::Microsoft::ReactNative::IJSValueWriter &writer) const { + void + UnimplementedViewManager::GetNativeProps(const winrt::Microsoft::ReactNative::IJSValueWriter &writer) const { Super::GetNativeProps(writer); - // Modal View Props (Todo: fix so these aren't in UnimplementedView) + // Modal View Props (Todo: fix so these aren't in UnimplementedView) #12753 winrt::Microsoft::ReactNative::WriteProperty(writer, L"animationType", L"string"); winrt::Microsoft::ReactNative::WriteProperty(writer, L"presentationStyle", L"string"); winrt::Microsoft::ReactNative::WriteProperty(writer, L"focusable", L"boolean"); From 2b15c454761f8078012b64a35975d295e47e65cb Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 21 Feb 2024 14:33:52 -0800 Subject: [PATCH 11/17] fix bad save --- .../Microsoft.ReactNative/Views/UnimplementedViewManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp index 4e8fe4ac357..529b5658dd0 100644 --- a/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp +++ b/vnext/Microsoft.ReactNative/Views/UnimplementedViewManager.cpp @@ -55,10 +55,8 @@ UnimplementedViewManager::UnimplementedViewManager(const Mso::React::IReactConte const wchar_t *UnimplementedViewManager::GetName() const { return m_name.c_str(); } -s - void - UnimplementedViewManager::GetNativeProps(const winrt::Microsoft::ReactNative::IJSValueWriter &writer) const { +void UnimplementedViewManager::GetNativeProps(const winrt::Microsoft::ReactNative::IJSValueWriter &writer) const { Super::GetNativeProps(writer); // Modal View Props (Todo: fix so these aren't in UnimplementedView) #12753 From 1383a96ff7863c08a21b162a4af84eed31b6e16f Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 21 Feb 2024 15:09:30 -0800 Subject: [PATCH 12/17] throw error --- .../Composition/Modal/WindowsModalHostViewComponentView.cpp | 4 ++-- .../Composition/Modal/WindowsModalHostViewComponentView.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index afe679cda2e..f3179a6941a 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -42,7 +42,7 @@ const int MODAL_DEFAULT_WIDTH = 500; const int MODAL_DEFAULT_HEIGHT = 500; // creates a new modal window -void WindowsModalHostComponentView::ShowOnUIThread() noexcept { +void WindowsModalHostComponentView::ShowOnUIThread() { auto host = winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); if (!host) { @@ -82,7 +82,7 @@ void WindowsModalHostComponentView::ShowOnUIThread() noexcept { // Check if window creation succeeded if (!m_hwnd) { spunk.detach(); - return; + throw std::exception("Failed to create new hwnd for Modal: " + GetLastError()); } spunk->AddRef(); // Will be stored in windowData diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index 8041df7ca52..5f75e796f27 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -52,7 +52,7 @@ struct WindowsModalHostComponentView : WindowsModalHostComponentViewT Date: Fri, 23 Feb 2024 13:33:55 -0800 Subject: [PATCH 13/17] feedback2 --- .../Composition/Modal/WindowsModalHostViewComponentView.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index f3179a6941a..8de881df36b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -81,11 +81,9 @@ void WindowsModalHostComponentView::ShowOnUIThread() { // Check if window creation succeeded if (!m_hwnd) { - spunk.detach(); throw std::exception("Failed to create new hwnd for Modal: " + GetLastError()); } - spunk->AddRef(); // Will be stored in windowData spunk.detach(); } From 1cdaadc18c512996e286c44c594e0fccdc43f391 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Tue, 27 Feb 2024 16:32:22 -0800 Subject: [PATCH 14/17] feedback3 --- .../Composition/Modal/WindowsModalHostViewComponentView.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 7cdfdd2c033..b03fe821a07 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -18,8 +18,6 @@ #include "ReactNativeHost.h" namespace winrt::Microsoft::ReactNative::Composition::implementation { - - WindowsModalHostComponentView::WindowsModalHostComponentView( const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext, facebook::react::Tag tag, @@ -126,8 +124,8 @@ LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM switch (message) { case WM_NCCREATE: { // sent before WM_CREATE, lparam should be identical to members of CreateWindowEx auto createStruct = reinterpret_cast(lparam); // CreateStruct - auto windowData = static_cast<::IUnknown *>(createStruct->lpCreateParams); - SetProp(hwnd, CompHostProperty, reinterpret_cast<::IUnknown *>(windowData)); // adds new properties to window + data = static_cast<::IUnknown *>(createStruct->lpCreateParams); + SetProp(hwnd, CompHostProperty, data); // adds new properties to window break; } case WM_CREATE: { // recieves after window is created but before visible From 78a85f3392bf048a81805f618be5af8f9e711ff6 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 28 Feb 2024 10:10:39 -0800 Subject: [PATCH 15/17] add comments --- .../Modal/WindowsModalHostViewComponentView.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index b03fe821a07..0e0d1518f79 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -115,7 +115,7 @@ LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM winrt::check_hresult(data->QueryInterface( winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host - auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); + auto result = host.TranslateMessage(message, wparam, lparam); if (result) { return result; } @@ -178,14 +178,16 @@ void WindowsModalHostComponentView::RegisterWndClass() noexcept { void WindowsModalHostComponentView::MountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - // assert(false); + // Disabled due to partial Modal implementation. Tracking re-enablement with task list here: + // https://github.com/microsoft/react-native-windows/issues/11157 assert(false); base_type::MountChildComponentView(childComponentView, index); } void WindowsModalHostComponentView::UnmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - // assert(false); + // Disabled due to partial Modal implementation.Tracking re-enablement with task list here : https : // + // github.com/microsoft/react-native-windows/issues/11157 assert(false); base_type::UnmountChildComponentView(childComponentView, index); } From 13e8761e6bc4616f79a4d25c14afec470effbc47 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 28 Feb 2024 10:32:47 -0800 Subject: [PATCH 16/17] add back cast --- .../Composition/Modal/WindowsModalHostViewComponentView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 0e0d1518f79..3ba9aa57543 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -115,7 +115,7 @@ LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM winrt::check_hresult(data->QueryInterface( winrt::guid_of(), winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host - auto result = host.TranslateMessage(message, wparam, lparam); + auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); if (result) { return result; } From 59f99d497796cd1f5e693b5d656168d6be503337 Mon Sep 17 00:00:00 2001 From: TatianaKapos Date: Wed, 28 Feb 2024 13:09:59 -0800 Subject: [PATCH 17/17] refactor methods --- .../WindowsModalHostViewComponentView.cpp | 80 ++++++++++--------- .../Modal/WindowsModalHostViewComponentView.h | 1 + 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 3ba9aa57543..57f287ede91 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -47,54 +47,55 @@ const int MODAL_DEFAULT_WIDTH = 500; const int MODAL_DEFAULT_HEIGHT = 500; // creates a new modal window -void WindowsModalHostComponentView::ShowOnUIThread() { +void WindowsModalHostComponentView::EnsureModalCreated() { auto host = winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties()); - if (!host) { + // return if hwnd already exists + if (!host || m_hwnd) { return; } RegisterWndClass(); // creates and register a windows class - + auto CompositionHwndHost = winrt::Microsoft::ReactNative::CompositionHwndHost(); + winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; + viewOptions.ComponentName(L"Modal"); + CompositionHwndHost.ReactViewHost(winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions)); + HINSTANCE hInstance = GetModuleHandle(NULL); + winrt::impl::abi::type *pHost{nullptr}; + winrt::com_ptr<::IUnknown> spunk; + CompositionHwndHost.as(spunk); + + // get the root hwnd + auto roothwnd = reinterpret_cast( + winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_context.Properties().Handle())); + + m_hwnd = CreateWindow( + c_modalWindowClassName, + L"React-Native Modal", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + MODAL_DEFAULT_WIDTH, + MODAL_DEFAULT_HEIGHT, + roothwnd, // parent + nullptr, + hInstance, + spunk.get()); + + // Check if window creation succeeded if (!m_hwnd) { - auto CompositionHwndHost = winrt::Microsoft::ReactNative::CompositionHwndHost(); - winrt::Microsoft::ReactNative::ReactViewOptions viewOptions; - viewOptions.ComponentName(L"Modal"); - CompositionHwndHost.ReactViewHost( - winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions)); - HINSTANCE hInstance = GetModuleHandle(NULL); - winrt::impl::abi::type *pHost{nullptr}; - winrt::com_ptr<::IUnknown> spunk; - CompositionHwndHost.as(spunk); - - // get the root hwnd - auto roothwnd = reinterpret_cast( - winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_context.Properties().Handle())); - - m_hwnd = CreateWindow( - c_modalWindowClassName, - L"React-Native Modal", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - MODAL_DEFAULT_WIDTH, - MODAL_DEFAULT_HEIGHT, - roothwnd, // parent - nullptr, - hInstance, - spunk.get()); - - // Check if window creation succeeded - if (!m_hwnd) { - throw std::exception("Failed to create new hwnd for Modal: " + GetLastError()); - } - - spunk.detach(); + throw std::exception("Failed to create new hwnd for Modal: " + GetLastError()); } - ShowWindow(m_hwnd, SW_NORMAL); - BringWindowToTop(m_hwnd); - SetFocus(m_hwnd); + spunk.detach(); +} + +void WindowsModalHostComponentView::ShowOnUIThread() { + if (m_hwnd) { + ShowWindow(m_hwnd, SW_NORMAL); + BringWindowToTop(m_hwnd); + SetFocus(m_hwnd); + } } void WindowsModalHostComponentView::HideOnUIThread() noexcept { @@ -205,6 +206,7 @@ void WindowsModalHostComponentView::updateProps( // currently Modal only gets Destroyed by closing the window if (newModalProps.visible) { + EnsureModalCreated(); ShowOnUIThread(); } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index 5f75e796f27..7917d255e77 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -54,6 +54,7 @@ struct WindowsModalHostComponentView : WindowsModalHostComponentViewT