Skip to content

Commit 60909d3

Browse files
authored
[Fabric] Use PopupWindowSiteBridge for Modal when USE_EXPERIMENTAL_WINUI3 is true (#14284)
* add modal implementation with PopupWindowSiteBridge * Change files * add conditional * feedback
1 parent c0848e5 commit 60909d3

File tree

3 files changed

+101
-16
lines changed

3 files changed

+101
-16
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "add modal implementation with PopupWindowSiteBridge",
4+
"packageName": "react-native-windows",
5+
"email": "tatianakapos@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}

vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
3737
m_window.Destroy();
3838
m_window = nullptr;
3939
}
40+
41+
#ifdef USE_EXPERIMENTAL_WINUI3
42+
if (m_popUp) {
43+
m_popUp.Close();
44+
m_popUp = nullptr;
45+
}
46+
#endif
4047
}
4148

4249
void InitializePortalViewComponent(
@@ -85,7 +92,6 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
8592
private:
8693
void OnMounted(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
8794
m_mounted = true;
88-
8995
if (m_showQueued) {
9096
ShowOnUIThread(view);
9197
}
@@ -108,11 +114,20 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
108114
int32_t yCor = static_cast<int32_t>(
109115
(parentRC.top + parentRC.bottom - layoutMetrics.Frame.Height * layoutMetrics.PointScaleFactor) / 2);
110116

117+
#ifdef USE_EXPERIMENTAL_WINUI3
118+
winrt::Windows::Graphics::RectInt32 rect2{
119+
(int)xCor,
120+
(int)yCor,
121+
static_cast<int32_t>(layoutMetrics.Frame.Width * (layoutMetrics.PointScaleFactor)),
122+
static_cast<int32_t>(layoutMetrics.Frame.Height * (layoutMetrics.PointScaleFactor))};
123+
m_popUp.MoveAndResize(rect2);
124+
#else
111125
// Adjust window position and size
112126
m_window.ResizeClient(
113127
{static_cast<int32_t>(layoutMetrics.Frame.Width * (layoutMetrics.PointScaleFactor)),
114128
static_cast<int32_t>(layoutMetrics.Frame.Height * (layoutMetrics.PointScaleFactor))});
115129
m_window.Move({xCor, yCor});
130+
#endif
116131
};
117132

118133
void ShowOnUIThread(const winrt::Microsoft::ReactNative::ComponentView &view) {
@@ -122,6 +137,24 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
122137
m_showQueued = false;
123138
EnsureModalCreated(view);
124139

140+
#ifdef USE_EXPERIMENTAL_WINUI3
141+
if (m_popUp) {
142+
m_bridge.Enable();
143+
m_popUp.Show();
144+
145+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(
146+
m_popUp.as<winrt::Microsoft::UI::Content::IContentSiteBridge>());
147+
auto result = navHost.NavigateFocus(winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(
148+
winrt::Microsoft::UI::Input::FocusNavigationReason::First));
149+
150+
// dispatch onShow event
151+
if (auto eventEmitter = EventEmitter()) {
152+
::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnShow eventArgs;
153+
eventEmitter->onShow(eventArgs);
154+
}
155+
}
156+
#endif
157+
125158
if (m_window && !m_window.IsVisible()) {
126159
m_bridge.Enable();
127160
m_window.Show(true);
@@ -146,6 +179,12 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
146179
m_window.Hide();
147180
}
148181

182+
#ifdef USE_EXPERIMENTAL_WINUI3
183+
if (m_popUp) {
184+
m_popUp.Hide();
185+
}
186+
#endif
187+
149188
// dispatch onDismiss event
150189
if (auto eventEmitter = EventEmitter()) {
151190
::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnDismiss eventArgs;
@@ -168,13 +207,45 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
168207
return;
169208
}
170209

210+
#ifdef USE_EXPERIMENTAL_WINUI3
211+
if (m_popUp) {
212+
return;
213+
}
214+
#endif
171215
// get the root hwnd
172216
m_prevWindowID =
173217
winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(view.ReactContext().Properties());
174218

175219
m_parentHwnd =
176220
view.as<::Microsoft::ReactNative::Composition::Experimental::IComponentViewInterop>()->GetHwndForParenting();
177221

222+
#ifdef USE_EXPERIMENTAL_WINUI3
223+
m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
224+
view.Parent().as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Compositor(),
225+
winrt::Microsoft::UI::GetWindowIdFromWindow(m_parentHwnd));
226+
m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal(
227+
view.as<winrt::Microsoft::ReactNative::Composition::PortalComponentView>());
228+
auto contentIsland = m_reactNativeIsland.Island();
229+
230+
m_popUp = m_bridge.TryCreatePopupSiteBridge();
231+
m_popUp.Connect(contentIsland);
232+
233+
// set the top-level windows as the new hwnd
234+
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
235+
view.ReactContext().Properties(),
236+
reinterpret_cast<uint64_t>(winrt::Microsoft::UI::GetWindowFromWindowId(m_popUp.WindowId())));
237+
238+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(
239+
m_popUp.as<winrt::Microsoft::UI::Content::IContentSiteBridge>());
240+
m_departFocusToken = navHost.DepartFocusRequested(
241+
[wkView = winrt::make_weak(view)](
242+
const auto &sender, const winrt::Microsoft::UI::Input::FocusNavigationRequestEventArgs &args) {
243+
if (auto strongView = wkView.get()) {
244+
TrySetFocus(strongView.Parent());
245+
}
246+
});
247+
248+
#else
178249
auto presenter = winrt::Microsoft::UI::Windowing::OverlappedPresenter::CreateForDialog();
179250
presenter.SetBorderAndTitleBar(true, false);
180251
presenter.IsModal(true);
@@ -202,9 +273,11 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
202273
TrySetFocus(strongView.Parent());
203274
}
204275
});
276+
m_bridge.Connect(contentIsland);
277+
278+
#endif
205279

206280
m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
207-
m_bridge.Connect(contentIsland);
208281
AdjustWindowSize(view.LayoutMetrics());
209282
m_bridge.Show();
210283
}
@@ -226,6 +299,9 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
226299
winrt::event_token m_departFocusToken;
227300
winrt::Microsoft::UI::Content::DesktopChildSiteBridge m_bridge{nullptr};
228301
winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland{nullptr};
302+
#ifdef USE_EXPERIMENTAL_WINUI3
303+
winrt::Microsoft::UI::Content::PopupWindowSiteBridge m_popUp{nullptr};
304+
#endif
229305
};
230306

231307
void RegisterWindowsModalHostNativeComponent(

vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -913,21 +913,23 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
913913
}
914914
});
915915
#ifdef USE_EXPERIMENTAL_WINUI3
916-
m_islandConnectedToken = m_island.Connected(
917-
[weakThis = get_weak()](
918-
winrt::IInspectable const &, winrt::Microsoft::UI::Content::ContentIsland const &island) {
919-
if (auto pThis = weakThis.get()) {
920-
pThis->OnMounted();
921-
}
922-
});
916+
if (!m_isFragment) {
917+
m_islandConnectedToken = m_island.Connected(
918+
[weakThis = get_weak()](
919+
winrt::IInspectable const &, winrt::Microsoft::UI::Content::ContentIsland const &island) {
920+
if (auto pThis = weakThis.get()) {
921+
pThis->OnMounted();
922+
}
923+
});
923924

924-
m_islandDisconnectedToken = m_island.Disconnected(
925-
[weakThis = get_weak()](
926-
winrt::IInspectable const &, winrt::Microsoft::UI::Content::ContentIsland const &island) {
927-
if (auto pThis = weakThis.get()) {
928-
pThis->OnUnmounted();
929-
}
930-
});
925+
m_islandDisconnectedToken = m_island.Disconnected(
926+
[weakThis = get_weak()](
927+
winrt::IInspectable const &, winrt::Microsoft::UI::Content::ContentIsland const &island) {
928+
if (auto pThis = weakThis.get()) {
929+
pThis->OnUnmounted();
930+
}
931+
});
932+
}
931933
#endif
932934
}
933935
return m_island;

0 commit comments

Comments
 (0)