From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../apz/test/gtest/TestTransformNotifications.cpp | 569 +++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 gfx/layers/apz/test/gtest/TestTransformNotifications.cpp (limited to 'gfx/layers/apz/test/gtest/TestTransformNotifications.cpp') diff --git a/gfx/layers/apz/test/gtest/TestTransformNotifications.cpp b/gfx/layers/apz/test/gtest/TestTransformNotifications.cpp new file mode 100644 index 0000000000..f9eeba66e6 --- /dev/null +++ b/gfx/layers/apz/test/gtest/TestTransformNotifications.cpp @@ -0,0 +1,569 @@ +/* -*- 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 "APZCBasicTester.h" +#include "APZCTreeManagerTester.h" +#include "APZTestCommon.h" +#include "mozilla/layers/WebRenderScrollDataWrapper.h" +#include "apz/util/APZEventState.h" + +#include "InputUtils.h" + +class APZCTransformNotificationTester : public APZCTreeManagerTester { + public: + explicit APZCTransformNotificationTester() { CreateMockHitTester(); } + + UniquePtr mRegistration; + + RefPtr mRootApzc; + + void SetupBasicTest() { + const char* treeShape = "x"; + LayerIntRect layerVisibleRect[] = { + LayerIntRect(0, 0, 100, 100), + }; + CreateScrollData(treeShape, layerVisibleRect); + SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID, + CSSRect(0, 0, 500, 500)); + + mRegistration = MakeUnique(LayersId{0}, mcc); + + UpdateHitTestingTree(); + + mRootApzc = ApzcOf(root); + } + + void SetupNonScrollableTest() { + const char* treeShape = "x"; + LayerIntRect layerVisibleRect[] = { + LayerIntRect(0, 0, 100, 100), + }; + CreateScrollData(treeShape, layerVisibleRect); + SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID, + CSSRect(0, 0, 100, 100)); + + mRegistration = MakeUnique(LayersId{0}, mcc); + + UpdateHitTestingTree(); + + mRootApzc = ApzcOf(root); + + mRootApzc->GetFrameMetrics().SetIsRootContent(true); + } +}; + +TEST_F(APZCTransformNotificationTester, PanningTransformNotifications) { + SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true); + + SetupBasicTest(); + + // Scroll down by 25 px. Ensure we only get one set of + // state change notifications. + // + // Then, scroll back up by 20px, this time flinging after. + // The fling should cover the remaining 5 px of room to scroll, then + // go into overscroll, and finally snap-back to recover from overscroll. + // Again, ensure we only get one set of state change notifications for + // this entire procedure. + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Simple pan")); + EXPECT_CALL( + *mcc, NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartTouch, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartPanning, _, _)) + .Times(1); + EXPECT_CALL(*mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eEndTouch, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL(check, Call("Complex pan")); + EXPECT_CALL( + *mcc, NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartTouch, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartPanning, _, _)) + .Times(1); + EXPECT_CALL(*mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eEndTouch, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Simple pan"); + Pan(mRootApzc, 50, 25, PanOptions::NoFling); + check.Call("Complex pan"); + Pan(mRootApzc, 25, 45); + mRootApzc->AdvanceAnimationsUntilEnd(); + check.Call("Done"); +} + +TEST_F(APZCTransformNotificationTester, PanWithMomentumTransformNotifications) { + SetupBasicTest(); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Panning")); + EXPECT_CALL(check, Call("Pan End")); + EXPECT_CALL(check, Call("Momentum Start")); + + EXPECT_CALL(check, Call("Momentum Pan")); + EXPECT_CALL(check, Call("Momentum End")); + // The TransformEnd should only be sent after the momentum pan. + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Panning"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, 30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Momentum Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager, + ScreenIntPoint(50, 50), ScreenPoint(30, 90), mcc->Time()); + mcc->AdvanceByMillis(10); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Momentum Pan"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager, + ScreenIntPoint(50, 50), ScreenPoint(10, 30), mcc->Time()); + mcc->AdvanceByMillis(10); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Momentum End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, manager, + ScreenIntPoint(50, 50), ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(10); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Done"); +} + +TEST_F(APZCTransformNotificationTester, + PanWithoutMomentumTransformNotifications) { + // Ensure that the TransformEnd delay is 100ms. + SCOPED_GFX_PREF_INT("apz.scrollend-event.content.delay_ms", 100); + + SetupBasicTest(); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Panning")); + EXPECT_CALL(check, Call("Pan End")); + EXPECT_CALL(check, Call("TransformEnd delay")); + // The TransformEnd should only be sent after the pan gesture and 100ms + // timer fire. + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Panning"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, 30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(55); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("TransformEnd delay"); + mcc->AdvanceByMillis(55); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Done"); +} + +TEST_F(APZCTransformNotificationTester, + PanFollowedByNewPanTransformNotifications) { + // Ensure that the TransformEnd delay is 100ms. + SCOPED_GFX_PREF_INT("apz.scrollend-event.content.delay_ms", 100); + + SetupBasicTest(); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Panning")); + EXPECT_CALL(check, Call("Pan End")); + // The TransformEnd delay should be cut short and delivered before the + // new pan gesture begins. + EXPECT_CALL(check, Call("New Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + EXPECT_CALL(check, Call("New Pan End")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Panning"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, 30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(55); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("New Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, 30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("New Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(105); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Done"); +} + +TEST_F(APZCTransformNotificationTester, + PanFollowedByWheelTransformNotifications) { + // Needed because the test uses SmoothWheel() + SCOPED_GFX_PREF_BOOL("general.smoothScroll", true); + // Ensure that the TransformEnd delay is 100ms. + SCOPED_GFX_PREF_INT("apz.scrollend-event.content.delay_ms", 100); + + SetupBasicTest(); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Panning")); + EXPECT_CALL(check, Call("Pan End")); + // The TransformEnd delay should be cut short and delivered before the + // new wheel event begins. + EXPECT_CALL(check, Call("Wheel Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + EXPECT_CALL(check, Call("Wheel End")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Panning"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, 30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(55); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Wheel Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + SmoothWheel(manager, ScreenIntPoint(50, 50), ScreenPoint(10, 10), + mcc->Time()); + mcc->AdvanceByMillis(10); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Wheel End"); + + mRootApzc->AdvanceAnimationsUntilEnd(); + + check.Call("Done"); +} + +#ifndef MOZ_WIDGET_ANDROID // Currently fails on Android +TEST_F(APZCTransformNotificationTester, PanOverscrollTransformNotifications) { + SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true); + + SetupBasicTest(); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("Pan Start")); + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformBegin, _, _)) + .Times(1); + + EXPECT_CALL(check, Call("Panning Into Overscroll")); + EXPECT_CALL(check, Call("Pan End")); + EXPECT_CALL(check, Call("Overscroll Animation End")); + // The TransformEnd should only be sent after the overscroll animation + // completes. + EXPECT_CALL( + *mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eTransformEnd, _, _)) + .Times(1); + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Pan Start"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50), + ScreenIntPoint(1, 2), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Panning Into Overscroll"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_PAN, mRootApzc, ScreenIntPoint(50, 50), + ScreenPoint(15, -30), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + // Ensure that we have overscrolled. + EXPECT_TRUE(mRootApzc->IsOverscrolled()); + + check.Call("Pan End"); + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50), + ScreenPoint(0, 0), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + // Wait for the overscroll animation to complete and the TransformEnd + // notification to be sent. + check.Call("Overscroll Animation End"); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimationsUntilEnd(); + EXPECT_FALSE(mRootApzc->IsOverscrolled()); + + check.Call("Done"); +} +#endif + +TEST_F(APZCTransformNotificationTester, ScrollableTouchStateChange) { + // Create a scroll frame with available space for a scroll. + SetupBasicTest(); + + MockFunction check; + { + EXPECT_CALL(check, Call("Start")); + // We receive a touch-start with the flag indicating that the + // touch-start occurred over a scrollable element. + EXPECT_CALL( + *mcc, NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartTouch, 1, _)) + .Times(1); + + EXPECT_CALL(*mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eEndTouch, 1, _)) + .Times(1); + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Start"); + + // Conduct a touch down and touch up in the scrollable element, + // and ensure the correct state change notifications are sent. + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + TouchDown(mRootApzc, ScreenIntPoint(10, 10), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + TouchUp(mRootApzc, ScreenIntPoint(10, 10), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Done"); +} + +TEST_F(APZCTransformNotificationTester, NonScrollableTouchStateChange) { + // Create a non-scrollable frame with no space to scroll. + SetupNonScrollableTest(); + + MockFunction check; + { + EXPECT_CALL(check, Call("Start")); + // We receive a touch-start with the flag indicating that the + // touch-start occurred over a non-scrollable element. + EXPECT_CALL( + *mcc, NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eStartTouch, 0, _)) + .Times(1); + + EXPECT_CALL(*mcc, + NotifyAPZStateChange( + _, GeckoContentController::APZStateChange::eEndTouch, 1, _)) + .Times(1); + EXPECT_CALL(check, Call("Done")); + } + + check.Call("Start"); + + // Conduct a touch down and touch up in the non-scrollable element, + // and ensure the correct state change notifications are sent. + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + TouchDown(mRootApzc, ScreenIntPoint(10, 10), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID); + TouchUp(mRootApzc, ScreenIntPoint(10, 10), mcc->Time()); + mcc->AdvanceByMillis(5); + mRootApzc->AdvanceAnimations(mcc->GetSampleTime()); + + check.Call("Done"); +} -- cgit v1.2.3