Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Unified Diff: ui/events/blink/input_handler_proxy_unittest.cc

Issue 2429953002: Implement compositor thread VSync aligned event queue (Closed)
Patch Set: dtapuska&enne's review: Call |Now()| once per loop; Chromium style; Remove parameterized test Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/events/blink/input_handler_proxy.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/blink/input_handler_proxy_unittest.cc
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index 78608b2d4ea9c316c87ee4bfeab3098c1395be41..d125c4ef76207082b26e4d9051409309bdbdc646 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -6,8 +6,12 @@
#include <memory>
+#include "base/bind.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_tick_clock.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/trees/swap_promise_monitor.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,7 +21,11 @@
#include "third_party/WebKit/public/platform/WebGestureCurve.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
+#include "ui/events/blink/compositor_thread_event_queue.h"
+#include "ui/events/blink/did_overscroll_params.h"
+#include "ui/events/blink/event_with_callback.h"
#include "ui/events/blink/input_handler_proxy_client.h"
+#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/size_f.h"
@@ -41,6 +49,15 @@ namespace test {
namespace {
+const char* kCoalescedCountHistogram =
+ "Event.CompositorThreadEventQueue.CoalescedCount";
+const char* kContinuousHeadQueueingTimeHistogram =
+ "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime";
+const char* kContinuousTailQueueingTimeHistogram =
+ "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime";
+const char* kNonContinuousQueueingTimeHistogram =
+ "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime";
+
enum InputHandlerProxyTestType {
ROOT_SCROLL_NORMAL_HANDLER,
ROOT_SCROLL_SYNCHRONOUS_HANDLER,
@@ -103,6 +120,23 @@ WebGestureEvent CreateFling(WebGestureDevice source_device,
modifiers);
}
+ScopedWebInputEvent CreateGestureScrollOrPinch(WebInputEvent::Type type,
+ float deltaYOrScale = 0,
+ int x = 0,
+ int y = 0) {
+ WebGestureEvent gesture;
+ gesture.sourceDevice = blink::WebGestureDeviceTouchpad;
+ gesture.type = type;
+ if (type == WebInputEvent::GestureScrollUpdate) {
+ gesture.data.scrollUpdate.deltaY = deltaYOrScale;
+ } else if (type == WebInputEvent::GesturePinchUpdate) {
+ gesture.data.pinchUpdate.scale = deltaYOrScale;
+ gesture.x = x;
+ gesture.y = y;
+ }
+ return WebInputEventTraits::Clone(gesture);
+}
+
class MockInputHandler : public cc::InputHandler {
public:
MockInputHandler() {}
@@ -437,6 +471,62 @@ class InputHandlerProxyTest
cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
};
+class InputHandlerProxyEventQueueTest : public testing::Test {
+ public:
+ InputHandlerProxyEventQueueTest() : weak_ptr_factory_(this) {
+ feature_list_.InitAndEnableFeature(features::kVsyncAlignedInputEvents);
+ }
+
+ ~InputHandlerProxyEventQueueTest() { input_handler_proxy_.reset(); }
+
+ void SetUp() override {
+ event_disposition_recorder_.clear();
+ input_handler_proxy_ = base::MakeUnique<TestInputHandlerProxy>(
+ &mock_input_handler_, &mock_client_);
+ if (input_handler_proxy_->compositor_event_queue_)
+ input_handler_proxy_->compositor_event_queue_ =
+ base::MakeUnique<CompositorThreadEventQueue>();
+ }
+
+ void HandleGestureEvent(WebInputEvent::Type type,
+ float deltay_or_scale = 0,
+ int x = 0,
+ int y = 0) {
+ LatencyInfo latency;
+ input_handler_proxy_->HandleInputEventWithLatencyInfo(
+ CreateGestureScrollOrPinch(type, deltay_or_scale, x, y), latency,
+ base::Bind(
+ &InputHandlerProxyEventQueueTest::DidHandleInputEventAndOverscroll,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ void DidHandleInputEventAndOverscroll(
+ InputHandlerProxy::EventDisposition event_disposition,
+ ui::ScopedWebInputEvent input_event,
+ const ui::LatencyInfo& latency_info,
+ std::unique_ptr<ui::DidOverscrollParams> overscroll_params) {
+ event_disposition_recorder_.push_back(event_disposition);
+ }
+
+ std::deque<std::unique_ptr<EventWithCallback>>& event_queue() {
+ return input_handler_proxy_->compositor_event_queue_->queue_;
+ }
+
+ void SetInputHandlerProxyTickClockForTesting(
+ std::unique_ptr<base::TickClock> tick_clock) {
+ input_handler_proxy_->SetTickClockForTesting(std::move(tick_clock));
+ }
+
+ protected:
+ base::test::ScopedFeatureList feature_list_;
+ testing::StrictMock<MockInputHandler> mock_input_handler_;
+ std::unique_ptr<TestInputHandlerProxy> input_handler_proxy_;
+ testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
+ std::vector<InputHandlerProxy::EventDisposition> event_disposition_recorder_;
+
+ base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_;
+};
+
TEST_P(InputHandlerProxyTest, MouseWheelNoListener) {
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
EXPECT_CALL(mock_input_handler_,
@@ -2815,9 +2905,187 @@ TEST_P(InputHandlerProxyTest, MainThreadScrollingMouseWheelHistograms) {
base::Bucket(5, 1), base::Bucket(14, 1)));
}
+TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScroll) {
+ base::HistogramTester histogram_tester;
+
+ // Handle scroll on compositor.
+ cc::InputHandlerScrollResult scroll_result_did_scroll_;
+ scroll_result_did_scroll_.did_scroll = true;
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
+
+ HandleGestureEvent(WebInputEvent::GestureScrollBegin);
+
+ // GestureScrollBegin will be processed immediately.
+ EXPECT_EQ(0ul, event_queue().size());
+ EXPECT_EQ(1ul, event_disposition_recorder_.size());
+ EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[0]);
+
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -20);
+
+ // GestureScrollUpdate will be queued.
+ EXPECT_EQ(1ul, event_queue().size());
+ EXPECT_EQ(-20, static_cast<const blink::WebGestureEvent&>(
+ event_queue().front()->event())
+ .data.scrollUpdate.deltaY);
+ EXPECT_EQ(1ul, event_queue().front()->coalesced_count());
+ EXPECT_EQ(1ul, event_disposition_recorder_.size());
+
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -40);
+
+ // GestureScrollUpdate will be coalesced.
+ EXPECT_EQ(1ul, event_queue().size());
+ EXPECT_EQ(-60, static_cast<const blink::WebGestureEvent&>(
+ event_queue().front()->event())
+ .data.scrollUpdate.deltaY);
+ EXPECT_EQ(2ul, event_queue().front()->coalesced_count());
+ EXPECT_EQ(1ul, event_disposition_recorder_.size());
+
+ HandleGestureEvent(WebInputEvent::GestureScrollEnd);
+
+ // GestureScrollEnd will be queued.
+ EXPECT_EQ(2ul, event_queue().size());
+ EXPECT_EQ(1ul, event_disposition_recorder_.size());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
+
+ // Dispatch all queued events.
+ input_handler_proxy_->DeliverInputForBeginFrame();
+ EXPECT_EQ(0ul, event_queue().size());
+ // Should run callbacks for every original events.
+ EXPECT_EQ(4ul, event_disposition_recorder_.size());
+ EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[1]);
+ EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[2]);
+ EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[3]);
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ histogram_tester.ExpectUniqueSample(kCoalescedCountHistogram, 2, 1);
+}
+
+TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScrollPinchScroll) {
+ base::HistogramTester histogram_tester;
+
+ // Handle scroll on compositor.
+ cc::InputHandlerScrollResult scroll_result_did_scroll_;
+ scroll_result_did_scroll_.did_scroll = true;
+
+ // Start scroll in the first frame.
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(
+ mock_input_handler_,
+ ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
+
+ HandleGestureEvent(WebInputEvent::GestureScrollBegin);
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -20);
+
+ EXPECT_EQ(1ul, event_queue().size());
+ EXPECT_EQ(1ul, event_disposition_recorder_.size());
+
+ input_handler_proxy_->DeliverInputForBeginFrame();
+
+ EXPECT_EQ(0ul, event_queue().size());
+ EXPECT_EQ(2ul, event_disposition_recorder_.size());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // Continue scroll in the second frame, pinch, then start another scroll.
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(
+ mock_input_handler_,
+ ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
+ .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(2);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+ EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
+ // Two |GesturePinchUpdate| will be coalesced.
+ EXPECT_CALL(mock_input_handler_,
+ PinchGestureUpdate(0.7f, gfx::Point(13, 17)));
+ EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
+
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -30);
+ HandleGestureEvent(WebInputEvent::GestureScrollEnd);
+ HandleGestureEvent(WebInputEvent::GesturePinchBegin);
+ HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 1.4f, 13, 17);
+ HandleGestureEvent(WebInputEvent::GesturePinchUpdate, 0.5f, 13, 17);
+ HandleGestureEvent(WebInputEvent::GesturePinchEnd);
+ HandleGestureEvent(WebInputEvent::GestureScrollBegin);
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -70);
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -5);
+ HandleGestureEvent(WebInputEvent::GestureScrollEnd);
+
+ EXPECT_EQ(8ul, event_queue().size());
+ EXPECT_EQ(2ul, event_disposition_recorder_.size());
+
+ input_handler_proxy_->DeliverInputForBeginFrame();
+
+ EXPECT_EQ(0ul, event_queue().size());
+ EXPECT_EQ(12ul, event_disposition_recorder_.size());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 1, 2);
+ histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 2, 2);
+}
+
+TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) {
+ base::HistogramTester histogram_tester;
+ std::unique_ptr<base::SimpleTestTickClock> tick_clock =
+ base::MakeUnique<base::SimpleTestTickClock>();
+ base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
+ tick_clock_ptr->SetNowTicks(base::TimeTicks::Now());
+ SetInputHandlerProxyTickClockForTesting(std::move(tick_clock));
+
+ // Handle scroll on compositor.
+ cc::InputHandlerScrollResult scroll_result_did_scroll_;
+ scroll_result_did_scroll_.did_scroll = true;
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
+ EXPECT_CALL(
+ mock_input_handler_,
+ ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
+
+ HandleGestureEvent(WebInputEvent::GestureScrollBegin);
+ tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(10));
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -20);
+ tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(40));
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -40);
+ tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(20));
+ HandleGestureEvent(WebInputEvent::GestureScrollUpdate, -10);
+ tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(10));
+ HandleGestureEvent(WebInputEvent::GestureScrollEnd);
+
+ // Dispatch all queued events.
+ tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(70));
+ input_handler_proxy_->DeliverInputForBeginFrame();
+ EXPECT_EQ(0ul, event_queue().size());
+ EXPECT_EQ(5ul, event_disposition_recorder_.size());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ histogram_tester.ExpectUniqueSample(kContinuousHeadQueueingTimeHistogram, 140,
+ 1);
+ histogram_tester.ExpectUniqueSample(kContinuousTailQueueingTimeHistogram, 80,
+ 1);
+ histogram_tester.ExpectBucketCount(kNonContinuousQueueingTimeHistogram, 0, 1);
+ histogram_tester.ExpectBucketCount(kNonContinuousQueueingTimeHistogram, 70,
+ 1);
+}
INSTANTIATE_TEST_CASE_P(AnimateInput,
InputHandlerProxyTest,
testing::ValuesIn(test_types));
+
} // namespace test
} // namespace ui
« no previous file with comments | « ui/events/blink/input_handler_proxy.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698