@@ -38,8 +38,10 @@ using fuchsia::scenic::scheduling::FuturePresentationTimes;
38
38
using fuchsia::scenic::scheduling::PresentReceivedInfo;
39
39
using ::testing::_;
40
40
using ::testing::AllOf;
41
+ using ::testing::Contains;
41
42
using ::testing::ElementsAre;
42
43
using ::testing::Eq;
44
+ using ::testing::Field;
43
45
using ::testing::FieldsAre;
44
46
using ::testing::IsEmpty;
45
47
using ::testing::Matcher;
@@ -297,6 +299,16 @@ Matcher<std::shared_ptr<FakeTransform>> IsClipTransformLayer(
297
299
/* content*/ _,
298
300
/* hit_regions*/ _));
299
301
}
302
+
303
+ Matcher<std::shared_ptr<FakeTransform>> IsInputShield () {
304
+ return Pointee (AllOf (
305
+ // Must not clip the hit region.
306
+ Field (" clip_bounds" , &FakeTransform::clip_bounds, Eq (std::nullopt)),
307
+ // Hit region must be "infinite".
308
+ Field (" hit_regions" , &FakeTransform::hit_regions,
309
+ Contains (flutter_runner::testing::kInfiniteHitRegion ))));
310
+ }
311
+
300
312
fuchsia::ui::composition::OnNextFrameBeginValues WithPresentCredits (
301
313
uint32_t additional_present_credits) {
302
314
fuchsia::ui::composition::OnNextFrameBeginValues values;
@@ -396,15 +408,18 @@ class FlatlandExternalViewEmbedderTest : public ::testing::Test {
396
408
fuchsia::ui::composition::FlatlandHandle flatland =
397
409
fake_flatland_.ConnectFlatland (session_subloop_->dispatcher ());
398
410
399
- auto test_name =
411
+ const auto test_name =
400
412
::testing::UnitTest::GetInstance ()->current_test_info()->name();
413
+ const auto max_frames_in_flight = 1 ;
414
+ const auto vsync_offset = fml::TimeDelta::Zero ();
401
415
return std::make_shared<FlatlandConnection>(
402
- std::move (test_name), std::move (flatland), []() { FAIL (); },
403
- [](auto ...) {}, 1 , fml::TimeDelta::Zero ());
416
+ std::move (test_name), std::move (flatland),
417
+ /* error_callback=*/ [] { FAIL (); }, /* ofpe_callback=*/ [](auto ...) {},
418
+ max_frames_in_flight, vsync_offset);
404
419
}
405
420
406
421
// Primary loop and subloop for the FakeFlatland instance to process its
407
- // messages. The subloop allocates it's own zx_port_t, allowing us to use a
422
+ // messages. The subloop allocates its own zx_port_t, allowing us to use a
408
423
// separate port for each end of the message channel, rather than sharing a
409
424
// single one. Dual ports allow messages and responses to be intermingled,
410
425
// which is how production code behaves; this improves test realism.
@@ -1476,4 +1491,143 @@ TEST_F(FlatlandExternalViewEmbedderTest, SimpleScene_OverlappingHitRegions) {
1476
1491
fuchsia::ui::composition::HitTestInteraction::DEFAULT)})}));
1477
1492
}
1478
1493
1494
+ TEST_F (FlatlandExternalViewEmbedderTest, ViewportCoveredWithInputInterceptor) {
1495
+ fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher;
1496
+ fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
1497
+ fuchsia::ui::views::ViewCreationToken view_creation_token;
1498
+ fuchsia::ui::views::ViewRef view_ref;
1499
+ auto view_creation_token_status = zx::channel::create (
1500
+ 0u , &viewport_creation_token.value , &view_creation_token.value );
1501
+ ASSERT_EQ (view_creation_token_status, ZX_OK);
1502
+ auto view_ref_pair = scenic::ViewRefPair::New ();
1503
+ view_ref_pair.view_ref .Clone (&view_ref);
1504
+
1505
+ // Create the `FlatlandExternalViewEmbedder` and pump the message loop until
1506
+ // the initial scene graph is setup.
1507
+ FlatlandExternalViewEmbedder external_view_embedder (
1508
+ std::move (view_creation_token),
1509
+ fuchsia::ui::views::ViewIdentityOnCreation{
1510
+ .view_ref = std::move (view_ref_pair.view_ref ),
1511
+ .view_ref_control = std::move (view_ref_pair.control_ref ),
1512
+ },
1513
+ fuchsia::ui::composition::ViewBoundProtocols{},
1514
+ parent_viewport_watcher.NewRequest (), flatland_connection (),
1515
+ fake_surface_producer (),
1516
+ /* intercept_all_input=*/ true // Enables the interceptor.
1517
+ );
1518
+ flatland_connection ()->Present ();
1519
+ loop ().RunUntilIdle ();
1520
+ fake_flatland ().FireOnNextFrameBeginEvent (WithPresentCredits (1u ));
1521
+ loop ().RunUntilIdle ();
1522
+ EXPECT_THAT (fake_flatland ().graph (),
1523
+ IsFlutterGraph (parent_viewport_watcher, viewport_creation_token,
1524
+ view_ref, {IsInputShield ()}));
1525
+
1526
+ // Create the view before drawing the scene.
1527
+ const SkSize child_view_size_signed = SkSize::Make (256 .f , 512 .f );
1528
+ const fuchsia::math::SizeU child_view_size{
1529
+ static_cast <uint32_t >(child_view_size_signed.width ()),
1530
+ static_cast <uint32_t >(child_view_size_signed.height ())};
1531
+ auto [child_view_token, child_viewport_token] = ViewTokenPair::New ();
1532
+ const uint32_t child_view_id = child_viewport_token.value .get ();
1533
+
1534
+ const int kOpacity = 200 ;
1535
+ const float kOpacityFloat = 200 / 255 .0f ;
1536
+ const fuchsia::math::VecF kScale {3 .0f , 4 .0f };
1537
+
1538
+ auto matrix = SkMatrix::I ();
1539
+ matrix.setScaleX (kScale .x );
1540
+ matrix.setScaleY (kScale .y );
1541
+
1542
+ auto mutators_stack = flutter::MutatorsStack ();
1543
+ mutators_stack.PushOpacity (kOpacity );
1544
+ mutators_stack.PushTransform (matrix);
1545
+
1546
+ flutter::EmbeddedViewParams child_view_params (matrix, child_view_size_signed,
1547
+ mutators_stack);
1548
+ external_view_embedder.CreateView (
1549
+ child_view_id, []() {},
1550
+ [](fuchsia::ui::composition::ContentId,
1551
+ fuchsia::ui::composition::ChildViewWatcherHandle) {});
1552
+ const SkRect child_view_occlusion_hint = SkRect::MakeLTRB (1 , 2 , 3 , 4 );
1553
+ const fuchsia::math::Inset child_view_inset{
1554
+ static_cast <int32_t >(child_view_occlusion_hint.top ()),
1555
+ static_cast <int32_t >(child_view_occlusion_hint.right ()),
1556
+ static_cast <int32_t >(child_view_occlusion_hint.bottom ()),
1557
+ static_cast <int32_t >(child_view_occlusion_hint.left ())};
1558
+ external_view_embedder.SetViewProperties (
1559
+ child_view_id, child_view_occlusion_hint, /* hit_testable=*/ false ,
1560
+ /* focusable=*/ false );
1561
+
1562
+ // We must take into account the effect of DPR on the view scale.
1563
+ const float kDPR = 2 .0f ;
1564
+ const float kInvDPR = 1 .f / kDPR ;
1565
+
1566
+ // Draw the scene. The scene graph shouldn't change yet.
1567
+ const SkISize frame_size_signed = SkISize::Make (512 , 512 );
1568
+ const fuchsia::math::SizeU frame_size{
1569
+ static_cast <uint32_t >(frame_size_signed.width ()),
1570
+ static_cast <uint32_t >(frame_size_signed.height ())};
1571
+ DrawFrameWithView (
1572
+ external_view_embedder, frame_size_signed, kDPR , child_view_id,
1573
+ child_view_params,
1574
+ [](SkCanvas* canvas) {
1575
+ const SkSize canvas_size = SkSize::Make (canvas->imageInfo ().width (),
1576
+ canvas->imageInfo ().height ());
1577
+ SkPaint rect_paint;
1578
+ rect_paint.setColor (SK_ColorGREEN);
1579
+ canvas->translate (canvas_size.width () / 4 .f ,
1580
+ canvas_size.height () / 2 .f );
1581
+ canvas->drawRect (SkRect::MakeWH (canvas_size.width () / 32 .f ,
1582
+ canvas_size.height () / 32 .f ),
1583
+ rect_paint);
1584
+ },
1585
+ [](SkCanvas* canvas) {
1586
+ const SkSize canvas_size = SkSize::Make (canvas->imageInfo ().width (),
1587
+ canvas->imageInfo ().height ());
1588
+ SkPaint rect_paint;
1589
+ rect_paint.setColor (SK_ColorRED);
1590
+ canvas->translate (canvas_size.width () * 3 .f / 4 .f ,
1591
+ canvas_size.height () / 2 .f );
1592
+ canvas->drawRect (SkRect::MakeWH (canvas_size.width () / 32 .f ,
1593
+ canvas_size.height () / 32 .f ),
1594
+ rect_paint);
1595
+ });
1596
+ EXPECT_THAT (fake_flatland ().graph (),
1597
+ IsFlutterGraph (parent_viewport_watcher, viewport_creation_token,
1598
+ view_ref, {IsInputShield ()}));
1599
+
1600
+ // Pump the message loop. The scene updates should propagate to flatland.
1601
+ loop ().RunUntilIdle ();
1602
+ fake_flatland ().FireOnNextFrameBeginEvent (WithPresentCredits (1u ));
1603
+ loop ().RunUntilIdle ();
1604
+
1605
+ EXPECT_THAT (
1606
+ fake_flatland ().graph (),
1607
+ IsFlutterGraph (
1608
+ parent_viewport_watcher, viewport_creation_token, view_ref, /* layers*/
1609
+ {IsImageLayer (
1610
+ frame_size, kFirstLayerBlendMode ,
1611
+ {IsHitRegion (
1612
+ /* x */ 128 .f ,
1613
+ /* y */ 256 .f ,
1614
+ /* width */ 16 .f ,
1615
+ /* height */ 16 .f ,
1616
+ /* hit_test */
1617
+ fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1618
+ IsViewportLayer (child_view_token, child_view_size, child_view_inset,
1619
+ {0 , 0 }, kScale , kOpacityFloat ),
1620
+ IsImageLayer (
1621
+ frame_size, kUpperLayerBlendMode ,
1622
+ {IsHitRegion (
1623
+ /* x */ 384 .f ,
1624
+ /* y */ 256 .f ,
1625
+ /* width */ 16 .f ,
1626
+ /* height */ 16 .f ,
1627
+ /* hit_test */
1628
+ fuchsia::ui::composition::HitTestInteraction::DEFAULT)}),
1629
+ IsInputShield ()},
1630
+ {kInvDPR , kInvDPR }));
1631
+ }
1632
+
1479
1633
} // namespace flutter_runner::testing
0 commit comments