react-native-windows 0.74.25 → 0.74.26
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/Fabric/Composition/BorderPrimitive.cpp +5 -0
- package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +190 -84
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +15 -10
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +10 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +6 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +1 -0
- package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/package.json +1 -1
|
@@ -818,6 +818,11 @@ uint8_t BorderPrimitive::numberOfVisuals() const noexcept {
|
|
|
818
818
|
return m_numBorderVisuals;
|
|
819
819
|
}
|
|
820
820
|
|
|
821
|
+
void BorderPrimitive::setOuter(
|
|
822
|
+
winrt::Microsoft::ReactNative::Composition::implementation::ComponentView *outer) noexcept {
|
|
823
|
+
m_outer = outer;
|
|
824
|
+
}
|
|
825
|
+
|
|
821
826
|
bool BorderPrimitive::TryUpdateSpecialBorderLayers(
|
|
822
827
|
winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
|
|
823
828
|
std::array<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual, SpecialBorderLayerCount>
|
|
@@ -29,6 +29,10 @@ struct BorderPrimitive {
|
|
|
29
29
|
|
|
30
30
|
void markNeedsUpdate() noexcept;
|
|
31
31
|
|
|
32
|
+
// We hoist focus visuals up the tree to allow them to be higher in the z-order.
|
|
33
|
+
// This means a single BorderPrimitive may change the owning ComponentView as focus moves around
|
|
34
|
+
void setOuter(winrt::Microsoft::ReactNative::Composition::implementation::ComponentView *outer) noexcept;
|
|
35
|
+
|
|
32
36
|
void updateProps(
|
|
33
37
|
const facebook::react::ViewProps &oldViewProps,
|
|
34
38
|
const facebook::react::ViewProps &newViewProps) noexcept;
|
|
@@ -40,7 +40,7 @@ constexpr float FOCUS_VISUAL_WIDTH = 2.0f;
|
|
|
40
40
|
// ----- m_visual <-- Background / clip - Can be a custom visual depending on Component type
|
|
41
41
|
// |
|
|
42
42
|
// ----- Border Visuals x N (BorderPrimitive attached to m_visual)
|
|
43
|
-
// ------Focus Visual Container
|
|
43
|
+
// ------Focus Visual Container (created when hosting focus visuals)
|
|
44
44
|
// |
|
|
45
45
|
// |------Inner Focus Visual
|
|
46
46
|
// |
|
|
@@ -57,9 +57,6 @@ ComponentView::ComponentView(
|
|
|
57
57
|
: base_type(tag, reactContext), m_compContext(compContext), m_flags(flags) {
|
|
58
58
|
m_outerVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a
|
|
59
59
|
// CreateContainerVisual in ICompositionContext
|
|
60
|
-
m_focusVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a
|
|
61
|
-
// CreateContainerVisual in ICompositionContext
|
|
62
|
-
m_outerVisual.InsertAt(m_focusVisual, 0);
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
ComponentView::~ComponentView() {
|
|
@@ -90,13 +87,17 @@ void ComponentView::onThemeChanged() noexcept {
|
|
|
90
87
|
m_borderPrimitive->onThemeChanged(
|
|
91
88
|
m_layoutMetrics, BorderPrimitive::resolveAndAlignBorderMetrics(m_layoutMetrics, *viewProps()));
|
|
92
89
|
}
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
if (m_componentHostingFocusVisual) {
|
|
91
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
92
|
+
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
93
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->onThemeChanged(
|
|
94
|
+
innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
95
|
+
}
|
|
96
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
97
|
+
auto outerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
98
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->onThemeChanged(
|
|
99
|
+
outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
100
|
+
}
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
|
|
@@ -160,14 +161,18 @@ void ComponentView::updateProps(
|
|
|
160
161
|
if (m_borderPrimitive) {
|
|
161
162
|
m_borderPrimitive->updateProps(oldViewProps, newViewProps);
|
|
162
163
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
|
|
165
|
+
if (m_componentHostingFocusVisual) {
|
|
166
|
+
if (!newViewProps.enableFocusRing) {
|
|
167
|
+
m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
171
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->updateProps(oldViewProps, newViewProps);
|
|
172
|
+
}
|
|
173
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
174
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->updateProps(oldViewProps, newViewProps);
|
|
175
|
+
}
|
|
171
176
|
}
|
|
172
177
|
if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
|
|
173
178
|
updateShadowProps(oldViewProps, newViewProps);
|
|
@@ -200,44 +205,70 @@ void ComponentView::updateLayoutMetrics(
|
|
|
200
205
|
});
|
|
201
206
|
}
|
|
202
207
|
|
|
203
|
-
|
|
208
|
+
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
204
209
|
|
|
205
210
|
if (layoutMetrics != oldLayoutMetrics) {
|
|
206
211
|
if (m_borderPrimitive) {
|
|
207
212
|
m_borderPrimitive->markNeedsUpdate();
|
|
208
213
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (m_focusOuterPrimitive) {
|
|
213
|
-
m_focusOuterPrimitive->markNeedsUpdate();
|
|
214
|
+
|
|
215
|
+
if (m_componentHostingFocusVisual) {
|
|
216
|
+
m_componentHostingFocusVisual->updateFocusLayoutMetrics();
|
|
214
217
|
}
|
|
215
218
|
}
|
|
216
219
|
|
|
217
|
-
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
218
220
|
UpdateCenterPropertySet();
|
|
219
221
|
}
|
|
220
222
|
|
|
221
|
-
void ComponentView::updateFocusLayoutMetrics(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
223
|
+
void ComponentView::updateFocusLayoutMetrics() noexcept {
|
|
224
|
+
facebook::react::RectangleEdges<bool> nudgeEdges;
|
|
225
|
+
auto scaleFactor = m_focusPrimitive->m_focusVisualComponent->m_layoutMetrics.pointScaleFactor;
|
|
226
|
+
if (m_focusPrimitive) {
|
|
227
|
+
if (m_focusPrimitive->m_focusOuterPrimitive) {
|
|
228
|
+
auto outerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(false /*inner*/);
|
|
229
|
+
|
|
230
|
+
if (outerFocusMetrics.frame.origin.x < 0) {
|
|
231
|
+
nudgeEdges.left = true;
|
|
232
|
+
}
|
|
233
|
+
if (outerFocusMetrics.frame.origin.y < 0) {
|
|
234
|
+
nudgeEdges.top = true;
|
|
235
|
+
}
|
|
236
|
+
if (outerFocusMetrics.frame.getMaxX() > m_layoutMetrics.frame.getMaxX()) {
|
|
237
|
+
nudgeEdges.right = true;
|
|
238
|
+
}
|
|
239
|
+
if (outerFocusMetrics.frame.getMaxY() > m_layoutMetrics.frame.getMaxY()) {
|
|
240
|
+
nudgeEdges.bottom = true;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Size(
|
|
244
|
+
{outerFocusMetrics.frame.size.width * scaleFactor -
|
|
245
|
+
(nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
|
|
246
|
+
(nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0),
|
|
247
|
+
outerFocusMetrics.frame.size.height * scaleFactor -
|
|
248
|
+
(nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
|
|
249
|
+
(nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0)});
|
|
250
|
+
m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Offset(
|
|
251
|
+
{nudgeEdges.left ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
|
|
252
|
+
nudgeEdges.top ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
|
|
253
|
+
0.0f});
|
|
254
|
+
m_focusPrimitive->m_focusOuterPrimitive->markNeedsUpdate();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (m_focusPrimitive->m_focusInnerPrimitive) {
|
|
258
|
+
auto innerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(true /*inner*/);
|
|
259
|
+
m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Size(
|
|
260
|
+
{innerFocusMetrics.frame.size.width * scaleFactor -
|
|
261
|
+
(nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
|
|
262
|
+
(nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0),
|
|
263
|
+
innerFocusMetrics.frame.size.height * scaleFactor -
|
|
264
|
+
(nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
|
|
265
|
+
(nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0)});
|
|
266
|
+
m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Offset(
|
|
267
|
+
{nudgeEdges.left ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
|
|
268
|
+
nudgeEdges.top ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
|
|
269
|
+
0.0f});
|
|
270
|
+
m_focusPrimitive->m_focusInnerPrimitive->markNeedsUpdate();
|
|
271
|
+
}
|
|
241
272
|
}
|
|
242
273
|
}
|
|
243
274
|
|
|
@@ -288,13 +319,17 @@ void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentView
|
|
|
288
319
|
}
|
|
289
320
|
}
|
|
290
321
|
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
322
|
+
if (m_componentHostingFocusVisual) {
|
|
323
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
324
|
+
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
325
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->finalize(
|
|
326
|
+
innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
327
|
+
}
|
|
328
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
329
|
+
auto outerFocusMetrics = focusLayoutMetrics(false /*inner*/);
|
|
330
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->finalize(
|
|
331
|
+
outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
332
|
+
}
|
|
298
333
|
}
|
|
299
334
|
|
|
300
335
|
if (m_FinalizeTransform) {
|
|
@@ -308,7 +343,12 @@ void ComponentView::onLostFocus(
|
|
|
308
343
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
309
344
|
if (args.OriginalSource() == Tag()) {
|
|
310
345
|
m_eventEmitter->onBlur();
|
|
311
|
-
|
|
346
|
+
|
|
347
|
+
if (m_componentHostingFocusVisual) {
|
|
348
|
+
auto s = get_strong();
|
|
349
|
+
|
|
350
|
+
m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
|
|
351
|
+
}
|
|
312
352
|
if (m_uiaProvider) {
|
|
313
353
|
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
314
354
|
m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
|
|
@@ -317,12 +357,47 @@ void ComponentView::onLostFocus(
|
|
|
317
357
|
base_type::onLostFocus(args);
|
|
318
358
|
}
|
|
319
359
|
|
|
360
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView::visualToHostFocus() noexcept {
|
|
361
|
+
return OuterVisual();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// We want to host focus visuals as close to the focused component as possible. However since the focus visuals extend
|
|
365
|
+
// past the bounds of the component, in cases where additional components are positioned directly next to this one, we'd
|
|
366
|
+
// get zorder issues causing most of the focus rect to be obscured. So we go up the tree until we find a component who's
|
|
367
|
+
// bounds will fix the entire focus rect.
|
|
368
|
+
winrt::com_ptr<ComponentView> ComponentView::focusVisualRoot(const facebook::react::Rect &focusRect) noexcept {
|
|
369
|
+
auto compVisual =
|
|
370
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(OuterVisual());
|
|
371
|
+
if (!compVisual) {
|
|
372
|
+
return get_strong();
|
|
373
|
+
// When not using lifted composition, force the focus visual to host within its own component, as we do not support
|
|
374
|
+
// ParentForTransform
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (facebook::react::Rect::intersect(focusRect, m_layoutMetrics.frame) == focusRect) {
|
|
378
|
+
return get_strong();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (!m_parent) {
|
|
382
|
+
return get_strong();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return m_parent.as<ComponentView>()->focusVisualRoot(
|
|
386
|
+
{{focusRect.origin.x + m_layoutMetrics.frame.origin.x, focusRect.origin.y + m_layoutMetrics.frame.origin.y},
|
|
387
|
+
focusRect.size});
|
|
388
|
+
}
|
|
389
|
+
|
|
320
390
|
void ComponentView::onGotFocus(
|
|
321
391
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
322
392
|
if (args.OriginalSource() == Tag()) {
|
|
323
393
|
m_eventEmitter->onFocus();
|
|
324
394
|
if (viewProps()->enableFocusRing) {
|
|
325
|
-
|
|
395
|
+
facebook::react::Rect focusRect = m_layoutMetrics.frame;
|
|
396
|
+
focusRect.origin.x -= (FOCUS_VISUAL_WIDTH * 2);
|
|
397
|
+
focusRect.origin.y -= (FOCUS_VISUAL_WIDTH * 2);
|
|
398
|
+
focusRect.size.width += (FOCUS_VISUAL_WIDTH * 2);
|
|
399
|
+
focusRect.size.height += (FOCUS_VISUAL_WIDTH * 2);
|
|
400
|
+
focusVisualRoot(focusRect)->hostFocusVisual(true, get_strong());
|
|
326
401
|
}
|
|
327
402
|
if (m_uiaProvider) {
|
|
328
403
|
auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
|
|
@@ -493,39 +568,70 @@ facebook::react::BorderMetrics ComponentView::focusBorderMetrics(
|
|
|
493
568
|
return metrics;
|
|
494
569
|
}
|
|
495
570
|
|
|
496
|
-
void ComponentView::
|
|
497
|
-
if ((m_flags & ComponentViewFeatures::FocusVisual) == ComponentViewFeatures::FocusVisual) {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
571
|
+
void ComponentView::hostFocusVisual(bool show, winrt::com_ptr<ComponentView> view) noexcept {
|
|
572
|
+
if ((view->m_flags & ComponentViewFeatures::FocusVisual) == ComponentViewFeatures::FocusVisual) {
|
|
573
|
+
// Any previous view showing focus visuals should have removed them before another shows it
|
|
574
|
+
assert(
|
|
575
|
+
!m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
|
|
576
|
+
m_focusPrimitive->m_focusVisualComponent == view);
|
|
577
|
+
assert(
|
|
578
|
+
!m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
|
|
579
|
+
view->m_componentHostingFocusVisual.get() == this);
|
|
580
|
+
if (show && !view->m_componentHostingFocusVisual) {
|
|
581
|
+
view->m_componentHostingFocusVisual = get_strong();
|
|
582
|
+
|
|
583
|
+
if (!m_focusPrimitive) {
|
|
584
|
+
m_focusPrimitive = std::make_unique<FocusPrimitive>();
|
|
506
585
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
586
|
+
m_focusPrimitive->m_focusVisualComponent = view;
|
|
587
|
+
|
|
588
|
+
if (!m_focusPrimitive->m_focusVisual) {
|
|
589
|
+
m_focusPrimitive->m_focusVisual = m_compContext.CreateSpriteVisual();
|
|
590
|
+
auto hostingVisual =
|
|
591
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
592
|
+
visualToHostFocus())
|
|
593
|
+
.as<winrt::Microsoft::UI::Composition::ContainerVisual>();
|
|
594
|
+
if (hostingVisual) {
|
|
595
|
+
hostingVisual.Children().InsertAtTop(
|
|
596
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
597
|
+
m_focusPrimitive->m_focusVisual));
|
|
598
|
+
} else {
|
|
599
|
+
assert(
|
|
600
|
+
view.get() ==
|
|
601
|
+
this); // When not using lifted comp, focus visuals should always host within their own component
|
|
602
|
+
OuterVisual().InsertAt(m_focusPrimitive->m_focusVisual, 1);
|
|
603
|
+
}
|
|
510
604
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
522
|
-
m_focusInnerPrimitive->finalize(innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
605
|
+
|
|
606
|
+
m_focusPrimitive->m_focusVisual.IsVisible(true);
|
|
607
|
+
assert(view->viewProps()->enableFocusRing);
|
|
608
|
+
if (!m_focusPrimitive->m_focusInnerPrimitive) {
|
|
609
|
+
m_focusPrimitive->m_focusInnerPrimitive = std::make_shared<BorderPrimitive>(*this);
|
|
610
|
+
m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusInnerPrimitive->RootVisual(), 0);
|
|
611
|
+
}
|
|
612
|
+
if (!m_focusPrimitive->m_focusOuterPrimitive) {
|
|
613
|
+
m_focusPrimitive->m_focusOuterPrimitive = std::make_shared<BorderPrimitive>(*this);
|
|
614
|
+
m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusOuterPrimitive->RootVisual(), 0);
|
|
523
615
|
}
|
|
524
|
-
if (
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
616
|
+
if (auto focusVisual =
|
|
617
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
618
|
+
m_focusPrimitive->m_focusVisual)) {
|
|
619
|
+
auto outerVisual =
|
|
620
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
621
|
+
view->OuterVisual());
|
|
622
|
+
focusVisual.ParentForTransform(outerVisual);
|
|
528
623
|
}
|
|
624
|
+
updateFocusLayoutMetrics();
|
|
625
|
+
auto innerFocusMetrics = view->focusLayoutMetrics(true /*inner*/);
|
|
626
|
+
m_focusPrimitive->m_focusInnerPrimitive->finalize(
|
|
627
|
+
innerFocusMetrics, view->focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
628
|
+
auto outerFocusMetrics = view->focusLayoutMetrics(false /*inner*/);
|
|
629
|
+
m_focusPrimitive->m_focusOuterPrimitive->finalize(
|
|
630
|
+
outerFocusMetrics, view->focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
631
|
+
} else if (!show && view->m_componentHostingFocusVisual && m_focusPrimitive) {
|
|
632
|
+
m_focusPrimitive->m_focusVisualComponent = nullptr;
|
|
633
|
+
m_focusPrimitive->m_focusVisual.IsVisible(false);
|
|
634
|
+
view->m_componentHostingFocusVisual = nullptr;
|
|
529
635
|
}
|
|
530
636
|
}
|
|
531
637
|
}
|
|
@@ -20,6 +20,13 @@ struct CompContext;
|
|
|
20
20
|
|
|
21
21
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
22
22
|
|
|
23
|
+
struct FocusPrimitive {
|
|
24
|
+
std::shared_ptr<BorderPrimitive> m_focusInnerPrimitive;
|
|
25
|
+
std::shared_ptr<BorderPrimitive> m_focusOuterPrimitive;
|
|
26
|
+
winrt::com_ptr<ComponentView> m_focusVisualComponent{nullptr}; // The owning component of focus visuals being hosted
|
|
27
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_focusVisual{nullptr};
|
|
28
|
+
};
|
|
29
|
+
|
|
23
30
|
struct ComponentView : public ComponentViewT<
|
|
24
31
|
ComponentView,
|
|
25
32
|
winrt::Microsoft::ReactNative::implementation::ComponentView,
|
|
@@ -125,13 +132,10 @@ struct ComponentView : public ComponentViewT<
|
|
|
125
132
|
facebook::react::SharedViewEventEmitter m_eventEmitter;
|
|
126
133
|
|
|
127
134
|
private:
|
|
128
|
-
void updateFocusLayoutMetrics(
|
|
135
|
+
void updateFocusLayoutMetrics() noexcept;
|
|
129
136
|
void updateClippingPath(
|
|
130
137
|
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
131
138
|
const facebook::react::ViewProps &viewProps) noexcept;
|
|
132
|
-
void finalizeFocusVisual(
|
|
133
|
-
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
134
|
-
const facebook::react::ViewProps &viewProps) noexcept;
|
|
135
139
|
void UpdateCenterPropertySet() noexcept;
|
|
136
140
|
void FinalizeTransform(
|
|
137
141
|
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
@@ -140,16 +144,18 @@ struct ComponentView : public ComponentViewT<
|
|
|
140
144
|
facebook::react::BorderMetrics focusBorderMetrics(bool inner, const facebook::react::LayoutMetrics &layoutMetrics)
|
|
141
145
|
const noexcept;
|
|
142
146
|
|
|
147
|
+
virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual visualToHostFocus() noexcept;
|
|
148
|
+
virtual winrt::com_ptr<ComponentView> focusVisualRoot(const facebook::react::Rect &focusRect) noexcept;
|
|
149
|
+
|
|
143
150
|
bool m_hasTransformMatrixFacade : 1 {false};
|
|
144
|
-
bool m_showingFocusVisual : 1 {false};
|
|
145
151
|
bool m_FinalizeTransform : 1 {false};
|
|
146
152
|
bool m_tooltipTracked : 1 {false};
|
|
147
153
|
ComponentViewFeatures m_flags;
|
|
148
|
-
void
|
|
154
|
+
void hostFocusVisual(bool show, winrt::com_ptr<ComponentView> view) noexcept;
|
|
155
|
+
winrt::com_ptr<ComponentView>
|
|
156
|
+
m_componentHostingFocusVisual; // The component that we are showing our focus visuals within
|
|
149
157
|
std::shared_ptr<BorderPrimitive> m_borderPrimitive;
|
|
150
|
-
std::
|
|
151
|
-
std::shared_ptr<BorderPrimitive> m_focusOuterPrimitive;
|
|
152
|
-
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_focusVisual{nullptr};
|
|
158
|
+
std::unique_ptr<FocusPrimitive> m_focusPrimitive{nullptr};
|
|
153
159
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_outerVisual{nullptr};
|
|
154
160
|
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::IInspectable>> m_themeChangedEvent;
|
|
155
161
|
};
|
|
@@ -176,7 +182,6 @@ struct ViewComponentView : public ViewComponentViewT<
|
|
|
176
182
|
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
177
183
|
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
|
|
178
184
|
void prepareForRecycle() noexcept override;
|
|
179
|
-
bool TryFocus() noexcept;
|
|
180
185
|
bool focusable() const noexcept override;
|
|
181
186
|
void OnKeyDown(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
|
|
182
187
|
void OnKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
|
|
@@ -1258,4 +1258,14 @@ std::string ScrollViewComponentView::DefaultControlType() const noexcept {
|
|
|
1258
1258
|
return "scrollbar";
|
|
1259
1259
|
}
|
|
1260
1260
|
|
|
1261
|
+
winrt::com_ptr<ComponentView> ScrollViewComponentView::focusVisualRoot(
|
|
1262
|
+
const facebook::react::Rect &focusRect) noexcept {
|
|
1263
|
+
return get_strong();
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
|
|
1267
|
+
ScrollViewComponentView::visualToHostFocus() noexcept {
|
|
1268
|
+
return m_scrollVisual;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1261
1271
|
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
@@ -110,6 +110,9 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
110
110
|
bool lineRight(bool animate) noexcept;
|
|
111
111
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept override;
|
|
112
112
|
|
|
113
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual visualToHostFocus() noexcept override;
|
|
114
|
+
winrt::com_ptr<ComponentView> focusVisualRoot(const facebook::react::Rect &focusRect) noexcept override;
|
|
115
|
+
|
|
113
116
|
private:
|
|
114
117
|
void updateContentVisualSize() noexcept;
|
|
115
118
|
bool scrollToEnd(bool animate) noexcept;
|
package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
CHANGED
|
@@ -165,6 +165,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
165
165
|
|
|
166
166
|
//@cmember Show the caret
|
|
167
167
|
BOOL TxShowCaret(BOOL fShow) override {
|
|
168
|
+
// Only show the caret if we have focus
|
|
169
|
+
if (fShow && !m_outer->m_hasFocus) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
168
172
|
m_outer->ShowCaret(m_outer->windowsTextInputProps().caretHidden ? false : fShow);
|
|
169
173
|
return true;
|
|
170
174
|
}
|
|
@@ -915,6 +919,7 @@ void WindowsTextInputComponentView::UnmountChildComponentView(
|
|
|
915
919
|
|
|
916
920
|
void WindowsTextInputComponentView::onLostFocus(
|
|
917
921
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
922
|
+
m_hasFocus = false;
|
|
918
923
|
Super::onLostFocus(args);
|
|
919
924
|
if (m_textServices) {
|
|
920
925
|
LRESULT lresult;
|
|
@@ -926,6 +931,7 @@ void WindowsTextInputComponentView::onLostFocus(
|
|
|
926
931
|
|
|
927
932
|
void WindowsTextInputComponentView::onGotFocus(
|
|
928
933
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
934
|
+
m_hasFocus = true;
|
|
929
935
|
Super::onGotFocus(args);
|
|
930
936
|
if (m_textServices) {
|
|
931
937
|
LRESULT lresult;
|
|
@@ -26,7 +26,7 @@ UnimplementedNativeViewComponentView::UnimplementedNativeViewComponentView(
|
|
|
26
26
|
~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps |
|
|
27
27
|
ComponentViewFeatures::NativeBorder)) {
|
|
28
28
|
m_labelVisual = compContext.CreateSpriteVisual();
|
|
29
|
-
OuterVisual().InsertAt(m_labelVisual,
|
|
29
|
+
OuterVisual().InsertAt(m_labelVisual, 0);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
winrt::Microsoft::ReactNative::ComponentView UnimplementedNativeViewComponentView::Create(
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.74.
|
|
13
|
+
<ReactNativeWindowsVersion>0.74.26</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>74</ReactNativeWindowsMinor>
|
|
16
|
-
<ReactNativeWindowsPatch>
|
|
16
|
+
<ReactNativeWindowsPatch>26</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
|
-
<ReactNativeWindowsCommitId>
|
|
18
|
+
<ReactNativeWindowsCommitId>242effb4b70c5c442b0568203fb2de1818b9f8a3</ReactNativeWindowsCommitId>
|
|
19
19
|
</PropertyGroup>
|
|
20
20
|
</Project>
|