33
33
namespace winrt ::Microsoft::ReactNative::Composition::implementation {
34
34
35
35
constexpr float FOCUS_VISUAL_WIDTH = 2 .0f ;
36
+ constexpr float FOCUS_VISUAL_RADIUS = 3 .0f ;
36
37
37
38
// m_outerVisual
38
39
// |
@@ -228,29 +229,11 @@ void ComponentView::updateFocusLayoutMetrics() noexcept {
228
229
facebook::react::RectangleEdges<bool > nudgeEdges;
229
230
auto scaleFactor = m_focusPrimitive->m_focusVisualComponent ->m_layoutMetrics .pointScaleFactor ;
230
231
if (m_focusPrimitive) {
232
+ auto nudgeEdges = m_focusPrimitive->m_focusVisualComponent ->focusNudges ();
231
233
if (m_focusPrimitive->m_focusOuterPrimitive ) {
232
234
auto outerFocusMetrics = m_focusPrimitive->m_focusVisualComponent ->focusLayoutMetrics (false /* inner*/ );
233
-
234
- if (outerFocusMetrics.frame .origin .x < 0 ) {
235
- nudgeEdges.left = true ;
236
- }
237
- if (outerFocusMetrics.frame .origin .y < 0 ) {
238
- nudgeEdges.top = true ;
239
- }
240
- if (outerFocusMetrics.frame .getMaxX () > m_layoutMetrics.frame .getMaxX ()) {
241
- nudgeEdges.right = true ;
242
- }
243
- if (outerFocusMetrics.frame .getMaxY () > m_layoutMetrics.frame .getMaxY ()) {
244
- nudgeEdges.bottom = true ;
245
- }
246
-
247
235
m_focusPrimitive->m_focusOuterPrimitive ->RootVisual ().Size (
248
- {outerFocusMetrics.frame .size .width * scaleFactor -
249
- (nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0 ) -
250
- (nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0 ),
251
- outerFocusMetrics.frame .size .height * scaleFactor -
252
- (nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0 ) -
253
- (nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0 )});
236
+ {outerFocusMetrics.frame .size .width * scaleFactor, outerFocusMetrics.frame .size .height * scaleFactor});
254
237
m_focusPrimitive->m_focusOuterPrimitive ->RootVisual ().Offset (
255
238
{nudgeEdges.left ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
256
239
nudgeEdges.top ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
@@ -261,15 +244,10 @@ void ComponentView::updateFocusLayoutMetrics() noexcept {
261
244
if (m_focusPrimitive->m_focusInnerPrimitive ) {
262
245
auto innerFocusMetrics = m_focusPrimitive->m_focusVisualComponent ->focusLayoutMetrics (true /* inner*/ );
263
246
m_focusPrimitive->m_focusInnerPrimitive ->RootVisual ().Size (
264
- {innerFocusMetrics.frame .size .width * scaleFactor -
265
- (nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0 ) -
266
- (nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0 ),
267
- innerFocusMetrics.frame .size .height * scaleFactor -
268
- (nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0 ) -
269
- (nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0 )});
247
+ {innerFocusMetrics.frame .size .width * scaleFactor, innerFocusMetrics.frame .size .height * scaleFactor});
270
248
m_focusPrimitive->m_focusInnerPrimitive ->RootVisual ().Offset (
271
- {nudgeEdges.left ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
272
- nudgeEdges.top ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
249
+ {nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * scaleFactor) : ( -FOCUS_VISUAL_WIDTH * scaleFactor) ,
250
+ nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * scaleFactor) : ( -FOCUS_VISUAL_WIDTH * scaleFactor) ,
273
251
0 .0f });
274
252
m_focusPrimitive->m_focusInnerPrimitive ->markNeedsUpdate ();
275
253
}
@@ -538,7 +516,33 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView:
538
516
return m_outerVisual ? m_outerVisual : Visual ();
539
517
}
540
518
541
- facebook::react::LayoutMetrics ComponentView::focusLayoutMetrics (bool inner) const noexcept {
519
+ // If the focus visual would extend past the bounds of the hosting visual,
520
+ // then we will nudge the focus visual back inside the hosting visuals bounds.
521
+ facebook::react::RectangleEdges<bool > ComponentView::focusNudges () const noexcept {
522
+ facebook::react::RectangleEdges<bool > nudgeEdges;
523
+
524
+ // Always use outer focus metrics to determine if we need to nudge the focus rect over to fit
525
+ facebook::react::LayoutMetrics layoutMetrics = focusLayoutMetricsNoNudge (false /* inner*/ );
526
+
527
+ Assert (m_componentHostingFocusVisual);
528
+
529
+ if (layoutMetrics.frame .origin .x < 0 ) {
530
+ nudgeEdges.left = true ;
531
+ }
532
+ if (layoutMetrics.frame .origin .y < 0 ) {
533
+ nudgeEdges.top = true ;
534
+ }
535
+ if (layoutMetrics.frame .getMaxX () > m_componentHostingFocusVisual->m_layoutMetrics .frame .getMaxX ()) {
536
+ nudgeEdges.right = true ;
537
+ }
538
+ if (layoutMetrics.frame .getMaxY () > m_componentHostingFocusVisual->m_layoutMetrics .frame .getMaxY ()) {
539
+ nudgeEdges.bottom = true ;
540
+ }
541
+
542
+ return nudgeEdges;
543
+ }
544
+
545
+ facebook::react::LayoutMetrics ComponentView::focusLayoutMetricsNoNudge (bool inner) const noexcept {
542
546
facebook::react::LayoutMetrics layoutMetrics = m_layoutMetrics;
543
547
layoutMetrics.frame .origin .x -= FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
544
548
layoutMetrics.frame .origin .y -= FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
@@ -547,6 +551,28 @@ facebook::react::LayoutMetrics ComponentView::focusLayoutMetrics(bool inner) con
547
551
return layoutMetrics;
548
552
}
549
553
554
+ facebook::react::LayoutMetrics ComponentView::focusLayoutMetrics (bool inner) const noexcept {
555
+ auto nudgeEdges = focusNudges ();
556
+ auto layoutMetrics = focusLayoutMetricsNoNudge (inner);
557
+
558
+ if (nudgeEdges.left ) {
559
+ layoutMetrics.frame .origin .x += FOCUS_VISUAL_WIDTH * 2 ;
560
+ layoutMetrics.frame .size .width -= FOCUS_VISUAL_WIDTH * 2 ;
561
+ }
562
+ if (nudgeEdges.top ) {
563
+ layoutMetrics.frame .origin .y += FOCUS_VISUAL_WIDTH * 2 ;
564
+ layoutMetrics.frame .size .height -= FOCUS_VISUAL_WIDTH * 2 ;
565
+ }
566
+ if (nudgeEdges.right ) {
567
+ layoutMetrics.frame .size .width -= FOCUS_VISUAL_WIDTH * 2 ;
568
+ }
569
+ if (nudgeEdges.bottom ) {
570
+ layoutMetrics.frame .size .height -= FOCUS_VISUAL_WIDTH * 2 ;
571
+ }
572
+
573
+ return layoutMetrics;
574
+ }
575
+
550
576
facebook::react::BorderMetrics ComponentView::focusBorderMetrics (
551
577
bool inner,
552
578
const facebook::react::LayoutMetrics &layoutMetrics) const noexcept {
@@ -556,22 +582,31 @@ facebook::react::BorderMetrics ComponentView::focusBorderMetrics(
556
582
innerColor.m_platformColor .push_back (inner ? " FocusVisualSecondary" : " FocusVisualPrimary" );
557
583
metrics.borderColors .bottom = metrics.borderColors .left = metrics.borderColors .right = metrics.borderColors .top =
558
584
innerColor;
559
- if (metrics.borderRadii .bottomLeft .horizontal != 0 )
560
- metrics.borderRadii .bottomLeft .horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
561
- if (metrics.borderRadii .bottomLeft .vertical != 0 )
562
- metrics.borderRadii .bottomLeft .vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
563
- if (metrics.borderRadii .bottomRight .horizontal != 0 )
564
- metrics.borderRadii .bottomRight .horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
565
- if (metrics.borderRadii .bottomRight .vertical != 0 )
566
- metrics.borderRadii .bottomRight .vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
567
- if (metrics.borderRadii .topLeft .horizontal != 0 )
568
- metrics.borderRadii .topLeft .horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
569
- if (metrics.borderRadii .topLeft .vertical != 0 )
570
- metrics.borderRadii .topLeft .vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
571
- if (metrics.borderRadii .topRight .horizontal != 0 )
572
- metrics.borderRadii .topRight .horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
573
- if (metrics.borderRadii .topRight .vertical != 0 )
574
- metrics.borderRadii .topRight .vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
585
+
586
+ metrics.borderRadii .bottomLeft .horizontal =
587
+ (metrics.borderRadii .bottomLeft .horizontal ? metrics.borderRadii .bottomLeft .horizontal : FOCUS_VISUAL_RADIUS) +
588
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
589
+ metrics.borderRadii .bottomLeft .vertical =
590
+ (metrics.borderRadii .bottomLeft .vertical ? metrics.borderRadii .bottomLeft .vertical : FOCUS_VISUAL_RADIUS) +
591
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
592
+ metrics.borderRadii .bottomRight .horizontal =
593
+ (metrics.borderRadii .bottomRight .horizontal ? metrics.borderRadii .bottomRight .horizontal : FOCUS_VISUAL_RADIUS) +
594
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
595
+ metrics.borderRadii .bottomRight .vertical =
596
+ (metrics.borderRadii .bottomRight .vertical ? metrics.borderRadii .bottomRight .vertical : FOCUS_VISUAL_RADIUS) +
597
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
598
+ metrics.borderRadii .topLeft .horizontal =
599
+ (metrics.borderRadii .topLeft .horizontal ? metrics.borderRadii .topLeft .horizontal : FOCUS_VISUAL_RADIUS) +
600
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
601
+ metrics.borderRadii .topLeft .vertical =
602
+ (metrics.borderRadii .topLeft .vertical ? metrics.borderRadii .topLeft .vertical : FOCUS_VISUAL_RADIUS) +
603
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
604
+ metrics.borderRadii .topRight .horizontal =
605
+ (metrics.borderRadii .topRight .horizontal ? metrics.borderRadii .topRight .horizontal : FOCUS_VISUAL_RADIUS) +
606
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
607
+ metrics.borderRadii .topRight .vertical =
608
+ (metrics.borderRadii .topRight .vertical ? metrics.borderRadii .topRight .vertical : FOCUS_VISUAL_RADIUS) +
609
+ FOCUS_VISUAL_WIDTH * (inner ? 1 : 2 );
575
610
576
611
metrics.borderStyles .bottom = metrics.borderStyles .left = metrics.borderStyles .right = metrics.borderStyles .top =
577
612
facebook::react::BorderStyle::Solid;
0 commit comments