TEST_F(APZCTreeManagerTester, Bug1194876) { CreateBug1194876Tree(); ScopedLayerTreeRegistration registration(manager, 0, root, mcc); manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); uint64_t blockId; nsTArray<ScrollableLayerGuid> targets; // First touch goes down, APZCTM will hit layers[1] because it is on top of // layers[0], but we tell it the real target APZC is layers[0]. MultiTouchInput mti; mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time()); mti.mTouches.AppendElement(SingleTouchData(0, ParentLayerPoint(25, 50), ScreenSize(0, 0), 0, 0)); manager->ReceiveInputEvent(mti, nullptr, &blockId); manager->ContentReceivedInputBlock(blockId, false); targets.AppendElement(ApzcOf(layers[0])->GetGuid()); manager->SetTargetAPZC(blockId, targets); // Around here, the above touch will get processed by ApzcOf(layers[0]) // Second touch goes down (first touch remains down), APZCTM will again hit // layers[1]. Again we tell it both touches landed on layers[0], but because // layers[1] is the RCD layer, it will end up being the multitouch target. mti.mTouches.AppendElement(SingleTouchData(1, ParentLayerPoint(75, 50), ScreenSize(0, 0), 0, 0)); manager->ReceiveInputEvent(mti, nullptr, &blockId); manager->ContentReceivedInputBlock(blockId, false); targets.AppendElement(ApzcOf(layers[0])->GetGuid()); manager->SetTargetAPZC(blockId, targets); // Around here, the above multi-touch will get processed by ApzcOf(layers[1]). // We want to ensure that ApzcOf(layers[0]) has had its state cleared, because // otherwise it will do things like dispatch spurious long-tap events. EXPECT_CALL(*mcc, HandleLongTap(_, _, _, _)).Times(0); }
void DoLongPressTest(uint32_t aBehavior) { MakeApzcUnzoomable(); uint64_t blockId = 0; nsEventStatus status = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &blockId); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) { // SetAllowedTouchBehavior() must be called after sending touch-start. nsTArray<uint32_t> allowedTouchBehaviors; allowedTouchBehaviors.AppendElement(aBehavior); apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors); } // Have content "respond" to the touchstart apzc->ContentReceivedInputBlock(blockId, false); MockFunction<void(std::string checkPointName)> check; { InSequence s; EXPECT_CALL(check, Call("preHandleLongTap")); blockId++; EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid(), blockId)).Times(1); EXPECT_CALL(check, Call("postHandleLongTap")); EXPECT_CALL(check, Call("preHandleSingleTap")); EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1); EXPECT_CALL(check, Call("postHandleSingleTap")); } // Manually invoke the longpress while the touch is currently down. check.Call("preHandleLongTap"); mcc->RunThroughDelayedTasks(); check.Call("postHandleLongTap"); // Dispatching the longpress event starts a new touch block, which // needs a new content response and also has a pending timeout task // in the queue. Deal with those here. We do the content response first // with preventDefault=false, and then we run the timeout task which // "loses the race" and does nothing. apzc->ContentReceivedInputBlock(blockId, false); mcc->AdvanceByMillis(1000); // Finally, simulate lifting the finger. Since the long-press wasn't // prevent-defaulted, we should get a long-tap-up event. check.Call("preHandleSingleTap"); status = TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time()); mcc->RunThroughDelayedTasks(); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); check.Call("postHandleSingleTap"); apzc->AssertStateIsReset(); }
TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) { // Since the wheel block interrupted the long-press, we don't expect // any long-press notifications. However, this also shouldn't crash, which // is what it used to do. EXPECT_CALL(*mcc, HandleLongTap(_, _, _, _)).Times(0); uint64_t touchBlockId = 0; uint64_t wheelBlockId = 0; TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &touchBlockId); mcc->AdvanceByMillis(10); Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time(), &wheelBlockId); EXPECT_NE(touchBlockId, wheelBlockId); mcc->AdvanceByMillis(1000); }
void DoLongPressPreventDefaultTest(uint32_t aBehavior) { MakeApzcUnzoomable(); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); int touchX = 10, touchStartY = 10, touchEndY = 50; uint64_t blockId = 0; nsEventStatus status = TouchDown(apzc, ScreenIntPoint(touchX, touchStartY), mcc->Time(), &blockId); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) { // SetAllowedTouchBehavior() must be called after sending touch-start. nsTArray<uint32_t> allowedTouchBehaviors; allowedTouchBehaviors.AppendElement(aBehavior); apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors); } // Have content "respond" to the touchstart apzc->ContentReceivedInputBlock(blockId, false); MockFunction<void(std::string checkPointName)> check; { InSequence s; EXPECT_CALL(check, Call("preHandleLongTap")); blockId++; EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid(), blockId)).Times(1); EXPECT_CALL(check, Call("postHandleLongTap")); } // Manually invoke the longpress while the touch is currently down. check.Call("preHandleLongTap"); mcc->RunThroughDelayedTasks(); check.Call("postHandleLongTap"); // There should be a TimeoutContentResponse task in the queue still, // waiting for the response from the longtap event dispatched above. // Send the signal that content has handled the long-tap, and then run // the timeout task (it will be a no-op because the content "wins" the // race. This takes the place of the "contextmenu" event. apzc->ContentReceivedInputBlock(blockId, true); mcc->AdvanceByMillis(1000); MultiTouchInput mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time()); mti.mTouches.AppendElement(SingleTouchData(0, ParentLayerPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); status = apzc->ReceiveInputEvent(mti, nullptr); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0); status = TouchUp(apzc, ScreenIntPoint(touchX, touchEndY), mcc->Time()); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); ParentLayerPoint pointOut; AsyncTransform viewTransformOut; apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(AsyncTransform(), viewTransformOut); apzc->AssertStateIsReset(); }