react-native-windows 0.74.5 → 0.74.7
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/Microsoft.ReactNative/ComponentView.idl +26 -0
- package/Microsoft.ReactNative/CompositionComponentView.idl +2 -0
- package/Microsoft.ReactNative/CompositionRootView.idl +13 -3
- package/Microsoft.ReactNative/Fabric/ComponentView.cpp +83 -12
- package/Microsoft.ReactNative/Fabric/ComponentView.h +33 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +6 -6
- package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +3 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp +131 -79
- package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h +20 -13
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +37 -23
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +8 -2
- package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +152 -0
- package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +85 -0
- package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +54 -40
- package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +9 -1
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +7 -5
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +2 -2
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +6 -12
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +1 -0
- package/Microsoft.ReactNative/FocusManager.idl +22 -0
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/Shared/Shared.vcxitems +6 -5
- package/package.json +1 -1
- package/templates/cpp-app/windows/MyApp/MyApp.cpp +3 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp +0 -149
- package/Microsoft.ReactNative/Views/ICompositionRootView.h +0 -18
|
@@ -67,6 +67,26 @@ namespace Microsoft.ReactNative
|
|
|
67
67
|
IReactContext ReactContext { get;};
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
[experimental]
|
|
71
|
+
[webhosthidden]
|
|
72
|
+
runtimeclass LosingFocusEventArgs : Microsoft.ReactNative.Composition.Input.RoutedEventArgs {
|
|
73
|
+
Microsoft.ReactNative.ComponentView NewFocusedComponent { get; };
|
|
74
|
+
Microsoft.ReactNative.ComponentView OldFocusedComponent { get; };
|
|
75
|
+
|
|
76
|
+
void TryCancel();
|
|
77
|
+
void TrySetNewFocusedComponent(Microsoft.ReactNative.ComponentView component);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
[experimental]
|
|
81
|
+
[webhosthidden]
|
|
82
|
+
runtimeclass GettingFocusEventArgs : Microsoft.ReactNative.Composition.Input.RoutedEventArgs {
|
|
83
|
+
Microsoft.ReactNative.ComponentView NewFocusedComponent { get; };
|
|
84
|
+
Microsoft.ReactNative.ComponentView OldFocusedComponent { get; };
|
|
85
|
+
|
|
86
|
+
void TryCancel();
|
|
87
|
+
void TrySetNewFocusedComponent(Microsoft.ReactNative.ComponentView component);
|
|
88
|
+
};
|
|
89
|
+
|
|
70
90
|
[experimental]
|
|
71
91
|
[webhosthidden]
|
|
72
92
|
unsealed runtimeclass ComponentView {
|
|
@@ -101,6 +121,12 @@ namespace Microsoft.ReactNative
|
|
|
101
121
|
overridable void OnPointerExited(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args);
|
|
102
122
|
overridable void OnPointerCaptureLost();
|
|
103
123
|
|
|
124
|
+
Boolean TryFocus();
|
|
125
|
+
|
|
126
|
+
event Windows.Foundation.EventHandler<LosingFocusEventArgs> LosingFocus;
|
|
127
|
+
event Windows.Foundation.EventHandler<GettingFocusEventArgs> GettingFocus;
|
|
128
|
+
event Windows.Foundation.EventHandler<Microsoft.ReactNative.Composition.Input.RoutedEventArgs> LostFocus;
|
|
129
|
+
event Windows.Foundation.EventHandler<Microsoft.ReactNative.Composition.Input.RoutedEventArgs> GotFocus;
|
|
104
130
|
};
|
|
105
131
|
|
|
106
132
|
} // namespace Microsoft.ReactNative
|
|
@@ -48,6 +48,7 @@ namespace Microsoft.ReactNative.Composition
|
|
|
48
48
|
ComponentView(CreateCompositionComponentViewArgs args);
|
|
49
49
|
|
|
50
50
|
Microsoft.UI.Composition.Compositor Compositor { get; };
|
|
51
|
+
RootComponentView Root { get; };
|
|
51
52
|
Theme Theme;
|
|
52
53
|
overridable void OnThemeChanged();
|
|
53
54
|
Boolean CapturePointer(Microsoft.ReactNative.Composition.Input.Pointer pointer);
|
|
@@ -88,6 +89,7 @@ namespace Microsoft.ReactNative.Composition
|
|
|
88
89
|
[webhosthidden]
|
|
89
90
|
[default_interface]
|
|
90
91
|
unsealed runtimeclass RootComponentView : ViewComponentView {
|
|
92
|
+
Microsoft.ReactNative.ComponentView GetFocusedComponent();
|
|
91
93
|
};
|
|
92
94
|
|
|
93
95
|
[experimental]
|
|
@@ -5,6 +5,7 @@ import "IJSValueWriter.idl";
|
|
|
5
5
|
import "ReactCoreInjection.idl";
|
|
6
6
|
import "ReactNativeHost.idl";
|
|
7
7
|
import "Theme.idl";
|
|
8
|
+
import "IReactViewComponentBuilder.idl";
|
|
8
9
|
#include "NamespaceRedirect.h"
|
|
9
10
|
#include "DocString.h"
|
|
10
11
|
|
|
@@ -61,6 +62,13 @@ namespace Microsoft.ReactNative
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
[default_interface]
|
|
66
|
+
[webhosthidden]
|
|
67
|
+
[experimental]
|
|
68
|
+
runtimeclass RootViewSizeChangedEventArgs {
|
|
69
|
+
Windows.Foundation.Size Size { get; };
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
[default_interface]
|
|
65
73
|
[webhosthidden]
|
|
66
74
|
[experimental]
|
|
@@ -82,7 +90,7 @@ namespace Microsoft.ReactNative
|
|
|
82
90
|
DOC_STRING("The RootVisual associated with the @CompositionRootView. It must be set to show any React UI elements.")
|
|
83
91
|
Microsoft.UI.Composition.Visual RootVisual { get; };
|
|
84
92
|
|
|
85
|
-
Windows.Foundation.Size Size {get;
|
|
93
|
+
Windows.Foundation.Size Size { get; };
|
|
86
94
|
|
|
87
95
|
DOC_STRING("ScaleFactor for this windows (DPI/96)")
|
|
88
96
|
Single ScaleFactor {get; set;};
|
|
@@ -90,8 +98,8 @@ namespace Microsoft.ReactNative
|
|
|
90
98
|
DOC_STRING("Move focus to this @CompositionRootView")
|
|
91
99
|
FocusNavigationResult NavigateFocus(FocusNavigationRequest request);
|
|
92
100
|
|
|
93
|
-
Windows.Foundation.Size Measure(Windows.Foundation.
|
|
94
|
-
|
|
101
|
+
Windows.Foundation.Size Measure(LayoutConstraints layoutConstraints, Windows.Foundation.Point viewportOffset);
|
|
102
|
+
void Arrange(LayoutConstraints layoutConstraints, Windows.Foundation.Point viewportOffset);
|
|
95
103
|
|
|
96
104
|
Object GetUiaProvider();
|
|
97
105
|
|
|
@@ -104,6 +112,8 @@ namespace Microsoft.ReactNative
|
|
|
104
112
|
#ifdef USE_WINUI3
|
|
105
113
|
Microsoft.UI.Content.ContentIsland Island { get; };
|
|
106
114
|
#endif
|
|
115
|
+
|
|
116
|
+
event Windows.Foundation.EventHandler<RootViewSizeChangedEventArgs> SizeChanged;
|
|
107
117
|
}
|
|
108
118
|
|
|
109
119
|
} // namespace Microsoft.ReactNative
|
|
@@ -143,19 +143,16 @@ ComponentView::rootComponentView() noexcept {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
void ComponentView::parent(const winrt::Microsoft::ReactNative::ComponentView &parent) noexcept {
|
|
146
|
-
if (!parent) {
|
|
147
|
-
auto root = rootComponentView();
|
|
148
|
-
winrt::Microsoft::ReactNative::ComponentView view{nullptr};
|
|
149
|
-
winrt::check_hresult(
|
|
150
|
-
QueryInterface(winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(view)));
|
|
151
|
-
if (root && root->GetFocusedComponent() == view) {
|
|
152
|
-
root->SetFocusedComponent(nullptr); // TODO need move focus logic - where should focus go?
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
146
|
if (m_parent != parent) {
|
|
147
|
+
auto oldRootView = rootComponentView();
|
|
157
148
|
m_rootView = nullptr;
|
|
149
|
+
auto oldParent = m_parent;
|
|
158
150
|
m_parent = parent;
|
|
151
|
+
if (!parent) {
|
|
152
|
+
if (oldRootView && oldRootView->GetFocusedComponent() == *this) {
|
|
153
|
+
oldRootView->TrySetFocusedComponent(oldParent);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
159
156
|
if (parent) {
|
|
160
157
|
theme(winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(parent)->theme());
|
|
161
158
|
}
|
|
@@ -220,9 +217,83 @@ facebook::react::Point ComponentView::getClientOffset() const noexcept {
|
|
|
220
217
|
return {};
|
|
221
218
|
}
|
|
222
219
|
|
|
223
|
-
void ComponentView::
|
|
220
|
+
void ComponentView::onLostFocus(
|
|
221
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
222
|
+
m_lostFocusEvent(*this, args);
|
|
223
|
+
if (m_parent) {
|
|
224
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_parent)->onLostFocus(args);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void ComponentView::onGotFocus(
|
|
229
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
230
|
+
m_gotFocusEvent(*this, args);
|
|
231
|
+
if (m_parent) {
|
|
232
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_parent)->onGotFocus(args);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
void ComponentView::onLosingFocus(const winrt::Microsoft::ReactNative::LosingFocusEventArgs &args) noexcept {
|
|
237
|
+
m_losingFocusEvent(*this, args);
|
|
238
|
+
if (m_parent) {
|
|
239
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_parent)->onLosingFocus(args);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
void ComponentView::onGettingFocus(const winrt::Microsoft::ReactNative::GettingFocusEventArgs &args) noexcept {
|
|
244
|
+
m_gettingFocusEvent(*this, args);
|
|
245
|
+
if (m_parent) {
|
|
246
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_parent)->onGettingFocus(args);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
224
249
|
|
|
225
|
-
|
|
250
|
+
winrt::event_token ComponentView::LosingFocus(
|
|
251
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::LosingFocusEventArgs> const
|
|
252
|
+
&handler) noexcept {
|
|
253
|
+
return m_losingFocusEvent.add(handler);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
void ComponentView::LosingFocus(winrt::event_token const &token) noexcept {
|
|
257
|
+
m_losingFocusEvent.remove(token);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
winrt::event_token ComponentView::GettingFocus(
|
|
261
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::GettingFocusEventArgs> const
|
|
262
|
+
&handler) noexcept {
|
|
263
|
+
return m_gettingFocusEvent.add(handler);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
void ComponentView::GettingFocus(winrt::event_token const &token) noexcept {
|
|
267
|
+
m_gettingFocusEvent.remove(token);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
winrt::event_token ComponentView::LostFocus(
|
|
271
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> const
|
|
272
|
+
&handler) noexcept {
|
|
273
|
+
return m_lostFocusEvent.add(handler);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
void ComponentView::LostFocus(winrt::event_token const &token) noexcept {
|
|
277
|
+
m_lostFocusEvent.remove(token);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
winrt::event_token ComponentView::GotFocus(
|
|
281
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> const
|
|
282
|
+
&handler) noexcept {
|
|
283
|
+
return m_gotFocusEvent.add(handler);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
void ComponentView::GotFocus(winrt::event_token const &token) noexcept {
|
|
287
|
+
m_gotFocusEvent.remove(token);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
bool ComponentView::TryFocus() noexcept {
|
|
291
|
+
if (auto root = rootComponentView()) {
|
|
292
|
+
return root->TrySetFocusedComponent(*get_strong());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
226
297
|
|
|
227
298
|
void ComponentView::OnPointerEntered(
|
|
228
299
|
const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {}
|
|
@@ -87,8 +87,29 @@ struct ComponentView : public ComponentViewT<ComponentView> {
|
|
|
87
87
|
virtual RECT getClientRect() const noexcept;
|
|
88
88
|
// The offset from this elements parent to its children (accounts for things like scroll position)
|
|
89
89
|
virtual facebook::react::Point getClientOffset() const noexcept;
|
|
90
|
-
virtual void
|
|
91
|
-
virtual void
|
|
90
|
+
virtual void onLosingFocus(const winrt::Microsoft::ReactNative::LosingFocusEventArgs &args) noexcept;
|
|
91
|
+
virtual void onGettingFocus(const winrt::Microsoft::ReactNative::GettingFocusEventArgs &args) noexcept;
|
|
92
|
+
virtual void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
|
|
93
|
+
virtual void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
|
|
94
|
+
|
|
95
|
+
winrt::event_token LosingFocus(
|
|
96
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::LosingFocusEventArgs> const
|
|
97
|
+
&handler) noexcept;
|
|
98
|
+
void LosingFocus(winrt::event_token const &token) noexcept;
|
|
99
|
+
winrt::event_token GettingFocus(
|
|
100
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::GettingFocusEventArgs> const
|
|
101
|
+
&handler) noexcept;
|
|
102
|
+
void GettingFocus(winrt::event_token const &token) noexcept;
|
|
103
|
+
winrt::event_token LostFocus(
|
|
104
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> const
|
|
105
|
+
&handler) noexcept;
|
|
106
|
+
void LostFocus(winrt::event_token const &token) noexcept;
|
|
107
|
+
winrt::event_token GotFocus(
|
|
108
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> const
|
|
109
|
+
&handler) noexcept;
|
|
110
|
+
void GotFocus(winrt::event_token const &token) noexcept;
|
|
111
|
+
|
|
112
|
+
bool TryFocus() noexcept;
|
|
92
113
|
|
|
93
114
|
virtual bool focusable() const noexcept;
|
|
94
115
|
virtual facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept;
|
|
@@ -158,6 +179,16 @@ struct ComponentView : public ComponentViewT<ComponentView> {
|
|
|
158
179
|
winrt::Microsoft::ReactNative::ComponentView m_parent{nullptr};
|
|
159
180
|
winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::ReactNative::ComponentView> m_children{
|
|
160
181
|
winrt::single_threaded_vector<winrt::Microsoft::ReactNative::ComponentView>()};
|
|
182
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::LosingFocusEventArgs>>
|
|
183
|
+
m_losingFocusEvent;
|
|
184
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::GettingFocusEventArgs>>
|
|
185
|
+
m_gettingFocusEvent;
|
|
186
|
+
winrt::event<
|
|
187
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs>>
|
|
188
|
+
m_lostFocusEvent;
|
|
189
|
+
winrt::event<
|
|
190
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs>>
|
|
191
|
+
m_gotFocusEvent;
|
|
161
192
|
};
|
|
162
193
|
|
|
163
194
|
// Run fn on all nodes of the component view tree starting from this one until fn returns true
|
|
@@ -243,7 +243,7 @@ CompositionEventHandler::CompositionEventHandler(
|
|
|
243
243
|
: static_cast<facebook::react::Tag>(
|
|
244
244
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(
|
|
245
245
|
strongRootView)
|
|
246
|
-
->
|
|
246
|
+
->RootTag()),
|
|
247
247
|
args);
|
|
248
248
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
249
249
|
onKeyDown(keyboardSource, keyArgs);
|
|
@@ -266,7 +266,7 @@ CompositionEventHandler::CompositionEventHandler(
|
|
|
266
266
|
: static_cast<facebook::react::Tag>(
|
|
267
267
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(
|
|
268
268
|
strongRootView)
|
|
269
|
-
->
|
|
269
|
+
->RootTag()),
|
|
270
270
|
args);
|
|
271
271
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
272
272
|
onKeyUp(keyboardSource, keyArgs);
|
|
@@ -290,7 +290,7 @@ CompositionEventHandler::CompositionEventHandler(
|
|
|
290
290
|
: static_cast<facebook::react::Tag>(
|
|
291
291
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(
|
|
292
292
|
strongRootView)
|
|
293
|
-
->
|
|
293
|
+
->RootTag()),
|
|
294
294
|
args);
|
|
295
295
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
296
296
|
onCharacterReceived(keyboardSource, charArgs);
|
|
@@ -323,7 +323,7 @@ CompositionEventHandler::~CompositionEventHandler() {
|
|
|
323
323
|
facebook::react::SurfaceId CompositionEventHandler::SurfaceId() const noexcept {
|
|
324
324
|
if (auto strongRootView = m_wkRootView.get()) {
|
|
325
325
|
return static_cast<facebook::react::SurfaceId>(
|
|
326
|
-
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(strongRootView)->
|
|
326
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(strongRootView)->RootTag());
|
|
327
327
|
}
|
|
328
328
|
return -1;
|
|
329
329
|
}
|
|
@@ -460,7 +460,7 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
460
460
|
: static_cast<facebook::react::Tag>(
|
|
461
461
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(
|
|
462
462
|
strongRootView)
|
|
463
|
-
->
|
|
463
|
+
->RootTag()),
|
|
464
464
|
msg,
|
|
465
465
|
wParam,
|
|
466
466
|
lParam);
|
|
@@ -481,7 +481,7 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
481
481
|
: static_cast<facebook::react::Tag>(
|
|
482
482
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(
|
|
483
483
|
strongRootView)
|
|
484
|
-
->
|
|
484
|
+
->RootTag()),
|
|
485
485
|
msg,
|
|
486
486
|
wParam,
|
|
487
487
|
lParam);
|
|
@@ -101,8 +101,9 @@ void CompositionHwndHost::UpdateSize() noexcept {
|
|
|
101
101
|
static_cast<float>(m_width / ScaleFactor()), static_cast<float>(m_height / ScaleFactor())};
|
|
102
102
|
// Do not relayout when minimized
|
|
103
103
|
if (!IsIconic(m_hwnd)) {
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
winrt::Microsoft::ReactNative::LayoutConstraints constraints;
|
|
105
|
+
constraints.MinimumSize = constraints.MaximumSize = size;
|
|
106
|
+
m_compRootView.Arrange(constraints, {0, 0});
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include "CompositionRootView.h"
|
|
5
5
|
#include "CompositionRootView.g.cpp"
|
|
6
6
|
#include "FocusNavigationRequest.g.cpp"
|
|
7
|
+
#include <RootViewSizeChangedEventArgs.g.h>
|
|
7
8
|
|
|
8
9
|
#include <AutoDraw.h>
|
|
9
10
|
#include <DynamicWriter.h>
|
|
@@ -132,6 +133,12 @@ CompositionRootView::CompositionRootView(const winrt::Microsoft::UI::Composition
|
|
|
132
133
|
#endif
|
|
133
134
|
|
|
134
135
|
CompositionRootView::~CompositionRootView() noexcept {
|
|
136
|
+
#ifdef USE_WINUI3
|
|
137
|
+
if (m_island && m_island.IsConnected()) {
|
|
138
|
+
m_island.AutomationProviderRequested(m_islandAutomationProviderRequestedToken);
|
|
139
|
+
}
|
|
140
|
+
#endif
|
|
141
|
+
|
|
135
142
|
if (m_uiDispatcher) {
|
|
136
143
|
assert(m_uiDispatcher.HasThreadAccess());
|
|
137
144
|
UninitRootView();
|
|
@@ -193,7 +200,7 @@ void CompositionRootView::RemoveRenderedVisual(
|
|
|
193
200
|
|
|
194
201
|
bool CompositionRootView::TrySetFocus() noexcept {
|
|
195
202
|
#ifdef USE_WINUI3
|
|
196
|
-
if (m_island) {
|
|
203
|
+
if (m_island && m_island.IsConnected()) {
|
|
197
204
|
auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(m_island);
|
|
198
205
|
return focusController.TrySetFocus();
|
|
199
206
|
}
|
|
@@ -324,26 +331,6 @@ winrt::IInspectable CompositionRootView::GetUiaProvider() noexcept {
|
|
|
324
331
|
return m_uiaProvider;
|
|
325
332
|
}
|
|
326
333
|
|
|
327
|
-
std::string CompositionRootView::JSComponentName() const noexcept {
|
|
328
|
-
return to_string(m_reactViewOptions.ComponentName());
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
int64_t CompositionRootView::GetActualHeight() const noexcept {
|
|
332
|
-
return static_cast<int64_t>(m_size.Height);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
int64_t CompositionRootView::GetActualWidth() const noexcept {
|
|
336
|
-
return static_cast<int64_t>(m_size.Width);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
int64_t CompositionRootView::GetTag() const noexcept {
|
|
340
|
-
return m_rootTag;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
void CompositionRootView::SetTag(int64_t tag) noexcept {
|
|
344
|
-
m_rootTag = tag;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
334
|
void CompositionRootView::SetWindow(uint64_t hwnd) noexcept {
|
|
348
335
|
m_hwnd = reinterpret_cast<HWND>(hwnd);
|
|
349
336
|
}
|
|
@@ -439,7 +426,7 @@ void CompositionRootView::UninitRootView() noexcept {
|
|
|
439
426
|
|
|
440
427
|
auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
|
|
441
428
|
winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()));
|
|
442
|
-
uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(
|
|
429
|
+
uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(RootTag()));
|
|
443
430
|
|
|
444
431
|
// This is needed to ensure that the unmount JS logic is completed before the the instance is shutdown during
|
|
445
432
|
// instance destruction. Aligns with similar code in ReactInstanceWin::DetachRootView for paper Future: Instead this
|
|
@@ -478,19 +465,82 @@ void CompositionRootView::ShowInstanceLoaded() noexcept {
|
|
|
478
465
|
auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
|
|
479
466
|
winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()));
|
|
480
467
|
|
|
481
|
-
|
|
482
|
-
SetTag(rootTag);
|
|
468
|
+
m_rootTag = ::Microsoft::ReactNative::getNextRootViewTag();
|
|
483
469
|
auto initProps = DynamicWriter::ToDynamic(Mso::Copy(m_reactViewOptions.InitialProps()));
|
|
484
470
|
if (initProps.isNull()) {
|
|
485
471
|
initProps = folly::dynamic::object();
|
|
486
472
|
}
|
|
487
473
|
initProps["concurrentRoot"] = true;
|
|
488
|
-
uiManager->startSurface(
|
|
474
|
+
uiManager->startSurface(
|
|
475
|
+
*this,
|
|
476
|
+
static_cast<facebook::react::SurfaceId>(m_rootTag),
|
|
477
|
+
m_layoutConstraints,
|
|
478
|
+
to_string(m_reactViewOptions.ComponentName()),
|
|
479
|
+
initProps);
|
|
489
480
|
|
|
490
481
|
m_isJSViewAttached = true;
|
|
491
482
|
}
|
|
492
483
|
}
|
|
493
484
|
|
|
485
|
+
facebook::react::AttributedStringBox CreateLoadingAttributedString() noexcept {
|
|
486
|
+
auto attributedString = facebook::react::AttributedString{};
|
|
487
|
+
auto fragment = facebook::react::AttributedString::Fragment{};
|
|
488
|
+
fragment.string = "Loading";
|
|
489
|
+
fragment.textAttributes.fontSize = loadingBarFontSize;
|
|
490
|
+
attributedString.appendFragment(fragment);
|
|
491
|
+
return facebook::react::AttributedStringBox{attributedString};
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
facebook::react::Size MeasureLoading(const facebook::react::LayoutConstraints &layoutConstraints, float scaleFactor) {
|
|
495
|
+
auto attributedStringBox = CreateLoadingAttributedString();
|
|
496
|
+
winrt::com_ptr<::IDWriteTextLayout> textLayout;
|
|
497
|
+
facebook::react::TextLayoutManager::GetTextLayout(
|
|
498
|
+
attributedStringBox, {} /*paragraphAttributes*/, layoutConstraints, textLayout);
|
|
499
|
+
|
|
500
|
+
DWRITE_TEXT_METRICS tm;
|
|
501
|
+
textLayout->GetMetrics(&tm);
|
|
502
|
+
|
|
503
|
+
return layoutConstraints.clamp(
|
|
504
|
+
{loadingActivityHorizontalOffset * scaleFactor + tm.width, loadingBarHeight * scaleFactor});
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
winrt::event_token CompositionRootView::SizeChanged(
|
|
508
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs> const
|
|
509
|
+
&handler) noexcept {
|
|
510
|
+
return m_sizeChangedEvent.add(handler);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
void CompositionRootView::SizeChanged(winrt::event_token const &token) noexcept {
|
|
514
|
+
m_sizeChangedEvent.remove(token);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
struct RootViewSizeChangedEventArgs : RootViewSizeChangedEventArgsT<RootViewSizeChangedEventArgs> {
|
|
518
|
+
RootViewSizeChangedEventArgs(winrt::Windows::Foundation::Size size) : m_size(size) {}
|
|
519
|
+
winrt::Windows::Foundation::Size Size() const noexcept {
|
|
520
|
+
return m_size;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
private:
|
|
524
|
+
const winrt::Windows::Foundation::Size m_size;
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
void CompositionRootView::NotifySizeChanged() noexcept {
|
|
528
|
+
auto oldSize = m_size;
|
|
529
|
+
facebook::react::Size size;
|
|
530
|
+
auto rootComponentView = GetComponentView();
|
|
531
|
+
if (rootComponentView) {
|
|
532
|
+
size = rootComponentView->layoutMetrics().frame.size;
|
|
533
|
+
} else if (m_loadingVisual) {
|
|
534
|
+
size = MeasureLoading(m_layoutConstraints, m_scaleFactor);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
m_size = {size.width, size.height};
|
|
538
|
+
UpdateRootVisualSize();
|
|
539
|
+
if (oldSize != m_size) {
|
|
540
|
+
m_sizeChangedEvent(*this, winrt::make<RootViewSizeChangedEventArgs>(m_size));
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
494
544
|
void CompositionRootView::ShowInstanceError() noexcept {
|
|
495
545
|
ClearLoadingUI();
|
|
496
546
|
}
|
|
@@ -500,6 +550,9 @@ Composition::Experimental::IDrawingSurfaceBrush CompositionRootView::CreateLoadi
|
|
|
500
550
|
winrt::Microsoft::ReactNative::Composition::implementation::CompositionUIService::GetCompositionContext(
|
|
501
551
|
m_context.Properties().Handle());
|
|
502
552
|
|
|
553
|
+
if (m_size.Height == 0 || m_size.Width == 0)
|
|
554
|
+
return nullptr;
|
|
555
|
+
|
|
503
556
|
winrt::Windows::Foundation::Size surfaceSize = {
|
|
504
557
|
m_size.Width * m_scaleFactor, std::min(m_size.Height, loadingBarHeight) * m_scaleFactor};
|
|
505
558
|
auto drawingSurface = compContext.CreateDrawingSurfaceBrush(
|
|
@@ -517,12 +570,7 @@ Composition::Experimental::IDrawingSurfaceBrush CompositionRootView::CreateLoadi
|
|
|
517
570
|
constraints.maximumSize.width = std::max(0.0f, m_size.Width - loadingTextHorizontalOffset);
|
|
518
571
|
constraints.maximumSize.height = std::max(0.0f, m_size.Height - loadingBarHeight);
|
|
519
572
|
|
|
520
|
-
auto
|
|
521
|
-
auto fragment = facebook::react::AttributedString::Fragment{};
|
|
522
|
-
fragment.string = "Loading";
|
|
523
|
-
fragment.textAttributes.fontSize = loadingBarFontSize;
|
|
524
|
-
attributedString.appendFragment(fragment);
|
|
525
|
-
auto attributedStringBox = facebook::react::AttributedStringBox{attributedString};
|
|
573
|
+
auto attributedStringBox = CreateLoadingAttributedString();
|
|
526
574
|
|
|
527
575
|
auto textAttributes = facebook::react::TextAttributes{};
|
|
528
576
|
textAttributes.foregroundColor = facebook::react::whiteColor();
|
|
@@ -563,10 +611,7 @@ void CompositionRootView::ShowInstanceLoading() noexcept {
|
|
|
563
611
|
winrt::Microsoft::ReactNative::Composition::implementation::CompositionUIService::GetCompositionContext(
|
|
564
612
|
m_context.Properties().Handle());
|
|
565
613
|
|
|
566
|
-
auto drawingSurface = CreateLoadingVisualBrush();
|
|
567
|
-
|
|
568
614
|
m_loadingVisual = compContext.CreateSpriteVisual();
|
|
569
|
-
m_loadingVisual.Brush(drawingSurface);
|
|
570
615
|
|
|
571
616
|
auto foregroundBrush = compContext.CreateColorBrush({255, 255, 255, 255});
|
|
572
617
|
|
|
@@ -574,14 +619,28 @@ void CompositionRootView::ShowInstanceLoading() noexcept {
|
|
|
574
619
|
m_loadingActivityVisual.Brush(foregroundBrush);
|
|
575
620
|
m_loadingVisual.InsertAt(m_loadingActivityVisual, 0);
|
|
576
621
|
|
|
622
|
+
NotifySizeChanged();
|
|
577
623
|
UpdateLoadingVisualSize();
|
|
578
624
|
|
|
579
625
|
InternalRootVisual().InsertAt(m_loadingVisual, m_hasRenderedVisual ? 1 : 0);
|
|
580
626
|
}
|
|
581
627
|
|
|
628
|
+
void ApplyConstraints(
|
|
629
|
+
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
|
|
630
|
+
facebook::react::LayoutConstraints &layoutConstraintsOut) noexcept {
|
|
631
|
+
layoutConstraintsOut.minimumSize = {layoutConstraintsIn.MinimumSize.Width, layoutConstraintsIn.MinimumSize.Height};
|
|
632
|
+
layoutConstraintsOut.maximumSize = {layoutConstraintsIn.MaximumSize.Width, layoutConstraintsIn.MaximumSize.Height};
|
|
633
|
+
layoutConstraintsOut.layoutDirection =
|
|
634
|
+
static_cast<facebook::react::LayoutDirection>(layoutConstraintsIn.LayoutDirection);
|
|
635
|
+
}
|
|
636
|
+
|
|
582
637
|
winrt::Windows::Foundation::Size CompositionRootView::Measure(
|
|
583
|
-
winrt::
|
|
584
|
-
|
|
638
|
+
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
|
|
639
|
+
const winrt::Windows::Foundation::Point &viewportOffset) const noexcept {
|
|
640
|
+
facebook::react::Size size{0, 0};
|
|
641
|
+
|
|
642
|
+
facebook::react::LayoutConstraints constraints;
|
|
643
|
+
ApplyConstraints(layoutConstraints, constraints);
|
|
585
644
|
|
|
586
645
|
if (m_isInitialized && m_rootTag != -1) {
|
|
587
646
|
if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
|
|
@@ -590,55 +649,39 @@ winrt::Windows::Foundation::Size CompositionRootView::Measure(
|
|
|
590
649
|
// TODO scaling factor
|
|
591
650
|
context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
|
|
592
651
|
context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
|
|
652
|
+
context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
|
|
593
653
|
|
|
594
|
-
facebook::react::
|
|
595
|
-
// TODO should support MinHeight/MinWidth
|
|
596
|
-
constraints.minimumSize.height = static_cast<facebook::react::Float>(0.0f);
|
|
597
|
-
constraints.minimumSize.width = static_cast<facebook::react::Float>(0.0f);
|
|
598
|
-
|
|
599
|
-
// TODO should support MaxHeight/MaxWidth props?
|
|
600
|
-
constraints.minimumSize.height = constraints.maximumSize.height =
|
|
601
|
-
static_cast<facebook::react::Float>(availableSize.Height);
|
|
602
|
-
constraints.minimumSize.width = constraints.maximumSize.width =
|
|
603
|
-
static_cast<facebook::react::Float>(availableSize.Width);
|
|
604
|
-
// TODO get RTL
|
|
605
|
-
constraints.layoutDirection = facebook::react::LayoutDirection::LeftToRight;
|
|
606
|
-
|
|
607
|
-
auto yogaSize =
|
|
608
|
-
fabricuiManager->measureSurface(static_cast<facebook::react::SurfaceId>(m_rootTag), constraints, context);
|
|
609
|
-
return {std::min(yogaSize.width, availableSize.Width), std::min(yogaSize.height, availableSize.Height)};
|
|
654
|
+
size = fabricuiManager->measureSurface(static_cast<facebook::react::SurfaceId>(m_rootTag), constraints, context);
|
|
610
655
|
}
|
|
656
|
+
} else if (m_loadingVisual) {
|
|
657
|
+
size = MeasureLoading(constraints, m_scaleFactor);
|
|
611
658
|
}
|
|
612
659
|
|
|
613
|
-
|
|
660
|
+
auto clampedSize = constraints.clamp(size);
|
|
661
|
+
return {clampedSize.width, clampedSize.height};
|
|
614
662
|
}
|
|
615
663
|
|
|
616
|
-
|
|
664
|
+
void CompositionRootView::Arrange(
|
|
665
|
+
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
|
|
666
|
+
const winrt::Windows::Foundation::Point &viewportOffset) noexcept {
|
|
667
|
+
ApplyConstraints(layoutConstraints, m_layoutConstraints);
|
|
668
|
+
|
|
617
669
|
if (m_isInitialized && m_rootTag != -1) {
|
|
618
670
|
if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
|
|
619
671
|
winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
|
|
620
672
|
facebook::react::LayoutContext context;
|
|
621
673
|
context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
|
|
622
674
|
context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
|
|
623
|
-
|
|
624
|
-
facebook::react::LayoutConstraints constraints;
|
|
625
|
-
// TODO should support MinHeight/MinWidth
|
|
626
|
-
constraints.minimumSize.height = static_cast<facebook::react::Float>(0.0f);
|
|
627
|
-
constraints.minimumSize.width = static_cast<facebook::react::Float>(0.0f);
|
|
628
|
-
|
|
629
|
-
// TODO should support MaxHeight/MaxWidth props?
|
|
630
|
-
constraints.minimumSize.height = constraints.maximumSize.height =
|
|
631
|
-
static_cast<facebook::react::Float>(finalSize.Height);
|
|
632
|
-
constraints.minimumSize.width = constraints.maximumSize.width =
|
|
633
|
-
static_cast<facebook::react::Float>(finalSize.Width);
|
|
634
|
-
// TODO get RTL
|
|
635
|
-
constraints.layoutDirection = facebook::react::LayoutDirection::LeftToRight;
|
|
675
|
+
context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
|
|
636
676
|
|
|
637
677
|
fabricuiManager->constraintSurfaceLayout(
|
|
638
|
-
static_cast<facebook::react::SurfaceId>(m_rootTag),
|
|
678
|
+
static_cast<facebook::react::SurfaceId>(m_rootTag), m_layoutConstraints, context);
|
|
639
679
|
}
|
|
680
|
+
} else if (m_loadingVisual) {
|
|
681
|
+
// TODO: Resize to align loading
|
|
682
|
+
auto s = m_layoutConstraints.clamp(MeasureLoading(m_layoutConstraints, m_scaleFactor));
|
|
683
|
+
NotifySizeChanged();
|
|
640
684
|
}
|
|
641
|
-
return finalSize;
|
|
642
685
|
}
|
|
643
686
|
|
|
644
687
|
#ifdef USE_WINUI3
|
|
@@ -655,20 +698,29 @@ winrt::Microsoft::UI::Content::ContentIsland CompositionRootView::Island() noexc
|
|
|
655
698
|
rootVisual));
|
|
656
699
|
m_island = winrt::Microsoft::UI::Content::ContentIsland::Create(rootVisual);
|
|
657
700
|
|
|
658
|
-
|
|
659
|
-
|
|
701
|
+
// ContentIsland does not support weak_ref, so we cannot use auto_revoke for these events
|
|
702
|
+
m_islandAutomationProviderRequestedToken = m_island.AutomationProviderRequested(
|
|
703
|
+
[weakThis = get_weak()](
|
|
660
704
|
winrt::Microsoft::UI::Content::ContentIsland const &,
|
|
661
705
|
winrt::Microsoft::UI::Content::ContentIslandAutomationProviderRequestedEventArgs const &args) {
|
|
662
|
-
auto
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
pRootProvider
|
|
706
|
+
if (auto pThis = weakThis.get()) {
|
|
707
|
+
auto provider = pThis->GetUiaProvider();
|
|
708
|
+
auto pRootProvider =
|
|
709
|
+
static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
|
|
710
|
+
provider.as<IRawElementProviderSimple>().get());
|
|
711
|
+
if (pRootProvider != nullptr) {
|
|
712
|
+
pRootProvider->SetIsland(pThis->m_island);
|
|
713
|
+
}
|
|
714
|
+
args.AutomationProvider(std::move(provider));
|
|
715
|
+
args.Handled(true);
|
|
668
716
|
}
|
|
669
|
-
args.AutomationProvider(std::move(provider));
|
|
670
|
-
args.Handled(true);
|
|
671
717
|
});
|
|
718
|
+
|
|
719
|
+
m_islandFrameworkClosedToken = m_island.FrameworkClosed([weakThis = get_weak()]() {
|
|
720
|
+
if (auto pThis = weakThis.get()) {
|
|
721
|
+
pThis->m_island = nullptr;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
672
724
|
}
|
|
673
725
|
return m_island;
|
|
674
726
|
}
|