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
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
#include <FocusNavigationResult.g.h>
|
|
8
8
|
|
|
9
9
|
#include <ReactContext.h>
|
|
10
|
+
#include <react/renderer/core/LayoutConstraints.h>
|
|
10
11
|
#include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
|
|
11
12
|
#include <winrt/Microsoft.ReactNative.h>
|
|
12
13
|
#include "CompositionEventHandler.h"
|
|
13
14
|
#include "ReactHost/React.h"
|
|
14
|
-
#include "Views/ICompositionRootView.h"
|
|
15
15
|
|
|
16
16
|
namespace winrt::Microsoft::ReactNative::implementation {
|
|
17
17
|
|
|
@@ -42,8 +42,7 @@ struct FocusNavigationResult : FocusNavigationResultT<FocusNavigationResult> {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
struct CompositionRootView
|
|
45
|
-
: CompositionRootViewT<CompositionRootView, Composition::Experimental::IInternalCompositionRootView
|
|
46
|
-
::Microsoft::ReactNative::ICompositionRootView {
|
|
45
|
+
: CompositionRootViewT<CompositionRootView, Composition::Experimental::IInternalCompositionRootView> {
|
|
47
46
|
CompositionRootView() noexcept;
|
|
48
47
|
~CompositionRootView() noexcept;
|
|
49
48
|
|
|
@@ -70,6 +69,12 @@ struct CompositionRootView
|
|
|
70
69
|
float ScaleFactor() noexcept;
|
|
71
70
|
void ScaleFactor(float value) noexcept;
|
|
72
71
|
|
|
72
|
+
winrt::event_token SizeChanged(
|
|
73
|
+
winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs> const
|
|
74
|
+
&handler) noexcept;
|
|
75
|
+
void SizeChanged(winrt::event_token const &token) noexcept;
|
|
76
|
+
void NotifySizeChanged() noexcept;
|
|
77
|
+
|
|
73
78
|
void AddRenderedVisual(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept;
|
|
74
79
|
void RemoveRenderedVisual(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept;
|
|
75
80
|
bool TrySetFocus() noexcept;
|
|
@@ -80,8 +85,12 @@ struct CompositionRootView
|
|
|
80
85
|
winrt::Microsoft::ReactNative::Composition::Theme Theme() noexcept;
|
|
81
86
|
void Theme(const winrt::Microsoft::ReactNative::Composition::Theme &value) noexcept;
|
|
82
87
|
|
|
83
|
-
winrt::Windows::Foundation::Size Measure(
|
|
84
|
-
|
|
88
|
+
winrt::Windows::Foundation::Size Measure(
|
|
89
|
+
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
|
|
90
|
+
const winrt::Windows::Foundation::Point &viewportOffset) const noexcept;
|
|
91
|
+
void Arrange(
|
|
92
|
+
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
|
|
93
|
+
const winrt::Windows::Foundation::Point &viewportOffset) noexcept;
|
|
85
94
|
|
|
86
95
|
winrt::Microsoft::ReactNative::FocusNavigationResult NavigateFocus(
|
|
87
96
|
const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
|
|
@@ -103,13 +112,6 @@ struct CompositionRootView
|
|
|
103
112
|
const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
|
|
104
113
|
facebook::react::Tag tag) noexcept;
|
|
105
114
|
|
|
106
|
-
public: // IReactRootView
|
|
107
|
-
std::string JSComponentName() const noexcept override;
|
|
108
|
-
int64_t GetActualHeight() const noexcept override;
|
|
109
|
-
int64_t GetActualWidth() const noexcept override;
|
|
110
|
-
int64_t GetTag() const noexcept override;
|
|
111
|
-
void SetTag(int64_t tag) noexcept override;
|
|
112
|
-
|
|
113
115
|
public: // IReactViewInstance UI-thread implementation
|
|
114
116
|
void InitRootView(
|
|
115
117
|
winrt::Microsoft::ReactNative::IReactContext &&context,
|
|
@@ -121,6 +123,8 @@ struct CompositionRootView
|
|
|
121
123
|
#ifdef USE_WINUI3
|
|
122
124
|
winrt::Microsoft::UI::Composition::Compositor m_compositor{nullptr};
|
|
123
125
|
winrt::Microsoft::UI::Content::ContentIsland m_island{nullptr};
|
|
126
|
+
winrt::event_token m_islandFrameworkClosedToken;
|
|
127
|
+
winrt::event_token m_islandAutomationProviderRequestedToken;
|
|
124
128
|
#endif
|
|
125
129
|
|
|
126
130
|
HWND m_hwnd{0};
|
|
@@ -132,7 +136,7 @@ struct CompositionRootView
|
|
|
132
136
|
winrt::IInspectable m_uiaProvider{nullptr};
|
|
133
137
|
int64_t m_rootTag{-1};
|
|
134
138
|
float m_scaleFactor{1.0};
|
|
135
|
-
winrt::Windows::Foundation::Size m_size;
|
|
139
|
+
winrt::Windows::Foundation::Size m_size{0, 0};
|
|
136
140
|
winrt::Microsoft::ReactNative::ReactContext m_context;
|
|
137
141
|
winrt::Microsoft::ReactNative::IReactViewHost m_reactViewHost;
|
|
138
142
|
winrt::Microsoft::ReactNative::ReactViewOptions m_reactViewOptions;
|
|
@@ -143,6 +147,9 @@ struct CompositionRootView
|
|
|
143
147
|
winrt::Microsoft::ReactNative::Composition::ICustomResourceLoader m_resources{nullptr};
|
|
144
148
|
winrt::Microsoft::ReactNative::Composition::Theme m_theme{nullptr};
|
|
145
149
|
winrt::Microsoft::ReactNative::Composition::Theme::ThemeChanged_revoker m_themeChangedRevoker;
|
|
150
|
+
facebook::react::LayoutConstraints m_layoutConstraints;
|
|
151
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs>>
|
|
152
|
+
m_sizeChangedEvent;
|
|
146
153
|
|
|
147
154
|
void UpdateRootViewInternal() noexcept;
|
|
148
155
|
void ClearLoadingUI() noexcept;
|
|
@@ -121,6 +121,10 @@ winrt::Microsoft::ReactNative::Composition::Theme ComponentView::Theme() const n
|
|
|
121
121
|
return theme()->get_strong().as<winrt::Microsoft::ReactNative::Composition::Theme>();
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
winrt::Microsoft::ReactNative::Composition::RootComponentView ComponentView::Root() noexcept {
|
|
125
|
+
return *rootComponentView();
|
|
126
|
+
}
|
|
127
|
+
|
|
124
128
|
winrt::Microsoft::UI::Composition::Compositor ComponentView::Compositor() const noexcept {
|
|
125
129
|
return winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerCompositor(
|
|
126
130
|
m_compContext);
|
|
@@ -171,6 +175,10 @@ void ComponentView::updateLayoutMetrics(
|
|
|
171
175
|
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
172
176
|
}
|
|
173
177
|
|
|
178
|
+
const facebook::react::LayoutMetrics &ComponentView::layoutMetrics() const noexcept {
|
|
179
|
+
return m_layoutMetrics;
|
|
180
|
+
}
|
|
181
|
+
|
|
174
182
|
void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept {
|
|
175
183
|
if ((m_flags & ComponentViewFeatures::NativeBorder) == ComponentViewFeatures::NativeBorder) {
|
|
176
184
|
finalizeBorderUpdates(m_layoutMetrics, *viewProps());
|
|
@@ -179,32 +187,38 @@ void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentView
|
|
|
179
187
|
base_type::FinalizeUpdates(updateMask);
|
|
180
188
|
}
|
|
181
189
|
|
|
182
|
-
void ComponentView::
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
190
|
+
void ComponentView::onLostFocus(
|
|
191
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
192
|
+
if (args.OriginalSource() == Tag()) {
|
|
193
|
+
m_eventEmitter->onBlur();
|
|
194
|
+
showFocusVisual(false);
|
|
195
|
+
if (m_uiaProvider) {
|
|
196
|
+
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
197
|
+
m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
|
|
198
|
+
}
|
|
188
199
|
}
|
|
189
|
-
base_type::
|
|
200
|
+
base_type::onLostFocus(args);
|
|
190
201
|
}
|
|
191
202
|
|
|
192
|
-
void ComponentView::
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
+
void ComponentView::onGotFocus(
|
|
204
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
205
|
+
if (args.OriginalSource() == Tag()) {
|
|
206
|
+
m_eventEmitter->onFocus();
|
|
207
|
+
if (m_enableFocusVisual) {
|
|
208
|
+
showFocusVisual(true);
|
|
209
|
+
}
|
|
210
|
+
if (m_uiaProvider) {
|
|
211
|
+
auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
|
|
212
|
+
if (spProviderSimple != nullptr) {
|
|
213
|
+
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
214
|
+
m_uiaProvider, UIA_HasKeyboardFocusPropertyId, false, true);
|
|
215
|
+
UiaRaiseAutomationEvent(spProviderSimple.get(), UIA_AutomationFocusChangedEventId);
|
|
216
|
+
}
|
|
203
217
|
}
|
|
204
|
-
}
|
|
205
218
|
|
|
206
|
-
|
|
207
|
-
|
|
219
|
+
StartBringIntoView({});
|
|
220
|
+
}
|
|
221
|
+
base_type::onGotFocus(args);
|
|
208
222
|
}
|
|
209
223
|
|
|
210
224
|
void ComponentView::StartBringIntoView(
|
|
@@ -234,13 +248,13 @@ void ComponentView::HandleCommand(
|
|
|
234
248
|
const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
|
|
235
249
|
if (commandName == L"focus") {
|
|
236
250
|
if (auto root = rootComponentView()) {
|
|
237
|
-
root->
|
|
251
|
+
root->TrySetFocusedComponent(*get_strong());
|
|
238
252
|
}
|
|
239
253
|
return;
|
|
240
254
|
}
|
|
241
255
|
if (commandName == L"blur") {
|
|
242
256
|
if (auto root = rootComponentView()) {
|
|
243
|
-
root->
|
|
257
|
+
root->TrySetFocusedComponent(nullptr); // Todo store this component as previously focused element
|
|
244
258
|
}
|
|
245
259
|
return;
|
|
246
260
|
}
|
|
@@ -69,11 +69,14 @@ struct ComponentView
|
|
|
69
69
|
assert(false);
|
|
70
70
|
return emptyProps;
|
|
71
71
|
};
|
|
72
|
+
|
|
73
|
+
winrt::Microsoft::ReactNative::Composition::RootComponentView Root() noexcept;
|
|
74
|
+
|
|
72
75
|
void Theme(const winrt::Microsoft::ReactNative::Composition::Theme &theme) noexcept;
|
|
73
76
|
winrt::Microsoft::ReactNative::Composition::Theme Theme() const noexcept;
|
|
74
77
|
void onThemeChanged() noexcept override;
|
|
75
|
-
void
|
|
76
|
-
void
|
|
78
|
+
void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
|
|
79
|
+
void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
|
|
77
80
|
bool CapturePointer(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
|
|
78
81
|
void ReleasePointerCapture(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
|
|
79
82
|
|
|
@@ -117,6 +120,8 @@ struct ComponentView
|
|
|
117
120
|
bool getAcccessiblityIsReadOnly() noexcept override;
|
|
118
121
|
virtual winrt::Microsoft::ReactNative::implementation::ClipState getClipState() noexcept;
|
|
119
122
|
|
|
123
|
+
const facebook::react::LayoutMetrics &layoutMetrics() const noexcept;
|
|
124
|
+
|
|
120
125
|
virtual std::string DefaultControlType() const noexcept;
|
|
121
126
|
virtual std::string DefaultAccessibleName() const noexcept;
|
|
122
127
|
virtual std::string DefaultHelpText() const noexcept;
|
|
@@ -189,6 +194,7 @@ struct ViewComponentView : public ViewComponentViewT<ViewComponentView, Componen
|
|
|
189
194
|
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
190
195
|
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
|
|
191
196
|
void prepareForRecycle() noexcept override;
|
|
197
|
+
bool TryFocus() noexcept;
|
|
192
198
|
bool focusable() const noexcept override;
|
|
193
199
|
void OnKeyDown(
|
|
194
200
|
const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "pch.h"
|
|
5
|
+
#include "FocusManager.h"
|
|
6
|
+
#include "Composition.FocusManager.g.cpp"
|
|
7
|
+
#include <Fabric/FabricUIManagerModule.h>
|
|
8
|
+
|
|
9
|
+
namespace winrt::Microsoft::ReactNative::implementation {
|
|
10
|
+
|
|
11
|
+
LostFocusEventArgs::LostFocusEventArgs(const winrt::Microsoft::ReactNative::ComponentView &originalSource)
|
|
12
|
+
: m_originalSource(originalSource ? originalSource.Tag() : -1) {}
|
|
13
|
+
int32_t LostFocusEventArgs::OriginalSource() noexcept {
|
|
14
|
+
return m_originalSource;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
GotFocusEventArgs::GotFocusEventArgs(const winrt::Microsoft::ReactNative::ComponentView &originalSource)
|
|
18
|
+
: m_originalSource(originalSource ? originalSource.Tag() : -1) {}
|
|
19
|
+
int32_t GotFocusEventArgs::OriginalSource() noexcept {
|
|
20
|
+
return m_originalSource;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
LosingFocusEventArgs::LosingFocusEventArgs(
|
|
24
|
+
const winrt::Microsoft::ReactNative::ComponentView &originalSource,
|
|
25
|
+
const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
|
|
26
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
|
|
27
|
+
: m_originalSource(originalSource ? originalSource.Tag() : -1),
|
|
28
|
+
m_old(oldFocusedComponent),
|
|
29
|
+
m_new(newFocusedComponent) {}
|
|
30
|
+
|
|
31
|
+
int32_t LosingFocusEventArgs::OriginalSource() noexcept {
|
|
32
|
+
return m_originalSource;
|
|
33
|
+
}
|
|
34
|
+
winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::NewFocusedComponent() noexcept {
|
|
35
|
+
return m_new;
|
|
36
|
+
}
|
|
37
|
+
winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::OldFocusedComponent() noexcept {
|
|
38
|
+
return m_old;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void LosingFocusEventArgs::TryCancel() noexcept {
|
|
42
|
+
m_new = m_old;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void LosingFocusEventArgs::TrySetNewFocusedComponent(
|
|
46
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept {
|
|
47
|
+
auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(newFocusedComponent);
|
|
48
|
+
if (selfView->focusable()) {
|
|
49
|
+
m_new = newFocusedComponent;
|
|
50
|
+
} else {
|
|
51
|
+
auto target =
|
|
52
|
+
winrt::Microsoft::ReactNative::Composition::FocusManager::FindFirstFocusableElement(newFocusedComponent);
|
|
53
|
+
if (!target)
|
|
54
|
+
return;
|
|
55
|
+
m_new = target;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
GettingFocusEventArgs::GettingFocusEventArgs(
|
|
60
|
+
const winrt::Microsoft::ReactNative::ComponentView &originalSource,
|
|
61
|
+
const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
|
|
62
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
|
|
63
|
+
: m_originalSource(originalSource ? originalSource.Tag() : -1),
|
|
64
|
+
m_old(oldFocusedComponent),
|
|
65
|
+
m_new(newFocusedComponent) {}
|
|
66
|
+
|
|
67
|
+
int32_t GettingFocusEventArgs::OriginalSource() noexcept {
|
|
68
|
+
return m_originalSource;
|
|
69
|
+
}
|
|
70
|
+
winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::NewFocusedComponent() noexcept {
|
|
71
|
+
return m_new;
|
|
72
|
+
}
|
|
73
|
+
winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::OldFocusedComponent() noexcept {
|
|
74
|
+
return m_old;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void GettingFocusEventArgs::TryCancel() noexcept {
|
|
78
|
+
m_new = m_old;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
void GettingFocusEventArgs::TrySetNewFocusedComponent(
|
|
82
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept {
|
|
83
|
+
auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(newFocusedComponent);
|
|
84
|
+
if (selfView->focusable()) {
|
|
85
|
+
m_new = newFocusedComponent;
|
|
86
|
+
} else {
|
|
87
|
+
auto target =
|
|
88
|
+
winrt::Microsoft::ReactNative::Composition::FocusManager::FindFirstFocusableElement(newFocusedComponent);
|
|
89
|
+
if (!target)
|
|
90
|
+
return;
|
|
91
|
+
m_new = target;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
} // namespace winrt::Microsoft::ReactNative::implementation
|
|
96
|
+
|
|
97
|
+
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
98
|
+
|
|
99
|
+
winrt::Microsoft::ReactNative::implementation::ComponentView *NavigateFocusHelper(
|
|
100
|
+
winrt::Microsoft::ReactNative::implementation::ComponentView &view,
|
|
101
|
+
winrt::Microsoft::ReactNative::FocusNavigationReason reason) {
|
|
102
|
+
if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First) {
|
|
103
|
+
if (view.focusable()) {
|
|
104
|
+
return &view;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
winrt::Microsoft::ReactNative::implementation::ComponentView *toFocus = nullptr;
|
|
108
|
+
|
|
109
|
+
Mso::Functor<bool(::winrt::Microsoft::ReactNative::implementation::ComponentView & v)> fn =
|
|
110
|
+
[reason, &toFocus](::winrt::Microsoft::ReactNative::implementation::ComponentView &v) noexcept
|
|
111
|
+
-> bool { return (toFocus = NavigateFocusHelper(v, reason)); };
|
|
112
|
+
|
|
113
|
+
if (view.runOnChildren(reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First, fn)) {
|
|
114
|
+
return toFocus;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::Last) {
|
|
118
|
+
if (view.focusable()) {
|
|
119
|
+
return &view;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return nullptr;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
winrt::Microsoft::ReactNative::ComponentView FocusManager::FindFirstFocusableElement(
|
|
127
|
+
const winrt::Microsoft::ReactNative::ComponentView &searchScope) noexcept {
|
|
128
|
+
auto selfSearchScope = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(searchScope);
|
|
129
|
+
auto view = NavigateFocusHelper(*selfSearchScope, winrt::Microsoft::ReactNative::FocusNavigationReason::First);
|
|
130
|
+
if (view) {
|
|
131
|
+
winrt::Microsoft::ReactNative::ComponentView component{nullptr};
|
|
132
|
+
winrt::check_hresult(view->QueryInterface(
|
|
133
|
+
winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(component)));
|
|
134
|
+
return *view;
|
|
135
|
+
}
|
|
136
|
+
return nullptr;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
winrt::Microsoft::ReactNative::ComponentView FocusManager::FindLastFocusableElement(
|
|
140
|
+
const winrt::Microsoft::ReactNative::ComponentView &searchScope) noexcept {
|
|
141
|
+
auto selfSearchScope = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(searchScope);
|
|
142
|
+
auto view = NavigateFocusHelper(*selfSearchScope, winrt::Microsoft::ReactNative::FocusNavigationReason::Last);
|
|
143
|
+
if (view) {
|
|
144
|
+
winrt::Microsoft::ReactNative::ComponentView component{nullptr};
|
|
145
|
+
winrt::check_hresult(view->QueryInterface(
|
|
146
|
+
winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(component)));
|
|
147
|
+
return *view;
|
|
148
|
+
}
|
|
149
|
+
return nullptr;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
#include "Composition.FocusManager.g.h"
|
|
6
|
+
#include "GettingFocusEventArgs.g.h"
|
|
7
|
+
#include "LosingFocusEventArgs.g.h"
|
|
8
|
+
#include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
|
|
9
|
+
#include <winrt/Microsoft.ReactNative.Composition.Input.h>
|
|
10
|
+
|
|
11
|
+
namespace winrt::Microsoft::ReactNative::implementation {
|
|
12
|
+
|
|
13
|
+
struct LostFocusEventArgs
|
|
14
|
+
: winrt::implements<LostFocusEventArgs, winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> {
|
|
15
|
+
LostFocusEventArgs(const winrt::Microsoft::ReactNative::ComponentView &originalSource);
|
|
16
|
+
int32_t OriginalSource() noexcept;
|
|
17
|
+
|
|
18
|
+
private:
|
|
19
|
+
const int32_t m_originalSource;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
struct GotFocusEventArgs
|
|
23
|
+
: winrt::implements<GotFocusEventArgs, winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs> {
|
|
24
|
+
GotFocusEventArgs(const winrt::Microsoft::ReactNative::ComponentView &originalSource);
|
|
25
|
+
int32_t OriginalSource() noexcept;
|
|
26
|
+
|
|
27
|
+
private:
|
|
28
|
+
const int32_t m_originalSource;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
struct LosingFocusEventArgs
|
|
32
|
+
: winrt::Microsoft::ReactNative::implementation::LosingFocusEventArgsT<LosingFocusEventArgs> {
|
|
33
|
+
LosingFocusEventArgs(
|
|
34
|
+
const winrt::Microsoft::ReactNative::ComponentView &originalSource,
|
|
35
|
+
const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
|
|
36
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent);
|
|
37
|
+
int32_t OriginalSource() noexcept;
|
|
38
|
+
winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() noexcept;
|
|
39
|
+
winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() noexcept;
|
|
40
|
+
|
|
41
|
+
void TryCancel() noexcept;
|
|
42
|
+
void TrySetNewFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept;
|
|
43
|
+
|
|
44
|
+
private:
|
|
45
|
+
const int32_t m_originalSource;
|
|
46
|
+
winrt::Microsoft::ReactNative::ComponentView m_old{nullptr};
|
|
47
|
+
winrt::Microsoft::ReactNative::ComponentView m_new{nullptr};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
struct GettingFocusEventArgs
|
|
51
|
+
: winrt::Microsoft::ReactNative::implementation::GettingFocusEventArgsT<GettingFocusEventArgs> {
|
|
52
|
+
GettingFocusEventArgs(
|
|
53
|
+
const winrt::Microsoft::ReactNative::ComponentView &originalSource,
|
|
54
|
+
const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
|
|
55
|
+
const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent);
|
|
56
|
+
int32_t OriginalSource() noexcept;
|
|
57
|
+
winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() noexcept;
|
|
58
|
+
winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() noexcept;
|
|
59
|
+
|
|
60
|
+
void TryCancel() noexcept;
|
|
61
|
+
void TrySetNewFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept;
|
|
62
|
+
|
|
63
|
+
private:
|
|
64
|
+
const int32_t m_originalSource;
|
|
65
|
+
winrt::Microsoft::ReactNative::ComponentView m_old{nullptr};
|
|
66
|
+
winrt::Microsoft::ReactNative::ComponentView m_new{nullptr};
|
|
67
|
+
};
|
|
68
|
+
} // namespace winrt::Microsoft::ReactNative::implementation
|
|
69
|
+
|
|
70
|
+
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
71
|
+
|
|
72
|
+
struct FocusManager : FocusManagerT<FocusManager> {
|
|
73
|
+
FocusManager() = default;
|
|
74
|
+
|
|
75
|
+
static winrt::Microsoft::ReactNative::ComponentView FindFirstFocusableElement(
|
|
76
|
+
const winrt::Microsoft::ReactNative::ComponentView &searchScope) noexcept;
|
|
77
|
+
static winrt::Microsoft::ReactNative::ComponentView FindLastFocusableElement(
|
|
78
|
+
const winrt::Microsoft::ReactNative::ComponentView &searchScope) noexcept;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
82
|
+
|
|
83
|
+
namespace winrt::Microsoft::ReactNative::Composition::factory_implementation {
|
|
84
|
+
struct FocusManager : FocusManagerT<FocusManager, implementation::FocusManager> {};
|
|
85
|
+
} // namespace winrt::Microsoft::ReactNative::Composition::factory_implementation
|
|
@@ -45,7 +45,21 @@ RootComponentView *RootComponentView::rootComponentView() noexcept {
|
|
|
45
45
|
return this;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
void RootComponentView::updateLayoutMetrics(
|
|
49
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
50
|
+
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
|
|
51
|
+
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
52
|
+
|
|
53
|
+
if (oldLayoutMetrics.frame != layoutMetrics.frame ||
|
|
54
|
+
oldLayoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor) {
|
|
55
|
+
if (auto rootView = m_wkRootView.get()) {
|
|
56
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(rootView)
|
|
57
|
+
->NotifySizeChanged();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
winrt::Microsoft::ReactNative::ComponentView RootComponentView::GetFocusedComponent() noexcept {
|
|
49
63
|
return m_focusedComponent;
|
|
50
64
|
}
|
|
51
65
|
void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept {
|
|
@@ -53,69 +67,69 @@ void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative:
|
|
|
53
67
|
return;
|
|
54
68
|
|
|
55
69
|
if (m_focusedComponent) {
|
|
56
|
-
winrt::
|
|
70
|
+
auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::LostFocusEventArgs>(m_focusedComponent);
|
|
71
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)
|
|
72
|
+
->onLostFocus(args);
|
|
57
73
|
}
|
|
58
74
|
|
|
59
75
|
if (value) {
|
|
60
76
|
if (auto rootView = m_wkRootView.get()) {
|
|
61
77
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(rootView)->TrySetFocus();
|
|
62
78
|
}
|
|
63
|
-
winrt::
|
|
79
|
+
auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>(value);
|
|
80
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(value)->onGotFocus(args);
|
|
64
81
|
}
|
|
65
82
|
|
|
66
83
|
m_focusedComponent = value;
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
winrt::Microsoft::ReactNative::implementation::ComponentView *NavigateFocusHelper(
|
|
70
|
-
winrt::Microsoft::ReactNative::implementation::ComponentView &view,
|
|
71
|
-
winrt::Microsoft::ReactNative::FocusNavigationReason reason) {
|
|
72
|
-
if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First) {
|
|
73
|
-
if (view.focusable()) {
|
|
74
|
-
return &view;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
winrt::Microsoft::ReactNative::implementation::ComponentView *toFocus = nullptr;
|
|
78
|
-
|
|
79
|
-
Mso::Functor<bool(::winrt::Microsoft::ReactNative::implementation::ComponentView & v)> fn =
|
|
80
|
-
[reason, &toFocus](::winrt::Microsoft::ReactNative::implementation::ComponentView &v) noexcept
|
|
81
|
-
-> bool { return (toFocus = NavigateFocusHelper(v, reason)); };
|
|
82
|
-
|
|
83
|
-
if (view.runOnChildren(reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First, fn)) {
|
|
84
|
-
return toFocus;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::Last) {
|
|
88
|
-
if (view.focusable()) {
|
|
89
|
-
return &view;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return nullptr;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
86
|
bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept {
|
|
97
87
|
if (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::Restore) {
|
|
98
88
|
// No-op for now
|
|
99
89
|
return m_focusedComponent != nullptr;
|
|
100
90
|
}
|
|
101
91
|
|
|
102
|
-
auto view =
|
|
92
|
+
auto view = (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::First)
|
|
93
|
+
? FocusManager::FindFirstFocusableElement(*this)
|
|
94
|
+
: FocusManager::FindLastFocusableElement(*this);
|
|
103
95
|
if (view) {
|
|
104
|
-
|
|
105
|
-
winrt::check_hresult(view->QueryInterface(
|
|
106
|
-
winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(component)));
|
|
107
|
-
SetFocusedComponent(component);
|
|
96
|
+
TrySetFocusedComponent(view);
|
|
108
97
|
}
|
|
109
98
|
return view != nullptr;
|
|
110
99
|
}
|
|
111
100
|
|
|
112
101
|
bool RootComponentView::TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
|
|
113
|
-
auto
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
102
|
+
auto target = view;
|
|
103
|
+
auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
|
|
104
|
+
if (selfView && !selfView->focusable()) {
|
|
105
|
+
target = FocusManager::FindFirstFocusableElement(target);
|
|
106
|
+
if (!target)
|
|
107
|
+
return false;
|
|
108
|
+
selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (selfView && selfView->rootComponentView() != this)
|
|
112
|
+
return false;
|
|
113
|
+
|
|
114
|
+
auto losingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::LosingFocusEventArgs>(
|
|
115
|
+
target, m_focusedComponent, target);
|
|
116
|
+
if (m_focusedComponent) {
|
|
117
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)
|
|
118
|
+
->onLosingFocus(losingFocusArgs);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (losingFocusArgs.NewFocusedComponent()) {
|
|
122
|
+
auto gettingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::GettingFocusEventArgs>(
|
|
123
|
+
target, m_focusedComponent, losingFocusArgs.NewFocusedComponent());
|
|
124
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
|
|
125
|
+
->onGettingFocus(gettingFocusArgs);
|
|
126
|
+
|
|
127
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
|
|
128
|
+
->rootComponentView()
|
|
129
|
+
->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent());
|
|
117
130
|
}
|
|
118
|
-
|
|
131
|
+
|
|
132
|
+
return true;
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
bool RootComponentView::TryMoveFocus(bool next) noexcept {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include <Microsoft.ReactNative.Cxx/ReactContext.h>
|
|
9
9
|
|
|
10
10
|
#include "CompositionViewComponentView.h"
|
|
11
|
+
#include "FocusManager.h"
|
|
11
12
|
#include "Theme.h"
|
|
12
13
|
|
|
13
14
|
#include "Composition.RootComponentView.g.h"
|
|
@@ -25,7 +26,7 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
|
|
|
25
26
|
facebook::react::Tag tag,
|
|
26
27
|
winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept;
|
|
27
28
|
|
|
28
|
-
winrt::Microsoft::ReactNative::ComponentView
|
|
29
|
+
winrt::Microsoft::ReactNative::ComponentView GetFocusedComponent() noexcept;
|
|
29
30
|
void SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept;
|
|
30
31
|
bool TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
|
|
31
32
|
|
|
@@ -42,6 +43,10 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
|
|
|
42
43
|
HRESULT GetFragmentRoot(IRawElementProviderFragmentRoot **pRetVal) noexcept;
|
|
43
44
|
winrt::Microsoft::ReactNative::implementation::ClipState getClipState() noexcept override;
|
|
44
45
|
|
|
46
|
+
void updateLayoutMetrics(
|
|
47
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
48
|
+
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
|
|
49
|
+
|
|
45
50
|
winrt::IInspectable UiaProviderFromPoint(const POINT &ptPixels) noexcept;
|
|
46
51
|
|
|
47
52
|
RootComponentView(
|
|
@@ -51,6 +56,9 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
|
|
|
51
56
|
|
|
52
57
|
virtual ~RootComponentView();
|
|
53
58
|
|
|
59
|
+
winrt::Microsoft::ReactNative::ComponentView FindFirstFocusableElement() noexcept;
|
|
60
|
+
winrt::Microsoft::ReactNative::ComponentView FindLastFocusableElement() noexcept;
|
|
61
|
+
|
|
54
62
|
private:
|
|
55
63
|
// should this be a ReactTaggedView? - It shouldn't actually matter since if the view is going away it should always
|
|
56
64
|
// be clearing its focus But being a reactTaggedView might make it easier to identify cases where that isn't
|
package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
CHANGED
|
@@ -224,7 +224,7 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
224
224
|
winrt::Microsoft::ReactNative::ComponentView view{nullptr};
|
|
225
225
|
winrt::check_hresult(
|
|
226
226
|
m_outer->QueryInterface(winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(view)));
|
|
227
|
-
m_outer->rootComponentView()->
|
|
227
|
+
m_outer->rootComponentView()->TrySetFocusedComponent(view);
|
|
228
228
|
// assert(false);
|
|
229
229
|
// TODO focus
|
|
230
230
|
}
|
|
@@ -929,8 +929,9 @@ void WindowsTextInputComponentView::UnmountChildComponentView(
|
|
|
929
929
|
base_type::UnmountChildComponentView(childComponentView, index);
|
|
930
930
|
}
|
|
931
931
|
|
|
932
|
-
void WindowsTextInputComponentView::
|
|
933
|
-
|
|
932
|
+
void WindowsTextInputComponentView::onLostFocus(
|
|
933
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
934
|
+
Super::onLostFocus(args);
|
|
934
935
|
if (m_textServices) {
|
|
935
936
|
LRESULT lresult;
|
|
936
937
|
DrawBlock db(*this);
|
|
@@ -939,8 +940,9 @@ void WindowsTextInputComponentView::onFocusLost() noexcept {
|
|
|
939
940
|
m_caretVisual.IsVisible(false);
|
|
940
941
|
}
|
|
941
942
|
|
|
942
|
-
void WindowsTextInputComponentView::
|
|
943
|
-
|
|
943
|
+
void WindowsTextInputComponentView::onGotFocus(
|
|
944
|
+
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
945
|
+
Super::onGotFocus(args);
|
|
944
946
|
if (m_textServices) {
|
|
945
947
|
LRESULT lresult;
|
|
946
948
|
DrawBlock db(*this);
|