react-native-windows 0.77.7 → 0.77.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Modal/Modal.windows.js +4 -1
- package/Microsoft.ReactNative/CompositionComponentView.idl +13 -1
- package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.cpp +97 -0
- package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.h +53 -0
- package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.h +160 -17
- package/Microsoft.ReactNative/Fabric/ComponentView.cpp +0 -1
- package/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +0 -5
- package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +0 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +13 -32
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -3
- package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +25 -20
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +313 -319
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +3 -61
- package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp +78 -0
- package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h +52 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +22 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +7 -5
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +79 -19
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -6
- package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +73 -19
- package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +16 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +2 -2
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +38 -23
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +1 -6
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +0 -3
- package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +0 -2
- package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +15 -1
- package/Microsoft.ReactNative/ReactNativeHost.cpp +5 -0
- package/Microsoft.ReactNative/ReactNativeIsland.idl +5 -1
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/Shared/Networking/WinRTWebSocketResource.cpp +82 -96
- package/Shared/Networking/WinRTWebSocketResource.h +91 -7
- package/Shared/Shared.vcxitems +6 -5
- package/Shared/Shared.vcxitems.filters +3 -4
- package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +212 -0
- package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +295 -0
- package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +200 -0
- package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +224 -0
- package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +250 -0
- package/codegen/react/components/rnwcore/AndroidSwitch.g.h +267 -0
- package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +234 -0
- package/codegen/react/components/rnwcore/InputAccessory.g.h +200 -0
- package/codegen/react/components/rnwcore/ModalHostView.g.h +283 -0
- package/codegen/react/components/rnwcore/PullToRefreshView.g.h +246 -0
- package/codegen/react/components/rnwcore/SafeAreaView.g.h +197 -0
- package/codegen/react/components/rnwcore/Switch.g.h +263 -0
- package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +200 -0
- package/just-task.js +1 -1
- package/package.json +3 -3
- package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +0 -191
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h +0 -39
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp +0 -18
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h +0 -39
package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp
CHANGED
|
@@ -5,379 +5,373 @@
|
|
|
5
5
|
|
|
6
6
|
#include "WindowsModalHostViewComponentView.h"
|
|
7
7
|
|
|
8
|
-
#include
|
|
9
|
-
#include <
|
|
10
|
-
#include "../CompositionDynamicAutomationProvider.h"
|
|
11
|
-
#include "Unicode.h"
|
|
12
|
-
|
|
13
|
-
#include <DispatcherQueue.h>
|
|
14
|
-
#include <Fabric/ComponentView.h>
|
|
15
|
-
#include <Fabric/Composition/CompositionContextHelper.h>
|
|
16
|
-
#include <Fabric/Composition/CompositionUIService.h>
|
|
17
|
-
#include <Fabric/Composition/ReactNativeIsland.h>
|
|
18
|
-
#include <windows.ui.composition.interop.h>
|
|
19
|
-
#include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
|
|
8
|
+
#include "../../../codegen/react/components/rnwcore/ModalHostView.g.h"
|
|
9
|
+
#include <ComponentView.Experimental.interop.h>
|
|
20
10
|
#include <winrt/Microsoft.UI.Content.h>
|
|
11
|
+
#include <winrt/Microsoft.UI.Input.h>
|
|
12
|
+
#include <winrt/Microsoft.UI.Windowing.h>
|
|
21
13
|
#include <winrt/Microsoft.UI.interop.h>
|
|
22
|
-
#include <winrt/Windows.UI.Composition.Desktop.h>
|
|
23
|
-
#include <winrt/Windows.UI.Composition.h>
|
|
24
|
-
#include "IReactContext.h"
|
|
25
|
-
#include "ReactHost/ReactInstanceWin.h"
|
|
26
|
-
#include "ReactNativeHost.h"
|
|
27
|
-
#include "WindowsModalHostViewShadowNode.h"
|
|
28
14
|
|
|
29
15
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
30
|
-
WindowsModalHostComponentView::WindowsModalHostComponentView(
|
|
31
|
-
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
|
|
32
|
-
facebook::react::Tag tag,
|
|
33
|
-
winrt::Microsoft::ReactNative::ReactContext const &reactContext)
|
|
34
|
-
: Super(compContext, tag, reactContext) {}
|
|
35
|
-
|
|
36
|
-
WindowsModalHostComponentView::~WindowsModalHostComponentView() {
|
|
37
|
-
// dispatch onDismiss event
|
|
38
|
-
auto emitter = std::static_pointer_cast<const facebook::react::ModalHostViewEventEmitter>(m_eventEmitter);
|
|
39
|
-
facebook::react::ModalHostViewEventEmitter::OnDismiss onDismissArgs;
|
|
40
|
-
emitter->onDismiss(onDismissArgs);
|
|
41
|
-
|
|
42
|
-
// reset the topWindowID
|
|
43
|
-
if (m_prevWindowID) {
|
|
44
|
-
auto host =
|
|
45
|
-
winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
|
|
46
|
-
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
|
|
47
|
-
host.InstanceSettings().Properties(), m_prevWindowID);
|
|
48
|
-
m_prevWindowID = 0;
|
|
49
|
-
}
|
|
50
16
|
|
|
51
|
-
|
|
52
|
-
|
|
17
|
+
struct ModalHostState
|
|
18
|
+
: winrt::implements<ModalHostState, winrt::Microsoft::ReactNative::Composition::IPortalStateData> {
|
|
19
|
+
ModalHostState(winrt::Microsoft::ReactNative::LayoutConstraints layoutConstraints, float scaleFactor)
|
|
20
|
+
: m_layoutConstraints(layoutConstraints), m_pointScaleFactor(scaleFactor) {}
|
|
53
21
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// Close/Destroy the modal window
|
|
57
|
-
SendMessage(m_hwnd, WM_DESTROY, 0, 0);
|
|
58
|
-
m_hwnd = nullptr;
|
|
22
|
+
winrt::Microsoft::ReactNative::LayoutConstraints LayoutConstraints() const noexcept {
|
|
23
|
+
return m_layoutConstraints;
|
|
59
24
|
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create(
|
|
63
|
-
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
|
|
64
|
-
facebook::react::Tag tag,
|
|
65
|
-
winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept {
|
|
66
|
-
return winrt::make<WindowsModalHostComponentView>(compContext, tag, reactContext);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// constants for creating a new windows
|
|
70
|
-
constexpr PCWSTR c_modalWindowClassName = L"MS_REACTNATIVE_MODAL";
|
|
71
|
-
constexpr auto CompHostProperty = L"CompHost";
|
|
72
|
-
const int MODAL_MIN_WIDTH = 50;
|
|
73
|
-
const int MODAL_MIN_HEIGHT = 50;
|
|
74
|
-
|
|
75
|
-
float ScaleFactor(HWND hwnd) noexcept {
|
|
76
|
-
return GetDpiForWindow(hwnd) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
|
|
77
|
-
}
|
|
78
25
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
auto host =
|
|
82
|
-
winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
|
|
83
|
-
|
|
84
|
-
// return if hwnd already exists
|
|
85
|
-
if (!host || m_hwnd) {
|
|
86
|
-
return;
|
|
26
|
+
float PointScaleFactor() const noexcept {
|
|
27
|
+
return m_pointScaleFactor;
|
|
87
28
|
}
|
|
88
29
|
|
|
89
|
-
|
|
30
|
+
private:
|
|
31
|
+
float m_pointScaleFactor{1.0f};
|
|
32
|
+
winrt::Microsoft::ReactNative::LayoutConstraints m_layoutConstraints;
|
|
33
|
+
};
|
|
90
34
|
|
|
91
|
-
|
|
92
|
-
|
|
35
|
+
struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::Foundation::IInspectable>,
|
|
36
|
+
::Microsoft::ReactNativeSpecs::BaseModalHostView<ModalHostView> {
|
|
37
|
+
~ModalHostView() {
|
|
38
|
+
if (m_window && m_window.IsVisible()) {
|
|
39
|
+
CloseWindow();
|
|
40
|
+
}
|
|
93
41
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
42
|
+
if (m_reactNativeIsland) {
|
|
43
|
+
m_reactNativeIsland.Island().Close();
|
|
44
|
+
}
|
|
97
45
|
|
|
98
|
-
|
|
46
|
+
if (m_bridge) {
|
|
47
|
+
if (m_departFocusToken && !m_bridge.IsClosed()) {
|
|
48
|
+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge);
|
|
49
|
+
navHost.DepartFocusRequested(m_departFocusToken);
|
|
50
|
+
}
|
|
51
|
+
m_bridge.Close();
|
|
52
|
+
}
|
|
99
53
|
|
|
100
|
-
|
|
54
|
+
if (m_window) {
|
|
55
|
+
m_window.Destroy();
|
|
56
|
+
m_window = nullptr;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
101
59
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
windowsStyle,
|
|
106
|
-
CW_USEDEFAULT,
|
|
107
|
-
CW_USEDEFAULT,
|
|
108
|
-
MODAL_MIN_WIDTH,
|
|
109
|
-
MODAL_MIN_HEIGHT,
|
|
110
|
-
m_parentHwnd, // parent
|
|
111
|
-
nullptr,
|
|
112
|
-
hInstance,
|
|
113
|
-
spunk.get());
|
|
60
|
+
void InitializePortalViewComponent(
|
|
61
|
+
const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portalComponentView) noexcept {
|
|
62
|
+
m_reactContext = portalComponentView.ReactContext();
|
|
114
63
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
64
|
+
portalComponentView.Mounted(
|
|
65
|
+
[](const auto & /*sender*/, const auto &view) { view.UserData().as<ModalHostView>()->OnMounted(view); });
|
|
66
|
+
portalComponentView.Unmounted(
|
|
67
|
+
[](const auto & /*sender*/, const auto &view) { view.UserData().as<ModalHostView>()->OnUnmounted(view); });
|
|
118
68
|
}
|
|
119
69
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
compositor, winrt::Microsoft::UI::GetWindowIdFromWindow(m_hwnd));
|
|
136
|
-
m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland(compositor, m_reactContext.Handle(), *this);
|
|
137
|
-
auto contentIsland = m_reactNativeIsland.Island();
|
|
138
|
-
bridge.Connect(contentIsland);
|
|
139
|
-
bridge.Show();
|
|
140
|
-
|
|
141
|
-
// set ScaleFactor
|
|
142
|
-
ScaleFactor(m_hwnd);
|
|
143
|
-
|
|
144
|
-
// set layout contraints
|
|
145
|
-
winrt::Microsoft::ReactNative::LayoutConstraints constraints;
|
|
146
|
-
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
|
|
147
|
-
|
|
148
|
-
RECT rc;
|
|
149
|
-
GetClientRect(m_parentHwnd, &rc);
|
|
150
|
-
// Maximum size is set to size of parent hwnd
|
|
151
|
-
constraints.MaximumSize = {(rc.right - rc.left) * ScaleFactor(m_hwnd), (rc.bottom - rc.top) / ScaleFactor(m_hwnd)};
|
|
152
|
-
constraints.MinimumSize = {MODAL_MIN_WIDTH * ScaleFactor(m_hwnd), MODAL_MIN_HEIGHT * ScaleFactor(m_hwnd)};
|
|
153
|
-
m_reactNativeIsland.Arrange(constraints, {0, 0});
|
|
154
|
-
bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
|
|
155
|
-
|
|
156
|
-
spunk.detach();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
void WindowsModalHostComponentView::ShowOnUIThread() {
|
|
160
|
-
if (m_hwnd && !IsWindowVisible(m_hwnd)) {
|
|
161
|
-
ShowWindow(m_hwnd, SW_NORMAL);
|
|
162
|
-
BringWindowToTop(m_hwnd);
|
|
163
|
-
SetFocus(m_hwnd);
|
|
70
|
+
void UpdateProps(
|
|
71
|
+
const winrt::Microsoft::ReactNative::ComponentView &view,
|
|
72
|
+
const winrt::com_ptr<::Microsoft::ReactNativeSpecs::ModalHostViewProps> &newProps,
|
|
73
|
+
const winrt::com_ptr<::Microsoft::ReactNativeSpecs::ModalHostViewProps> &oldProps) noexcept override {
|
|
74
|
+
if (!oldProps || newProps->visible != oldProps->visible) {
|
|
75
|
+
if (newProps->visible.value_or(true)) {
|
|
76
|
+
// We do not immediately show the window, since we want to resize/position
|
|
77
|
+
// the window based on the layout metrics before we show it
|
|
78
|
+
m_showQueued = true;
|
|
79
|
+
} else {
|
|
80
|
+
CloseWindow();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
::Microsoft::ReactNativeSpecs::BaseModalHostView<ModalHostView>::UpdateProps(view, newProps, oldProps);
|
|
84
|
+
}
|
|
164
85
|
|
|
165
|
-
|
|
166
|
-
|
|
86
|
+
void UpdateState(
|
|
87
|
+
const winrt::Microsoft::ReactNative::ComponentView & /*view*/,
|
|
88
|
+
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept override {
|
|
89
|
+
m_state = newState;
|
|
90
|
+
}
|
|
167
91
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
92
|
+
void MountChildComponentView(
|
|
93
|
+
const winrt::Microsoft::ReactNative::ComponentView & /*view*/,
|
|
94
|
+
const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept override {
|
|
95
|
+
AdjustWindowSize(args.Child().LayoutMetrics());
|
|
96
|
+
assert(!m_childLayoutMetricsToken);
|
|
97
|
+
m_childLayoutMetricsToken = args.Child().LayoutMetricsChanged(
|
|
98
|
+
[wkThis = get_weak()](
|
|
99
|
+
auto &sender, const winrt::Microsoft::ReactNative::LayoutMetricsChangedArgs &layoutMetricsChangedArgs) {
|
|
100
|
+
if (auto strongThis = wkThis.get()) {
|
|
101
|
+
strongThis->AdjustWindowSize(layoutMetricsChangedArgs.NewLayoutMetrics());
|
|
102
|
+
}
|
|
103
|
+
});
|
|
172
104
|
}
|
|
173
|
-
}
|
|
174
105
|
|
|
175
|
-
void
|
|
176
|
-
|
|
177
|
-
|
|
106
|
+
void UnmountChildComponentView(
|
|
107
|
+
const winrt::Microsoft::ReactNative::ComponentView & /*view*/,
|
|
108
|
+
const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept override {
|
|
109
|
+
assert(m_childLayoutMetricsToken);
|
|
110
|
+
args.Child().LayoutMetricsChanged(m_childLayoutMetricsToken);
|
|
111
|
+
m_childLayoutMetricsToken.value = 0;
|
|
178
112
|
}
|
|
179
113
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
114
|
+
void FinalizeUpdate(
|
|
115
|
+
const winrt::Microsoft::ReactNative::ComponentView &view,
|
|
116
|
+
winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept override {
|
|
117
|
+
if (m_showQueued) {
|
|
118
|
+
ShowOnUIThread(view);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
184
121
|
|
|
185
|
-
|
|
186
|
-
|
|
122
|
+
private:
|
|
123
|
+
void OnMounted(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
|
|
124
|
+
m_mounted = true;
|
|
187
125
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
|
|
192
|
-
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
|
|
193
|
-
host.InstanceSettings().Properties(), m_prevWindowID);
|
|
194
|
-
m_prevWindowID = 0;
|
|
126
|
+
if (m_showQueued) {
|
|
127
|
+
ShowOnUIThread(view);
|
|
128
|
+
}
|
|
195
129
|
}
|
|
196
|
-
}
|
|
197
130
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept {
|
|
201
|
-
auto data = reinterpret_cast<::IUnknown *>(GetProp(
|
|
202
|
-
hwnd,
|
|
203
|
-
CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make)
|
|
204
|
-
winrt::Microsoft::ReactNative::CompositionHwndHost host{nullptr};
|
|
205
|
-
|
|
206
|
-
if (data) {
|
|
207
|
-
winrt::check_hresult(data->QueryInterface(
|
|
208
|
-
winrt::guid_of<winrt::Microsoft::ReactNative::CompositionHwndHost>(),
|
|
209
|
-
winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host
|
|
210
|
-
auto result = static_cast<LRESULT>(host.TranslateMessage(message, wparam, lparam));
|
|
211
|
-
if (result) {
|
|
212
|
-
return result;
|
|
213
|
-
}
|
|
131
|
+
void OnUnmounted(const winrt::Microsoft::ReactNative::ComponentView & /*view*/) noexcept {
|
|
132
|
+
m_mounted = false;
|
|
214
133
|
}
|
|
215
134
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
135
|
+
void AdjustWindowSize(const winrt::Microsoft::ReactNative::LayoutMetrics &layoutMetrics) noexcept {
|
|
136
|
+
#ifdef USE_EXPERIMENTAL_WINUI3
|
|
137
|
+
if (!m_popUp) {
|
|
138
|
+
#else
|
|
139
|
+
if (!m_window) {
|
|
140
|
+
#endif
|
|
141
|
+
return;
|
|
222
142
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
return 0;
|
|
143
|
+
|
|
144
|
+
if (layoutMetrics.Frame.Width == 0 && layoutMetrics.Frame.Height == 0) {
|
|
145
|
+
return;
|
|
227
146
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
147
|
+
|
|
148
|
+
// get Modal's position based on parent
|
|
149
|
+
RECT parentRC;
|
|
150
|
+
GetWindowRect(m_parentHwnd, &parentRC);
|
|
151
|
+
int32_t xCor = static_cast<int32_t>(
|
|
152
|
+
(parentRC.left + parentRC.right - layoutMetrics.Frame.Width * layoutMetrics.PointScaleFactor) / 2);
|
|
153
|
+
int32_t yCor = static_cast<int32_t>(
|
|
154
|
+
(parentRC.top + parentRC.bottom - layoutMetrics.Frame.Height * layoutMetrics.PointScaleFactor) / 2);
|
|
155
|
+
|
|
156
|
+
#ifdef USE_EXPERIMENTAL_WINUI3
|
|
157
|
+
winrt::Windows::Graphics::RectInt32 rect2{
|
|
158
|
+
(int)xCor,
|
|
159
|
+
(int)yCor,
|
|
160
|
+
static_cast<int32_t>(layoutMetrics.Frame.Width * (layoutMetrics.PointScaleFactor)),
|
|
161
|
+
static_cast<int32_t>(layoutMetrics.Frame.Height * (layoutMetrics.PointScaleFactor))};
|
|
162
|
+
m_popUp.MoveAndResize(rect2);
|
|
163
|
+
#else
|
|
164
|
+
// Fix for https://github.com/microsoft/microsoft-ui-xaml/issues/9529
|
|
165
|
+
auto titleBarHeight = m_window.TitleBar().Height();
|
|
166
|
+
|
|
167
|
+
// Adjust window position and size
|
|
168
|
+
m_window.ResizeClient(
|
|
169
|
+
{static_cast<int32_t>(layoutMetrics.Frame.Width * (layoutMetrics.PointScaleFactor)),
|
|
170
|
+
static_cast<int32_t>(layoutMetrics.Frame.Height * (layoutMetrics.PointScaleFactor)) - titleBarHeight});
|
|
171
|
+
m_window.Move({xCor, yCor});
|
|
172
|
+
#endif
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
void ShowOnUIThread(const winrt::Microsoft::ReactNative::ComponentView &view) {
|
|
176
|
+
if (!m_mounted)
|
|
177
|
+
return;
|
|
178
|
+
|
|
179
|
+
m_showQueued = false;
|
|
180
|
+
EnsureModalCreated(view);
|
|
181
|
+
|
|
182
|
+
if (m_window && !m_window.IsVisible()) {
|
|
183
|
+
m_bridge.Enable();
|
|
184
|
+
m_window.Show(true);
|
|
185
|
+
|
|
186
|
+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge);
|
|
187
|
+
auto result = navHost.NavigateFocus(winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(
|
|
188
|
+
winrt::Microsoft::UI::Input::FocusNavigationReason::First));
|
|
189
|
+
|
|
190
|
+
// dispatch onShow event
|
|
191
|
+
if (auto eventEmitter = EventEmitter()) {
|
|
192
|
+
::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnShow eventArgs;
|
|
193
|
+
eventEmitter->onShow(eventArgs);
|
|
232
194
|
}
|
|
233
|
-
SetProp(hwnd, CompHostProperty, nullptr);
|
|
234
|
-
break;
|
|
235
195
|
}
|
|
236
196
|
}
|
|
237
197
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// Creates and Register a new window class
|
|
242
|
-
void WindowsModalHostComponentView::RegisterWndClass() noexcept {
|
|
243
|
-
static bool registered = false;
|
|
244
|
-
if (registered) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
HINSTANCE hInstance =
|
|
249
|
-
GetModuleHandle(NULL); // returns a handle to the file used to create the calling process (.exe file)
|
|
250
|
-
|
|
251
|
-
WNDCLASSEX wcex = {}; // contains window class information
|
|
252
|
-
wcex.cbSize = sizeof(wcex); // size of windows class (bytes)
|
|
253
|
-
wcex.style = CS_HREDRAW | CS_VREDRAW; // class style (redraw window on size adjustment)
|
|
254
|
-
wcex.lpfnWndProc = &ModalBoxWndProc; // pointer to windows procedure
|
|
255
|
-
wcex.cbClsExtra = DLGWINDOWEXTRA; // extra bytes to allocate
|
|
256
|
-
wcex.cbWndExtra =
|
|
257
|
-
sizeof(winrt::impl::abi<winrt::Microsoft::ReactNative::ICompositionHwndHost>::type *); // extra bytes to allocate
|
|
258
|
-
wcex.hInstance = hInstance;
|
|
259
|
-
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); // handle to class cursor
|
|
260
|
-
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // background color
|
|
261
|
-
wcex.lpszClassName = c_modalWindowClassName; // specify resource name
|
|
262
|
-
ATOM classId = RegisterClassEx(&wcex); // register new windows class
|
|
263
|
-
WINRT_VERIFY(classId); // 0 = fail
|
|
264
|
-
winrt::check_win32(!classId);
|
|
265
|
-
|
|
266
|
-
registered = true;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
|
|
270
|
-
WindowsModalHostComponentView::VisualToMountChildrenInto() noexcept {
|
|
271
|
-
return m_reactNativeIsland
|
|
272
|
-
.as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>()
|
|
273
|
-
.InternalRootVisual();
|
|
274
|
-
}
|
|
198
|
+
void CloseWindow() noexcept {
|
|
199
|
+
// enable input to parent before closing the modal window, so focus can return back to the parent window
|
|
200
|
+
EnableWindow(m_parentHwnd, true);
|
|
275
201
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
|
|
280
|
-
uint32_t index) noexcept {
|
|
281
|
-
EnsureModalCreated();
|
|
282
|
-
base_type::MountChildComponentView(childComponentView, index);
|
|
283
|
-
}
|
|
202
|
+
if (m_window) {
|
|
203
|
+
m_window.Hide();
|
|
204
|
+
}
|
|
284
205
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
206
|
+
// dispatch onDismiss event
|
|
207
|
+
if (auto eventEmitter = EventEmitter()) {
|
|
208
|
+
::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnDismiss eventArgs;
|
|
209
|
+
eventEmitter->onDismiss(eventArgs);
|
|
210
|
+
}
|
|
290
211
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
AdjustWindowSize();
|
|
298
|
-
ShowOnUIThread();
|
|
299
|
-
}
|
|
300
|
-
}
|
|
212
|
+
// reset the topWindowID
|
|
213
|
+
if (m_prevWindowID) {
|
|
214
|
+
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
|
|
215
|
+
m_reactContext.Properties().Handle(), m_prevWindowID);
|
|
216
|
+
m_prevWindowID = 0;
|
|
217
|
+
}
|
|
301
218
|
|
|
302
|
-
|
|
303
|
-
if (m_layoutMetrics.overflowInset.right == 0 && m_layoutMetrics.overflowInset.bottom == 0) {
|
|
304
|
-
return;
|
|
219
|
+
m_bridge.Disable();
|
|
305
220
|
}
|
|
306
221
|
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
RECT rect = {0, 0, (int)xPos, (int)yPos};
|
|
222
|
+
// creates a new modal window
|
|
223
|
+
void EnsureModalCreated(const winrt::Microsoft::ReactNative::ComponentView &view) {
|
|
224
|
+
if (m_window) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
313
227
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
228
|
+
// get the root hwnd
|
|
229
|
+
m_prevWindowID =
|
|
230
|
+
winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(view.ReactContext().Properties());
|
|
317
231
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
m_layoutMetrics.overflowInset.right = 0;
|
|
321
|
-
m_layoutMetrics.overflowInset.bottom = 0;
|
|
232
|
+
m_parentHwnd =
|
|
233
|
+
view.as<::Microsoft::ReactNative::Composition::Experimental::IComponentViewInterop>()->GetHwndForParenting();
|
|
322
234
|
|
|
323
|
-
|
|
324
|
-
RECT parentRC;
|
|
325
|
-
GetWindowRect(m_parentHwnd, &parentRC);
|
|
326
|
-
float xCor = (parentRC.left + parentRC.right - m_layoutMetrics.frame.size.width) / 2; // midpointx - width / 2
|
|
327
|
-
float yCor = (parentRC.top + parentRC.bottom - m_layoutMetrics.frame.size.height) / 2; // midpointy - height / 2
|
|
235
|
+
auto portal = view.as<winrt::Microsoft::ReactNative::Composition::PortalComponentView>();
|
|
328
236
|
|
|
329
|
-
|
|
330
|
-
|
|
237
|
+
#ifdef USE_EXPERIMENTAL_WINUI3
|
|
238
|
+
m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
|
|
239
|
+
view.Parent().as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Compositor(),
|
|
240
|
+
winrt::Microsoft::UI::GetWindowIdFromWindow(m_parentHwnd));
|
|
241
|
+
m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal(portal);
|
|
242
|
+
auto contentIsland = m_reactNativeIsland.Island();
|
|
331
243
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
->NotifySizeChanged();
|
|
335
|
-
};
|
|
244
|
+
m_popUp = m_bridge.TryCreatePopupSiteBridge();
|
|
245
|
+
m_popUp.Connect(contentIsland);
|
|
336
246
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
247
|
+
// set the top-level windows as the new hwnd
|
|
248
|
+
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
|
|
249
|
+
view.ReactContext().Properties(),
|
|
250
|
+
reinterpret_cast<uint64_t>(winrt::Microsoft::UI::GetWindowFromWindowId(m_popUp.WindowId())));
|
|
251
|
+
|
|
252
|
+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(
|
|
253
|
+
m_popUp.as<winrt::Microsoft::UI::Content::IContentSiteBridge>());
|
|
254
|
+
m_departFocusToken = navHost.DepartFocusRequested(
|
|
255
|
+
[wkView = winrt::make_weak(view)](
|
|
256
|
+
const auto &sender, const winrt::Microsoft::UI::Input::FocusNavigationRequestEventArgs &args) {
|
|
257
|
+
if (auto strongView = wkView.get()) {
|
|
258
|
+
TrySetFocus(strongView.Parent());
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
#else
|
|
263
|
+
auto presenter = winrt::Microsoft::UI::Windowing::OverlappedPresenter::CreateForDialog();
|
|
264
|
+
presenter.SetBorderAndTitleBar(true, false);
|
|
265
|
+
presenter.IsModal(true);
|
|
266
|
+
|
|
267
|
+
m_window = winrt::Microsoft::UI::Windowing::AppWindow::Create(
|
|
268
|
+
presenter, winrt::Microsoft::UI::GetWindowIdFromWindow(m_parentHwnd));
|
|
269
|
+
|
|
270
|
+
// set the top-level windows as the new hwnd
|
|
271
|
+
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
|
|
272
|
+
view.ReactContext().Properties(),
|
|
273
|
+
reinterpret_cast<uint64_t>(winrt::Microsoft::UI::GetWindowFromWindowId(m_window.Id())));
|
|
274
|
+
|
|
275
|
+
// create a react native island - code taken from CompositionHwndHost
|
|
276
|
+
m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
|
|
277
|
+
view.Parent().as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Compositor(), m_window.Id());
|
|
278
|
+
m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal(portal);
|
|
279
|
+
auto contentIsland = m_reactNativeIsland.Island();
|
|
280
|
+
|
|
281
|
+
auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge);
|
|
282
|
+
m_departFocusToken = navHost.DepartFocusRequested(
|
|
283
|
+
[wkView = winrt::make_weak(view)](
|
|
284
|
+
const auto &sender, const winrt::Microsoft::UI::Input::FocusNavigationRequestEventArgs &args) {
|
|
285
|
+
if (auto strongView = wkView.get()) {
|
|
286
|
+
TrySetFocus(strongView.Parent());
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
m_bridge.Connect(contentIsland);
|
|
290
|
+
|
|
291
|
+
#endif
|
|
292
|
+
|
|
293
|
+
m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
|
|
294
|
+
|
|
295
|
+
m_islandStateChangedToken =
|
|
296
|
+
contentIsland.StateChanged([weakThis = get_weak()](
|
|
297
|
+
winrt::Microsoft::UI::Content::ContentIsland const &island,
|
|
298
|
+
winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs const &args) {
|
|
299
|
+
if (auto pThis = weakThis.get()) {
|
|
300
|
+
if (args.DidRasterizationScaleChange() || args.DidLayoutDirectionChange()) {
|
|
301
|
+
pThis->UpdateConstraints();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
UpdateConstraints();
|
|
307
|
+
|
|
308
|
+
if (portal.ContentRoot().Children().Size()) {
|
|
309
|
+
AdjustWindowSize(portal.ContentRoot().Children().GetAt(0).LayoutMetrics());
|
|
310
|
+
}
|
|
311
|
+
m_bridge.Show();
|
|
346
312
|
}
|
|
347
|
-
base_type::updateProps(props, oldProps);
|
|
348
|
-
}
|
|
349
313
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
314
|
+
void UpdateConstraints() noexcept {
|
|
315
|
+
auto displayArea = winrt::Microsoft::UI::Windowing::DisplayArea::GetFromDisplayId(
|
|
316
|
+
m_bridge.SiteView().EnvironmentView().DisplayId());
|
|
317
|
+
auto workArea = displayArea.WorkArea();
|
|
318
|
+
|
|
319
|
+
float scale = m_reactNativeIsland.Island().RasterizationScale();
|
|
320
|
+
|
|
321
|
+
winrt::Microsoft::ReactNative::LayoutConstraints constraints;
|
|
322
|
+
constraints.MinimumSize = {0, 0};
|
|
323
|
+
// Constrain the size of the modal to 90% of the screen size
|
|
324
|
+
constraints.MaximumSize = {
|
|
325
|
+
static_cast<float>((workArea.Width / scale) * 0.9), static_cast<float>((workArea.Height / scale) * 0.9)};
|
|
326
|
+
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
|
|
327
|
+
|
|
328
|
+
auto layoutDirection = m_reactNativeIsland.Island().LayoutDirection();
|
|
329
|
+
if (layoutDirection == winrt::Microsoft::UI::Content::ContentLayoutDirection::LeftToRight)
|
|
330
|
+
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight;
|
|
331
|
+
else if (layoutDirection == winrt::Microsoft::UI::Content::ContentLayoutDirection::RightToLeft)
|
|
332
|
+
constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft;
|
|
333
|
+
|
|
334
|
+
// By setting a custom contraint here the behavior of the modal slightly changes.
|
|
335
|
+
// When no constraint is set (maxSize is std::numeric_limits<Float>::infinity()), yoga will layout the content to a
|
|
336
|
+
// desired size If we provide a specific max size, then contents with a flex:1 will expand to fill that size. We
|
|
337
|
+
// might want to provide a windows specific property to control this behavior.
|
|
338
|
+
m_state.UpdateState(winrt::make<ModalHostState>(constraints, m_reactNativeIsland.Island().RasterizationScale()));
|
|
370
339
|
}
|
|
371
340
|
|
|
372
|
-
|
|
373
|
-
|
|
341
|
+
static void TrySetFocus(const winrt::Microsoft::ReactNative::ComponentView &view) {
|
|
342
|
+
auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(
|
|
343
|
+
view.as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Root().ReactNativeIsland().Island());
|
|
344
|
+
focusController.TrySetFocus();
|
|
345
|
+
}
|
|
374
346
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
347
|
+
ReactContext m_reactContext{nullptr};
|
|
348
|
+
HWND m_parentHwnd{nullptr};
|
|
349
|
+
winrt::Microsoft::UI::Windowing::AppWindow m_window{nullptr};
|
|
350
|
+
uint64_t m_prevWindowID;
|
|
351
|
+
bool m_showTitleBar{false};
|
|
352
|
+
bool m_showQueued{false};
|
|
353
|
+
bool m_mounted{false};
|
|
354
|
+
winrt::event_token m_islandStateChangedToken;
|
|
355
|
+
winrt::Microsoft::UI::Input::InputFocusNavigationHost::DepartFocusRequested_revoker m_departFocusRevoker;
|
|
356
|
+
winrt::event_token m_departFocusToken;
|
|
357
|
+
winrt::event_token m_childLayoutMetricsToken;
|
|
358
|
+
winrt::Microsoft::ReactNative::IComponentState m_state{nullptr};
|
|
359
|
+
winrt::Microsoft::UI::Content::DesktopChildSiteBridge m_bridge{nullptr};
|
|
360
|
+
winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland{nullptr};
|
|
361
|
+
};
|
|
378
362
|
|
|
379
|
-
|
|
380
|
-
|
|
363
|
+
void RegisterWindowsModalHostNativeComponent(
|
|
364
|
+
winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept {
|
|
365
|
+
::Microsoft::ReactNativeSpecs::RegisterModalHostViewNativeComponent<ModalHostView>(
|
|
366
|
+
packageBuilder,
|
|
367
|
+
[](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) {
|
|
368
|
+
builder.SetPortalComponentViewInitializer(
|
|
369
|
+
[](const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portalComponentView) noexcept {
|
|
370
|
+
auto userData = winrt::make_self<ModalHostView>();
|
|
371
|
+
userData->InitializePortalViewComponent(portalComponentView);
|
|
372
|
+
portalComponentView.UserData(*userData);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
381
375
|
}
|
|
382
376
|
|
|
383
377
|
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|