tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestEventRegions.cpp (8269B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "APZCTreeManagerTester.h"
      8 #include "APZTestCommon.h"
      9 #include "InputUtils.h"
     10 #include "mozilla/layers/LayersTypes.h"
     11 
     12 class APZEventRegionsTester : public APZCTreeManagerTester {
     13 protected:
     14  UniquePtr<ScopedLayerTreeRegistration> registration;
     15  TestAsyncPanZoomController* rootApzc;
     16 
     17  void CreateEventRegionsLayerTree1() {
     18    const char* treeShape = "x(xx)";
     19    LayerIntRect layerVisibleRects[] = {
     20        LayerIntRect(0, 0, 200, 200),    // root
     21        LayerIntRect(0, 0, 100, 200),    // left half
     22        LayerIntRect(0, 100, 200, 100),  // bottom half
     23    };
     24    CreateScrollData(treeShape, layerVisibleRects);
     25    SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID);
     26    SetScrollableFrameMetrics(layers[1],
     27                              ScrollableLayerGuid::START_SCROLL_ID + 1);
     28    SetScrollableFrameMetrics(layers[2],
     29                              ScrollableLayerGuid::START_SCROLL_ID + 2);
     30    SetScrollHandoff(layers[1], root);
     31    SetScrollHandoff(layers[2], root);
     32 
     33    registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
     34    UpdateHitTestingTree();
     35    rootApzc = ApzcOf(root);
     36  }
     37 
     38  void CreateEventRegionsLayerTree2() {
     39    const char* treeShape = "x(x)";
     40    LayerIntRect layerVisibleRects[] = {
     41        LayerIntRect(0, 0, 100, 500),
     42        LayerIntRect(0, 150, 100, 100),
     43    };
     44    CreateScrollData(treeShape, layerVisibleRects);
     45    SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID);
     46 
     47    registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
     48    UpdateHitTestingTree();
     49    rootApzc = ApzcOf(root);
     50  }
     51 
     52  void CreateBug1117712LayerTree() {
     53    const char* treeShape = "x(x(x)x)";
     54    // LayerID               0 1 2 3
     55    // 0 is the root
     56    // 1 is a container layer whose sole purpose to make a non-empty ancestor
     57    //   transform for 2, so that 2's screen-to-apzc and apzc-to-gecko
     58    //   transforms are different from 3's.
     59    // 2 is a small layer that is the actual target
     60    // 3 is a big layer obscuring 2 with a dispatch-to-content region
     61    LayerIntRect layerVisibleRects[] = {
     62        LayerIntRect(0, 0, 100, 100),
     63        LayerIntRect(0, 0, 0, 0),
     64        LayerIntRect(0, 0, 10, 10),
     65        LayerIntRect(0, 0, 100, 100),
     66    };
     67    Matrix4x4 layerTransforms[] = {
     68        Matrix4x4(),
     69        Matrix4x4::Translation(50, 0, 0),
     70        Matrix4x4(),
     71        Matrix4x4(),
     72    };
     73    CreateScrollData(treeShape, layerVisibleRects, layerTransforms);
     74 
     75    SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID,
     76                              CSSRect(0, 0, 10, 10));
     77    SetScrollableFrameMetrics(layers[3],
     78                              ScrollableLayerGuid::START_SCROLL_ID + 1,
     79                              CSSRect(0, 0, 100, 100));
     80    SetScrollHandoff(layers[3], layers[2]);
     81 
     82    registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
     83    UpdateHitTestingTree();
     84  }
     85 };
     86 
     87 class APZEventRegionsTesterMock : public APZEventRegionsTester {
     88 public:
     89  APZEventRegionsTesterMock() { CreateMockHitTester(); }
     90 };
     91 
     92 TEST_F(APZEventRegionsTesterMock, HitRegionImmediateResponse) {
     93  CreateEventRegionsLayerTree1();
     94 
     95  TestAsyncPanZoomController* root = ApzcOf(layers[0]);
     96  TestAsyncPanZoomController* left = ApzcOf(layers[1]);
     97  TestAsyncPanZoomController* bottom = ApzcOf(layers[2]);
     98 
     99  MockFunction<void(std::string checkPointName)> check;
    100  {
    101    InSequence s;
    102    EXPECT_CALL(*mcc,
    103                HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _, _))
    104        .Times(1);
    105    EXPECT_CALL(check, Call("Tapped on left"));
    106    EXPECT_CALL(*mcc,
    107                HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _, _))
    108        .Times(1);
    109    EXPECT_CALL(check, Call("Tapped on bottom"));
    110    EXPECT_CALL(*mcc,
    111                HandleTap(TapType::eSingleTap, _, _, root->GetGuid(), _, _))
    112        .Times(1);
    113    EXPECT_CALL(check, Call("Tapped on root"));
    114    EXPECT_CALL(check, Call("Tap pending on d-t-c region"));
    115    EXPECT_CALL(*mcc,
    116                HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _, _))
    117        .Times(1);
    118    EXPECT_CALL(check, Call("Tapped on bottom again"));
    119    EXPECT_CALL(*mcc,
    120                HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _, _))
    121        .Times(1);
    122    EXPECT_CALL(check, Call("Tapped on left this time"));
    123  }
    124 
    125  TimeDuration tapDuration = TimeDuration::FromMilliseconds(100);
    126 
    127  // Tap in the exposed hit regions of each of the layers once and ensure
    128  // the clicks are dispatched right away
    129  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    130  Tap(manager, ScreenIntPoint(10, 10), tapDuration);
    131  mcc->RunThroughDelayedTasks();  // this runs the tap event
    132  check.Call("Tapped on left");
    133  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2);
    134  Tap(manager, ScreenIntPoint(110, 110), tapDuration);
    135  mcc->RunThroughDelayedTasks();  // this runs the tap event
    136  check.Call("Tapped on bottom");
    137  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    138  Tap(manager, ScreenIntPoint(110, 10), tapDuration);
    139  mcc->RunThroughDelayedTasks();  // this runs the tap event
    140  check.Call("Tapped on root");
    141 
    142  // Now tap on the dispatch-to-content region where the layers overlap
    143  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2,
    144                     {CompositorHitTestFlags::eVisibleToHitTest,
    145                      CompositorHitTestFlags::eIrregularArea});
    146  Tap(manager, ScreenIntPoint(10, 110), tapDuration);
    147  mcc->RunThroughDelayedTasks();  // this runs the main-thread timeout
    148  check.Call("Tap pending on d-t-c region");
    149  mcc->RunThroughDelayedTasks();  // this runs the tap event
    150  check.Call("Tapped on bottom again");
    151 
    152  // Now let's do that again, but simulate a main-thread response
    153  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2,
    154                     {CompositorHitTestFlags::eVisibleToHitTest,
    155                      CompositorHitTestFlags::eIrregularArea});
    156  APZEventResult result =
    157      Tap(manager, ScreenIntPoint(10, 110), tapDuration, nullptr);
    158  nsTArray<ScrollableLayerGuid> targets;
    159  targets.AppendElement(left->GetGuid());
    160  manager->SetTargetAPZC(result.mInputBlockId, targets);
    161  while (mcc->RunThroughDelayedTasks());  // this runs the tap event
    162  check.Call("Tapped on left this time");
    163 }
    164 
    165 TEST_F(APZEventRegionsTesterMock, HitRegionAccumulatesChildren) {
    166  CreateEventRegionsLayerTree2();
    167 
    168  // Tap in the area of the child layer that's not directly included in the
    169  // parent layer's hit region. Verify that it comes out of the APZC's
    170  // content controller, which indicates the input events got routed correctly
    171  // to the APZC.
    172  EXPECT_CALL(*mcc,
    173              HandleTap(TapType::eSingleTap, _, _, rootApzc->GetGuid(), _, _))
    174      .Times(1);
    175  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    176  Tap(manager, ScreenIntPoint(10, 160), TimeDuration::FromMilliseconds(100));
    177 }
    178 
    179 TEST_F(APZEventRegionsTesterMock, Bug1117712) {
    180  CreateBug1117712LayerTree();
    181 
    182  TestAsyncPanZoomController* apzc2 = ApzcOf(layers[2]);
    183 
    184  // These touch events should hit the dispatch-to-content region of layers[3]
    185  // and so get queued with that APZC as the tentative target.
    186  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    187                     {CompositorHitTestFlags::eVisibleToHitTest,
    188                      CompositorHitTestFlags::eIrregularArea});
    189  APZEventResult result = Tap(manager, ScreenIntPoint(55, 5),
    190                              TimeDuration::FromMilliseconds(100), nullptr);
    191  // But now we tell the APZ that really it hit layers[2], and expect the tap
    192  // to be delivered at the correct coordinates.
    193  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(55, 5), 0,
    194                              apzc2->GetGuid(), _, _))
    195      .Times(1);
    196 
    197  nsTArray<ScrollableLayerGuid> targets;
    198  targets.AppendElement(apzc2->GetGuid());
    199  manager->SetTargetAPZC(result.mInputBlockId, targets);
    200 }