summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/gtest/TestEventRegions.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/apz/test/gtest/TestEventRegions.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/gfx/layers/apz/test/gtest/TestEventRegions.cpp b/gfx/layers/apz/test/gtest/TestEventRegions.cpp
new file mode 100644
index 0000000000..0b4564b49f
--- /dev/null
+++ b/gfx/layers/apz/test/gtest/TestEventRegions.cpp
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "APZCTreeManagerTester.h"
+#include "APZTestCommon.h"
+#include "InputUtils.h"
+#include "mozilla/layers/LayersTypes.h"
+
+class APZEventRegionsTester : public APZCTreeManagerTester {
+ protected:
+ UniquePtr<ScopedLayerTreeRegistration> registration;
+ TestAsyncPanZoomController* rootApzc;
+
+ void CreateEventRegionsLayerTree1() {
+ const char* treeShape = "x(xx)";
+ LayerIntRegion layerVisibleRegions[] = {
+ LayerIntRect(0, 0, 200, 200), // root
+ LayerIntRect(0, 0, 100, 200), // left half
+ LayerIntRect(0, 100, 200, 100), // bottom half
+ };
+ CreateScrollData(treeShape, layerVisibleRegions);
+ SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID);
+ SetScrollableFrameMetrics(layers[1],
+ ScrollableLayerGuid::START_SCROLL_ID + 1);
+ SetScrollableFrameMetrics(layers[2],
+ ScrollableLayerGuid::START_SCROLL_ID + 2);
+ SetScrollHandoff(layers[1], root);
+ SetScrollHandoff(layers[2], root);
+
+ registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
+ UpdateHitTestingTree();
+ rootApzc = ApzcOf(root);
+ }
+
+ void CreateEventRegionsLayerTree2() {
+ const char* treeShape = "x(x)";
+ LayerIntRegion layerVisibleRegions[] = {
+ LayerIntRect(0, 0, 100, 500),
+ LayerIntRect(0, 150, 100, 100),
+ };
+ CreateScrollData(treeShape, layerVisibleRegions);
+ SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID);
+
+ registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
+ UpdateHitTestingTree();
+ rootApzc = ApzcOf(root);
+ }
+
+ void CreateBug1117712LayerTree() {
+ const char* treeShape = "x(x(x)x)";
+ // LayerID 0 1 2 3
+ // 0 is the root
+ // 1 is a container layer whose sole purpose to make a non-empty ancestor
+ // transform for 2, so that 2's screen-to-apzc and apzc-to-gecko
+ // transforms are different from 3's.
+ // 2 is a small layer that is the actual target
+ // 3 is a big layer obscuring 2 with a dispatch-to-content region
+ LayerIntRegion layerVisibleRegions[] = {
+ LayerIntRect(0, 0, 100, 100),
+ LayerIntRect(0, 0, 0, 0),
+ LayerIntRect(0, 0, 10, 10),
+ LayerIntRect(0, 0, 100, 100),
+ };
+ Matrix4x4 layerTransforms[] = {
+ Matrix4x4(),
+ Matrix4x4::Translation(50, 0, 0),
+ Matrix4x4(),
+ Matrix4x4(),
+ };
+ CreateScrollData(treeShape, layerVisibleRegions, layerTransforms);
+
+ SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID,
+ CSSRect(0, 0, 10, 10));
+ SetScrollableFrameMetrics(layers[3],
+ ScrollableLayerGuid::START_SCROLL_ID + 1,
+ CSSRect(0, 0, 100, 100));
+ SetScrollHandoff(layers[3], layers[2]);
+
+ registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
+ UpdateHitTestingTree();
+ }
+};
+
+class APZEventRegionsTesterMock : public APZEventRegionsTester {
+ public:
+ APZEventRegionsTesterMock() { CreateMockHitTester(); }
+};
+
+TEST_F(APZEventRegionsTesterMock, HitRegionImmediateResponse) {
+ CreateEventRegionsLayerTree1();
+
+ TestAsyncPanZoomController* root = ApzcOf(layers[0]);
+ TestAsyncPanZoomController* left = ApzcOf(layers[1]);
+ TestAsyncPanZoomController* bottom = ApzcOf(layers[2]);
+
+ MockFunction<void(std::string checkPointName)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _))
+ .Times(1);
+ EXPECT_CALL(check, Call("Tapped on left"));
+ EXPECT_CALL(*mcc,
+ HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _))
+ .Times(1);
+ EXPECT_CALL(check, Call("Tapped on bottom"));
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, root->GetGuid(), _))
+ .Times(1);
+ EXPECT_CALL(check, Call("Tapped on root"));
+ EXPECT_CALL(check, Call("Tap pending on d-t-c region"));
+ EXPECT_CALL(*mcc,
+ HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _))
+ .Times(1);
+ EXPECT_CALL(check, Call("Tapped on bottom again"));
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _))
+ .Times(1);
+ EXPECT_CALL(check, Call("Tapped on left this time"));
+ }
+
+ TimeDuration tapDuration = TimeDuration::FromMilliseconds(100);
+
+ // Tap in the exposed hit regions of each of the layers once and ensure
+ // the clicks are dispatched right away
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
+ Tap(manager, ScreenIntPoint(10, 10), tapDuration);
+ mcc->RunThroughDelayedTasks(); // this runs the tap event
+ check.Call("Tapped on left");
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2);
+ Tap(manager, ScreenIntPoint(110, 110), tapDuration);
+ mcc->RunThroughDelayedTasks(); // this runs the tap event
+ check.Call("Tapped on bottom");
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
+ Tap(manager, ScreenIntPoint(110, 10), tapDuration);
+ mcc->RunThroughDelayedTasks(); // this runs the tap event
+ check.Call("Tapped on root");
+
+ // Now tap on the dispatch-to-content region where the layers overlap
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2,
+ {CompositorHitTestFlags::eVisibleToHitTest,
+ CompositorHitTestFlags::eIrregularArea});
+ Tap(manager, ScreenIntPoint(10, 110), tapDuration);
+ mcc->RunThroughDelayedTasks(); // this runs the main-thread timeout
+ check.Call("Tap pending on d-t-c region");
+ mcc->RunThroughDelayedTasks(); // this runs the tap event
+ check.Call("Tapped on bottom again");
+
+ // Now let's do that again, but simulate a main-thread response
+ uint64_t inputBlockId = 0;
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 2,
+ {CompositorHitTestFlags::eVisibleToHitTest,
+ CompositorHitTestFlags::eIrregularArea});
+ Tap(manager, ScreenIntPoint(10, 110), tapDuration, nullptr, &inputBlockId);
+ nsTArray<ScrollableLayerGuid> targets;
+ targets.AppendElement(left->GetGuid());
+ manager->SetTargetAPZC(inputBlockId, targets);
+ while (mcc->RunThroughDelayedTasks())
+ ; // this runs the tap event
+ check.Call("Tapped on left this time");
+}
+
+TEST_F(APZEventRegionsTesterMock, HitRegionAccumulatesChildren) {
+ CreateEventRegionsLayerTree2();
+
+ // Tap in the area of the child layer that's not directly included in the
+ // parent layer's hit region. Verify that it comes out of the APZC's
+ // content controller, which indicates the input events got routed correctly
+ // to the APZC.
+ EXPECT_CALL(*mcc,
+ HandleTap(TapType::eSingleTap, _, _, rootApzc->GetGuid(), _))
+ .Times(1);
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
+ Tap(manager, ScreenIntPoint(10, 160), TimeDuration::FromMilliseconds(100));
+}
+
+TEST_F(APZEventRegionsTesterMock, Bug1117712) {
+ CreateBug1117712LayerTree();
+
+ TestAsyncPanZoomController* apzc2 = ApzcOf(layers[2]);
+
+ // These touch events should hit the dispatch-to-content region of layers[3]
+ // and so get queued with that APZC as the tentative target.
+ uint64_t inputBlockId = 0;
+ QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
+ {CompositorHitTestFlags::eVisibleToHitTest,
+ CompositorHitTestFlags::eIrregularArea});
+ Tap(manager, ScreenIntPoint(55, 5), TimeDuration::FromMilliseconds(100),
+ nullptr, &inputBlockId);
+ // But now we tell the APZ that really it hit layers[2], and expect the tap
+ // to be delivered at the correct coordinates.
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(55, 5), 0,
+ apzc2->GetGuid(), _))
+ .Times(1);
+
+ nsTArray<ScrollableLayerGuid> targets;
+ targets.AppendElement(apzc2->GetGuid());
+ manager->SetTargetAPZC(inputBlockId, targets);
+}