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

Side by Side Diff: content/renderer/gpu/input_handler_proxy_unittest.cc

Issue 13844021: Move compositor thread input handling logic into content (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 7 years, 7 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/gpu/input_handler_proxy.h"
6
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "content/renderer/gpu/input_handler_proxy_client.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatPoint.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatSize.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebGestureCurve.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebPoint.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
17
18 using WebKit::WebActiveWheelFlingParameters;
19 using WebKit::WebFloatPoint;
20 using WebKit::WebFloatSize;
21 using WebKit::WebGestureEvent;
22 using WebKit::WebInputEvent;
23 using WebKit::WebMouseWheelEvent;
24 using WebKit::WebPoint;
25 using WebKit::WebSize;
26
27 namespace {
28
29 class MockInputHandler : public cc::InputHandler {
30 public:
31 MockInputHandler() {}
32 virtual ~MockInputHandler() {}
33
34 MOCK_METHOD0(PinchGestureBegin, void());
35 MOCK_METHOD2(PinchGestureUpdate,
36 void(float magnify_delta, gfx::Point anchor));
37 MOCK_METHOD0(PinchGestureEnd, void());
38
39 MOCK_METHOD0(ScheduleAnimation, void());
40
41 MOCK_METHOD2(ScrollBegin,
42 ScrollStatus(gfx::Point viewport_point,
43 cc::InputHandler::ScrollInputType type));
44 MOCK_METHOD2(ScrollBy,
45 bool(gfx::Point viewport_point, gfx::Vector2dF scroll_delta));
46 MOCK_METHOD2(ScrollVerticallyByPage,
47 bool(gfx::Point viewport_point,
48 WebKit::WebScrollbar::ScrollDirection direction));
49 MOCK_METHOD0(ScrollEnd, void());
50 MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
51
52 MOCK_METHOD1(DidReceiveLastInputEventForVSync, void(base::TimeTicks time));
53
54 virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
55
56 virtual void StartPageScaleAnimation(gfx::Vector2d target_offset,
57 bool anchor_point,
58 float page_scale,
59 base::TimeTicks start_time,
60 base::TimeDelta duration) OVERRIDE {}
61
62 virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {}
63
64 virtual bool HaveTouchEventHandlersAt(gfx::Point point) OVERRIDE {
65 return false;
66 }
67
68 virtual void SetRootLayerScrollOffsetDelegate(
69 cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
70 OVERRIDE {}
71
72 virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {}
73
74 DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
75 };
76
77 // A simple WebGestureCurve implementation that flings at a constant velocity
78 // indefinitely.
79 class FakeWebGestureCurve : public WebKit::WebGestureCurve {
80 public:
81 FakeWebGestureCurve(const WebKit::WebFloatPoint& velocity,
82 const WebKit::WebSize& cumulative_scroll)
83 : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {}
84
85 virtual ~FakeWebGestureCurve() {}
86
87 // Returns false if curve has finished and can no longer be applied.
88 virtual bool apply(double time, WebKit::WebGestureCurveTarget* target) {
89 WebKit::WebSize displacement(velocity_.x * time, velocity_.y * time);
90 WebKit::WebFloatSize increment(
91 displacement.width - cumulative_scroll_.width,
92 displacement.height - cumulative_scroll_.height);
93 cumulative_scroll_ = displacement;
94 // scrollBy() could delete this curve if the animation is over, so don't
95 // touch any member variables after making that call.
96 target->scrollBy(increment);
97 return true;
98 }
99
100 private:
101 WebKit::WebFloatPoint velocity_;
102 WebKit::WebSize cumulative_scroll_;
103
104 DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
105 };
106
107 class MockInputHandlerProxyClient
108 : public content::InputHandlerProxyClient {
109 public:
110 MockInputHandlerProxyClient() {}
111 virtual ~MockInputHandlerProxyClient() {}
112
113 virtual void WillShutdown() OVERRIDE {}
114
115 MOCK_METHOD0(DidHandleInputEvent, void());
116 MOCK_METHOD1(DidNotHandleInputEvent, void(bool send_to_widget));
117
118 MOCK_METHOD1(TransferActiveWheelFlingAnimation,
119 void(const WebActiveWheelFlingParameters&));
120
121 virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve(
122 int deviceSource,
123 const WebFloatPoint& velocity,
124 const WebSize& cumulative_scroll) OVERRIDE {
125 return new FakeWebGestureCurve(velocity, cumulative_scroll);
126 }
127
128 private:
129 DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
130 };
131
132 class InputHandlerProxyTest : public testing::Test {
133 public:
134 InputHandlerProxyTest() : expected_disposition_(DidHandle) {
135 input_handler_.reset(
136 new content::InputHandlerProxy(&mock_input_handler_));
137 input_handler_->SetClient(&mock_client_);
138 }
139
140 ~InputHandlerProxyTest() {
141 input_handler_.reset();
142 }
143
144 // This is defined as a macro because when an expectation is not satisfied the
145 // only output you get
146 // out of gmock is the line number that set the expectation.
147 #define VERIFY_AND_RESET_MOCKS() \
148 do { \
149 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \
150 testing::Mock::VerifyAndClearExpectations(&mock_client_); \
151 switch (expected_disposition_) { \
152 case DidHandle: \
153 /* If we expect to handle events, we shouldn't get any */ \
154 /* DidNotHandleInputEvent() calls with any parameter. */ \
155 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(::testing::_)) \
156 .Times(0); \
157 EXPECT_CALL(mock_client_, DidHandleInputEvent()); \
158 break; \
159 case DidNotHandle: \
160 /* If we aren't expecting to handle events, we shouldn't call */ \
161 /* DidHandleInputEvent(). */ \
162 EXPECT_CALL(mock_client_, DidHandleInputEvent()).Times(0); \
163 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(false)).Times(0); \
164 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)); \
165 break; \
166 case DropEvent: \
167 /* If we're expecting to drop, we shouldn't get any didHandle..() */ \
168 /* or DidNotHandleInputEvent(true) calls. */ \
169 EXPECT_CALL(mock_client_, DidHandleInputEvent()).Times(0); \
170 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)).Times(0); \
171 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(false)); \
172 break; \
173 } \
174 } while (false)
175
176 protected:
177 testing::StrictMock<MockInputHandler> mock_input_handler_;
178 scoped_ptr<content::InputHandlerProxy> input_handler_;
179 testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
180 WebGestureEvent gesture_;
181
182 enum ExpectedDisposition {
183 DidHandle,
184 DidNotHandle,
185 DropEvent
186 };
187 ExpectedDisposition expected_disposition_;
188 };
189
190 TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) {
191 WebMouseWheelEvent wheel;
192 wheel.type = WebInputEvent::MouseWheel;
193 wheel.scrollByPage = true;
194
195 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)).Times(1);
196 input_handler_->HandleInputEvent(wheel);
197 testing::Mock::VerifyAndClearExpectations(&mock_client_);
198 }
199
200 TEST_F(InputHandlerProxyTest, GestureScrollStarted) {
201 // We shouldn't send any events to the widget for this gesture.
202 expected_disposition_ = DidHandle;
203 VERIFY_AND_RESET_MOCKS();
204
205 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
206 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
207
208 gesture_.type = WebInputEvent::GestureScrollBegin;
209 input_handler_->HandleInputEvent(gesture_);
210
211 // The event should not be marked as handled if scrolling is not possible.
212 expected_disposition_ = DropEvent;
213 VERIFY_AND_RESET_MOCKS();
214
215 gesture_.type = WebInputEvent::GestureScrollUpdate;
216 gesture_.data.scrollUpdate.deltaY =
217 -40; // -Y means scroll down - i.e. in the +Y direction.
218 EXPECT_CALL(mock_input_handler_,
219 ScrollBy(testing::_,
220 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
221 .WillOnce(testing::Return(false));
222 input_handler_->HandleInputEvent(gesture_);
223
224 // Mark the event as handled if scroll happens.
225 expected_disposition_ = DidHandle;
226 VERIFY_AND_RESET_MOCKS();
227
228 gesture_.type = WebInputEvent::GestureScrollUpdate;
229 gesture_.data.scrollUpdate.deltaY =
230 -40; // -Y means scroll down - i.e. in the +Y direction.
231 EXPECT_CALL(mock_input_handler_,
232 ScrollBy(testing::_,
233 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
234 .WillOnce(testing::Return(true));
235 input_handler_->HandleInputEvent(gesture_);
236
237 VERIFY_AND_RESET_MOCKS();
238
239 gesture_.type = WebInputEvent::GestureScrollEnd;
240 gesture_.data.scrollUpdate.deltaY = 0;
241 EXPECT_CALL(mock_input_handler_, ScrollEnd());
242 input_handler_->HandleInputEvent(gesture_);
243 }
244
245 TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) {
246 // We should send all events to the widget for this gesture.
247 expected_disposition_ = DidNotHandle;
248 VERIFY_AND_RESET_MOCKS();
249
250 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
251 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
252
253 gesture_.type = WebInputEvent::GestureScrollBegin;
254 input_handler_->HandleInputEvent(gesture_);
255
256 VERIFY_AND_RESET_MOCKS();
257
258 gesture_.type = WebInputEvent::GestureScrollUpdate;
259 gesture_.data.scrollUpdate.deltaY = 40;
260 input_handler_->HandleInputEvent(gesture_);
261
262 VERIFY_AND_RESET_MOCKS();
263
264 gesture_.type = WebInputEvent::GestureScrollEnd;
265 gesture_.data.scrollUpdate.deltaY = 0;
266 input_handler_->HandleInputEvent(gesture_);
267 }
268
269 TEST_F(InputHandlerProxyTest, GestureScrollIgnored) {
270 // We shouldn't handle the GestureScrollBegin.
271 // Instead, we should get one DidNotHandleInputEvent(false) call per
272 // HandleInputEvent(), indicating that we could determine that there's nothing
273 // that could scroll or otherwise react to this gesture sequence and thus we
274 // should drop the whole gesture sequence on the floor.
275 expected_disposition_ = DropEvent;
276 VERIFY_AND_RESET_MOCKS();
277
278 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
279 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
280
281 gesture_.type = WebInputEvent::GestureScrollBegin;
282 input_handler_->HandleInputEvent(gesture_);
283 }
284
285 TEST_F(InputHandlerProxyTest, GesturePinch) {
286 // We shouldn't send any events to the widget for this gesture.
287 expected_disposition_ = DidHandle;
288 VERIFY_AND_RESET_MOCKS();
289
290 gesture_.type = WebInputEvent::GesturePinchBegin;
291 EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
292 input_handler_->HandleInputEvent(gesture_);
293
294 VERIFY_AND_RESET_MOCKS();
295
296 gesture_.type = WebInputEvent::GesturePinchUpdate;
297 gesture_.data.pinchUpdate.scale = 1.5;
298 gesture_.x = 7;
299 gesture_.y = 13;
300 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
301 input_handler_->HandleInputEvent(gesture_);
302
303 VERIFY_AND_RESET_MOCKS();
304
305 gesture_.type = WebInputEvent::GesturePinchUpdate;
306 gesture_.data.pinchUpdate.scale = 0.5;
307 gesture_.x = 9;
308 gesture_.y = 6;
309 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
310 input_handler_->HandleInputEvent(gesture_);
311
312 VERIFY_AND_RESET_MOCKS();
313
314 gesture_.type = WebInputEvent::GesturePinchEnd;
315 EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
316 input_handler_->HandleInputEvent(gesture_);
317 }
318
319 TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
320 // Scrolls will start by being sent to the main thread.
321 expected_disposition_ = DidNotHandle;
322 VERIFY_AND_RESET_MOCKS();
323
324 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
325 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
326
327 gesture_.type = WebInputEvent::GestureScrollBegin;
328 input_handler_->HandleInputEvent(gesture_);
329
330 VERIFY_AND_RESET_MOCKS();
331
332 gesture_.type = WebInputEvent::GestureScrollUpdate;
333 gesture_.data.scrollUpdate.deltaY = 40;
334 input_handler_->HandleInputEvent(gesture_);
335
336 // However, after the pinch gesture starts, they should go to the impl
337 // thread.
338 expected_disposition_ = DidHandle;
339 VERIFY_AND_RESET_MOCKS();
340
341 gesture_.type = WebInputEvent::GesturePinchBegin;
342 EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
343 input_handler_->HandleInputEvent(gesture_);
344
345 VERIFY_AND_RESET_MOCKS();
346
347 gesture_.type = WebInputEvent::GesturePinchUpdate;
348 gesture_.data.pinchUpdate.scale = 1.5;
349 gesture_.x = 7;
350 gesture_.y = 13;
351 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
352 input_handler_->HandleInputEvent(gesture_);
353
354 VERIFY_AND_RESET_MOCKS();
355
356 gesture_.type = WebInputEvent::GestureScrollUpdate;
357 gesture_.data.scrollUpdate.deltaY =
358 -40; // -Y means scroll down - i.e. in the +Y direction.
359 EXPECT_CALL(mock_input_handler_,
360 ScrollBy(testing::_,
361 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
362 .WillOnce(testing::Return(true));
363 input_handler_->HandleInputEvent(gesture_);
364
365 VERIFY_AND_RESET_MOCKS();
366
367 gesture_.type = WebInputEvent::GesturePinchUpdate;
368 gesture_.data.pinchUpdate.scale = 0.5;
369 gesture_.x = 9;
370 gesture_.y = 6;
371 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
372 input_handler_->HandleInputEvent(gesture_);
373
374 VERIFY_AND_RESET_MOCKS();
375
376 gesture_.type = WebInputEvent::GesturePinchEnd;
377 EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
378 input_handler_->HandleInputEvent(gesture_);
379
380 // After the pinch gesture ends, they should go to back to the main
381 // thread.
382 expected_disposition_ = DidNotHandle;
383 VERIFY_AND_RESET_MOCKS();
384
385 gesture_.type = WebInputEvent::GestureScrollEnd;
386 gesture_.data.scrollUpdate.deltaY = 0;
387 input_handler_->HandleInputEvent(gesture_);
388 }
389
390 TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) {
391 // We shouldn't send any events to the widget for this gesture.
392 expected_disposition_ = DidHandle;
393 VERIFY_AND_RESET_MOCKS();
394
395 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
396 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
397 EXPECT_CALL(mock_input_handler_, ScrollEnd());
398 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
399
400 gesture_.type = WebInputEvent::GestureFlingStart;
401 gesture_.data.flingStart.velocityX = 10;
402 gesture_.sourceDevice = WebGestureEvent::Touchpad;
403 input_handler_->HandleInputEvent(gesture_);
404
405 VERIFY_AND_RESET_MOCKS();
406
407 // Verify that a GestureFlingCancel during an animation cancels it.
408 gesture_.type = WebInputEvent::GestureFlingCancel;
409 gesture_.sourceDevice = WebGestureEvent::Touchpad;
410 input_handler_->HandleInputEvent(gesture_);
411 }
412
413 TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) {
414 // We should send all events to the widget for this gesture.
415 expected_disposition_ = DidNotHandle;
416 VERIFY_AND_RESET_MOCKS();
417
418 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
419 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
420
421 gesture_.type = WebInputEvent::GestureFlingStart;
422 gesture_.sourceDevice = WebGestureEvent::Touchpad;
423 input_handler_->HandleInputEvent(gesture_);
424
425 // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the
426 // input handler knows it's scrolling off the impl thread
427 ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
428
429 VERIFY_AND_RESET_MOCKS();
430
431 // Even if we didn't start a fling ourselves, we still need to send the cancel
432 // event to the widget.
433 gesture_.type = WebInputEvent::GestureFlingCancel;
434 gesture_.sourceDevice = WebGestureEvent::Touchpad;
435 input_handler_->HandleInputEvent(gesture_);
436 }
437
438 TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) {
439 expected_disposition_ = DidNotHandle;
440 VERIFY_AND_RESET_MOCKS();
441
442 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
443 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
444
445 gesture_.type = WebInputEvent::GestureFlingStart;
446 gesture_.sourceDevice = WebGestureEvent::Touchpad;
447 input_handler_->HandleInputEvent(gesture_);
448
449 expected_disposition_ = DropEvent;
450 VERIFY_AND_RESET_MOCKS();
451
452 // Since the previous fling was ignored, we should also be dropping the next
453 // fling_cancel.
454 gesture_.type = WebInputEvent::GestureFlingCancel;
455 gesture_.sourceDevice = WebGestureEvent::Touchpad;
456 input_handler_->HandleInputEvent(gesture_);
457 }
458
459 TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
460 // We shouldn't send any events to the widget for this gesture.
461 expected_disposition_ = DidHandle;
462 VERIFY_AND_RESET_MOCKS();
463
464 // On the fling start, we should schedule an animation but not actually start
465 // scrolling.
466 gesture_.type = WebInputEvent::GestureFlingStart;
467 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
468 WebPoint fling_point = WebPoint(7, 13);
469 WebPoint fling_global_point = WebPoint(17, 23);
470 int modifiers = 7;
471 gesture_.data.flingStart.velocityX = fling_delta.x;
472 gesture_.data.flingStart.velocityY = fling_delta.y;
473 gesture_.sourceDevice = WebGestureEvent::Touchpad;
474 gesture_.x = fling_point.x;
475 gesture_.y = fling_point.y;
476 gesture_.globalX = fling_global_point.x;
477 gesture_.globalY = fling_global_point.y;
478 gesture_.modifiers = modifiers;
479 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
480 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
481 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
482 EXPECT_CALL(mock_input_handler_, ScrollEnd());
483 input_handler_->HandleInputEvent(gesture_);
484
485 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
486 // The first animate call should let us pick up an animation start time, but
487 // we shouldn't actually move anywhere just yet. The first frame after the
488 // fling start will typically include the last scroll from the gesture that
489 // lead to the scroll (either wheel or gesture scroll), so there should be no
490 // visible hitch.
491 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
492 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
493 .Times(0);
494 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
495 input_handler_->Animate(time);
496
497 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
498
499 // The second call should start scrolling in the -X direction.
500 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
501 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
502 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
503 EXPECT_CALL(mock_input_handler_,
504 ScrollBy(testing::_,
505 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
506 .WillOnce(testing::Return(true));
507 EXPECT_CALL(mock_input_handler_, ScrollEnd());
508 time += base::TimeDelta::FromMilliseconds(100);
509 input_handler_->Animate(time);
510
511 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
512
513 // Let's say on the third call we hit a non-scrollable region. We should abort
514 // the fling and not scroll.
515 // We also should pass the current fling parameters out to the client so the
516 // rest of the fling can be
517 // transferred to the main thread.
518 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
519 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
520 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
521 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
522 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
523 // Expected wheel fling animation parameters:
524 // *) fling_delta and fling_point should match the original GestureFlingStart
525 // event
526 // *) startTime should be 10 to match the time parameter of the first
527 // Animate() call after the GestureFlingStart
528 // *) cumulativeScroll depends on the curve, but since we've animated in the
529 // -X direction the X value should be < 0
530 EXPECT_CALL(
531 mock_client_,
532 TransferActiveWheelFlingAnimation(testing::AllOf(
533 testing::Field(&WebActiveWheelFlingParameters::delta,
534 testing::Eq(fling_delta)),
535 testing::Field(&WebActiveWheelFlingParameters::point,
536 testing::Eq(fling_point)),
537 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
538 testing::Eq(fling_global_point)),
539 testing::Field(&WebActiveWheelFlingParameters::modifiers,
540 testing::Eq(modifiers)),
541 testing::Field(&WebActiveWheelFlingParameters::startTime,
542 testing::Eq(10)),
543 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
544 testing::Field(&WebSize::width, testing::Gt(0))))));
545 time += base::TimeDelta::FromMilliseconds(100);
546 input_handler_->Animate(time);
547
548 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
549 testing::Mock::VerifyAndClearExpectations(&mock_client_);
550
551 // Since we've aborted the fling, the next animation should be a no-op and
552 // should not result in another
553 // frame being requested.
554 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
555 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
556 .Times(0);
557 time += base::TimeDelta::FromMilliseconds(100);
558 input_handler_->Animate(time);
559
560 // Since we've transferred the fling to the main thread, we need to pass the
561 // next GestureFlingCancel to the main
562 // thread as well.
563 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true));
564 gesture_.type = WebInputEvent::GestureFlingCancel;
565 input_handler_->HandleInputEvent(gesture_);
566 }
567
568 TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
569 // We shouldn't send any events to the widget for this gesture.
570 expected_disposition_ = DidHandle;
571 VERIFY_AND_RESET_MOCKS();
572
573 // Start a gesture fling in the -X direction with zero Y movement.
574 gesture_.type = WebInputEvent::GestureFlingStart;
575 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
576 WebPoint fling_point = WebPoint(7, 13);
577 WebPoint fling_global_point = WebPoint(17, 23);
578 int modifiers = 1;
579 gesture_.data.flingStart.velocityX = fling_delta.x;
580 gesture_.data.flingStart.velocityY = fling_delta.y;
581 gesture_.sourceDevice = WebGestureEvent::Touchpad;
582 gesture_.x = fling_point.x;
583 gesture_.y = fling_point.y;
584 gesture_.globalX = fling_global_point.x;
585 gesture_.globalY = fling_global_point.y;
586 gesture_.modifiers = modifiers;
587 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
588 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
589 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
590 EXPECT_CALL(mock_input_handler_, ScrollEnd());
591 input_handler_->HandleInputEvent(gesture_);
592
593 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
594
595 // Start the fling animation at time 10. This shouldn't actually scroll, just
596 // establish a start time.
597 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
598 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
599 .Times(0);
600 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
601 input_handler_->Animate(time);
602
603 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
604
605 // The second call should start scrolling in the -X direction.
606 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
607 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
608 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
609 EXPECT_CALL(mock_input_handler_,
610 ScrollBy(testing::_,
611 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
612 .WillOnce(testing::Return(true));
613 EXPECT_CALL(mock_input_handler_, ScrollEnd());
614 time += base::TimeDelta::FromMilliseconds(100);
615 input_handler_->Animate(time);
616
617 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
618
619 // Let's say on the third call we hit a non-scrollable region. We should abort
620 // the fling and not scroll.
621 // We also should pass the current fling parameters out to the client so the
622 // rest of the fling can be
623 // transferred to the main thread.
624 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
625 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
626 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
627 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
628 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
629
630 // Expected wheel fling animation parameters:
631 // *) fling_delta and fling_point should match the original GestureFlingStart
632 // event
633 // *) startTime should be 10 to match the time parameter of the first
634 // Animate() call after the GestureFlingStart
635 // *) cumulativeScroll depends on the curve, but since we've animated in the
636 // -X direction the X value should be < 0
637 EXPECT_CALL(
638 mock_client_,
639 TransferActiveWheelFlingAnimation(testing::AllOf(
640 testing::Field(&WebActiveWheelFlingParameters::delta,
641 testing::Eq(fling_delta)),
642 testing::Field(&WebActiveWheelFlingParameters::point,
643 testing::Eq(fling_point)),
644 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
645 testing::Eq(fling_global_point)),
646 testing::Field(&WebActiveWheelFlingParameters::modifiers,
647 testing::Eq(modifiers)),
648 testing::Field(&WebActiveWheelFlingParameters::startTime,
649 testing::Eq(10)),
650 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
651 testing::Field(&WebSize::width, testing::Gt(0))))));
652 time += base::TimeDelta::FromMilliseconds(100);
653 input_handler_->Animate(time);
654
655 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
656 testing::Mock::VerifyAndClearExpectations(&mock_client_);
657
658 // Since we've aborted the fling, the next animation should be a no-op and
659 // should not result in another
660 // frame being requested.
661 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
662 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
663 .Times(0);
664 time += base::TimeDelta::FromMilliseconds(100);
665 input_handler_->Animate(time);
666
667 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
668
669 // Since we've transferred the fling to the main thread, we need to pass the
670 // next GestureFlingCancel to the main
671 // thread as well.
672 EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true));
673 gesture_.type = WebInputEvent::GestureFlingCancel;
674 input_handler_->HandleInputEvent(gesture_);
675
676 VERIFY_AND_RESET_MOCKS();
677 input_handler_->MainThreadHasStoppedFlinging();
678
679 // Start a second gesture fling, this time in the +Y direction with no X.
680 gesture_.type = WebInputEvent::GestureFlingStart;
681 fling_delta = WebFloatPoint(0, -1000);
682 fling_point = WebPoint(95, 87);
683 fling_global_point = WebPoint(32, 71);
684 modifiers = 2;
685 gesture_.data.flingStart.velocityX = fling_delta.x;
686 gesture_.data.flingStart.velocityY = fling_delta.y;
687 gesture_.sourceDevice = WebGestureEvent::Touchpad;
688 gesture_.x = fling_point.x;
689 gesture_.y = fling_point.y;
690 gesture_.globalX = fling_global_point.x;
691 gesture_.globalY = fling_global_point.y;
692 gesture_.modifiers = modifiers;
693 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
694 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
695 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
696 EXPECT_CALL(mock_input_handler_, ScrollEnd());
697 input_handler_->HandleInputEvent(gesture_);
698
699 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
700
701 // Start the second fling animation at time 30.
702 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
703 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
704 .Times(0);
705 time = base::TimeTicks() + base::TimeDelta::FromSeconds(30);
706 input_handler_->Animate(time);
707
708 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
709
710 // Tick the second fling once normally.
711 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
712 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
713 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
714 EXPECT_CALL(mock_input_handler_,
715 ScrollBy(testing::_,
716 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
717 .WillOnce(testing::Return(true));
718 EXPECT_CALL(mock_input_handler_, ScrollEnd());
719 time += base::TimeDelta::FromMilliseconds(100);
720 input_handler_->Animate(time);
721
722 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
723
724 // Then abort the second fling.
725 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
726 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
727 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
728 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
729 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
730
731 // We should get parameters from the second fling, nothing from the first
732 // fling should "leak".
733 EXPECT_CALL(
734 mock_client_,
735 TransferActiveWheelFlingAnimation(testing::AllOf(
736 testing::Field(&WebActiveWheelFlingParameters::delta,
737 testing::Eq(fling_delta)),
738 testing::Field(&WebActiveWheelFlingParameters::point,
739 testing::Eq(fling_point)),
740 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
741 testing::Eq(fling_global_point)),
742 testing::Field(&WebActiveWheelFlingParameters::modifiers,
743 testing::Eq(modifiers)),
744 testing::Field(&WebActiveWheelFlingParameters::startTime,
745 testing::Eq(30)),
746 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
747 testing::Field(&WebSize::height, testing::Lt(0))))));
748 time += base::TimeDelta::FromMilliseconds(100);
749 input_handler_->Animate(time);
750 }
751
752 TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) {
753 // We shouldn't send any events to the widget for this gesture.
754 expected_disposition_ = DidHandle;
755 VERIFY_AND_RESET_MOCKS();
756
757 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
758 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
759 gesture_.type = WebInputEvent::GestureScrollBegin;
760 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
761 input_handler_->HandleInputEvent(gesture_);
762
763 VERIFY_AND_RESET_MOCKS();
764
765 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
766 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
767 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
768
769 gesture_.type = WebInputEvent::GestureFlingStart;
770 gesture_.data.flingStart.velocityX = 10;
771 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
772 input_handler_->HandleInputEvent(gesture_);
773
774 VERIFY_AND_RESET_MOCKS();
775
776 EXPECT_CALL(mock_input_handler_, ScrollEnd());
777
778 // Verify that a GestureFlingCancel during an animation cancels it.
779 gesture_.type = WebInputEvent::GestureFlingCancel;
780 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
781 input_handler_->HandleInputEvent(gesture_);
782 }
783
784 TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) {
785 // We should send all events to the widget for this gesture.
786 expected_disposition_ = DidNotHandle;
787 VERIFY_AND_RESET_MOCKS();
788
789 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
790 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
791
792 gesture_.type = WebInputEvent::GestureScrollBegin;
793 input_handler_->HandleInputEvent(gesture_);
794
795 VERIFY_AND_RESET_MOCKS();
796
797 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0);
798
799 gesture_.type = WebInputEvent::GestureFlingStart;
800 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
801 input_handler_->HandleInputEvent(gesture_);
802
803 VERIFY_AND_RESET_MOCKS();
804
805 // Even if we didn't start a fling ourselves, we still need to send the cancel
806 // event to the widget.
807 gesture_.type = WebInputEvent::GestureFlingCancel;
808 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
809 input_handler_->HandleInputEvent(gesture_);
810 }
811
812 TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
813 expected_disposition_ = DidHandle;
814 VERIFY_AND_RESET_MOCKS();
815
816 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
817 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
818
819 gesture_.type = WebInputEvent::GestureScrollBegin;
820 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
821 input_handler_->HandleInputEvent(gesture_);
822
823 expected_disposition_ = DropEvent;
824 VERIFY_AND_RESET_MOCKS();
825
826 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
827 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
828
829 gesture_.type = WebInputEvent::GestureFlingStart;
830 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
831 input_handler_->HandleInputEvent(gesture_);
832
833 VERIFY_AND_RESET_MOCKS();
834
835 // Even if we didn't start a fling ourselves, we still need to send the cancel
836 // event to the widget.
837 gesture_.type = WebInputEvent::GestureFlingCancel;
838 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
839 input_handler_->HandleInputEvent(gesture_);
840 }
841
842 TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
843 // We shouldn't send any events to the widget for this gesture.
844 expected_disposition_ = DidHandle;
845 VERIFY_AND_RESET_MOCKS();
846
847 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
848 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
849
850 gesture_.type = WebInputEvent::GestureScrollBegin;
851 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
852 input_handler_->HandleInputEvent(gesture_);
853
854 VERIFY_AND_RESET_MOCKS();
855
856 // On the fling start, we should schedule an animation but not actually start
857 // scrolling.
858 gesture_.type = WebInputEvent::GestureFlingStart;
859 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
860 WebPoint fling_point = WebPoint(7, 13);
861 WebPoint fling_global_point = WebPoint(17, 23);
862 int modifiers = 7;
863 gesture_.data.flingStart.velocityX = fling_delta.x;
864 gesture_.data.flingStart.velocityY = fling_delta.y;
865 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
866 gesture_.x = fling_point.x;
867 gesture_.y = fling_point.y;
868 gesture_.globalX = fling_global_point.x;
869 gesture_.globalY = fling_global_point.y;
870 gesture_.modifiers = modifiers;
871 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
872 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
873 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
874 input_handler_->HandleInputEvent(gesture_);
875
876 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
877 // The first animate call should let us pick up an animation start time, but
878 // we shouldn't actually move anywhere just yet. The first frame after the
879 // fling start will typically include the last scroll from the gesture that
880 // lead to the scroll (either wheel or gesture scroll), so there should be no
881 // visible hitch.
882 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
883 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
884 input_handler_->Animate(time);
885
886 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
887
888 // The second call should start scrolling in the -X direction.
889 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
890 EXPECT_CALL(mock_input_handler_,
891 ScrollBy(testing::_,
892 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
893 .WillOnce(testing::Return(true));
894 time += base::TimeDelta::FromMilliseconds(100);
895 input_handler_->Animate(time);
896
897 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
898
899 EXPECT_CALL(mock_client_, DidHandleInputEvent());
900 EXPECT_CALL(mock_input_handler_, ScrollEnd());
901 gesture_.type = WebInputEvent::GestureFlingCancel;
902 input_handler_->HandleInputEvent(gesture_);
903 }
904
905 TEST_F(InputHandlerProxyTest,
906 GestureScrollOnImplThreadFlagClearedAfterFling) {
907 // We shouldn't send any events to the widget for this gesture.
908 expected_disposition_ = DidHandle;
909 VERIFY_AND_RESET_MOCKS();
910
911 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
912 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
913
914 gesture_.type = WebInputEvent::GestureScrollBegin;
915 input_handler_->HandleInputEvent(gesture_);
916
917 // After sending a GestureScrollBegin, the member variable
918 // |gesture_scroll_on_impl_thread_| should be true.
919 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
920
921 expected_disposition_ = DidHandle;
922 VERIFY_AND_RESET_MOCKS();
923
924 // On the fling start, we should schedule an animation but not actually start
925 // scrolling.
926 gesture_.type = WebInputEvent::GestureFlingStart;
927 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
928 WebPoint fling_point = WebPoint(7, 13);
929 WebPoint fling_global_point = WebPoint(17, 23);
930 int modifiers = 7;
931 gesture_.data.flingStart.velocityX = fling_delta.x;
932 gesture_.data.flingStart.velocityY = fling_delta.y;
933 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
934 gesture_.x = fling_point.x;
935 gesture_.y = fling_point.y;
936 gesture_.globalX = fling_global_point.x;
937 gesture_.globalY = fling_global_point.y;
938 gesture_.modifiers = modifiers;
939 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
940 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
941 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
942 input_handler_->HandleInputEvent(gesture_);
943
944 // |gesture_scroll_on_impl_thread_| should still be true after
945 // a GestureFlingStart is sent.
946 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
947
948 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
949 // The first animate call should let us pick up an animation start time, but
950 // we shouldn't actually move anywhere just yet. The first frame after the
951 // fling start will typically include the last scroll from the gesture that
952 // lead to the scroll (either wheel or gesture scroll), so there should be no
953 // visible hitch.
954 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
955 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
956 input_handler_->Animate(time);
957
958 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
959
960 // The second call should start scrolling in the -X direction.
961 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
962 EXPECT_CALL(mock_input_handler_,
963 ScrollBy(testing::_,
964 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
965 .WillOnce(testing::Return(true));
966 time += base::TimeDelta::FromMilliseconds(100);
967 input_handler_->Animate(time);
968
969 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
970
971 EXPECT_CALL(mock_client_, DidHandleInputEvent());
972 EXPECT_CALL(mock_input_handler_, ScrollEnd());
973 gesture_.type = WebInputEvent::GestureFlingCancel;
974 input_handler_->HandleInputEvent(gesture_);
975
976 // |gesture_scroll_on_impl_thread_| should be false once
977 // the fling has finished (note no GestureScrollEnd has been sent).
978 EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing());
979 }
980
981 TEST_F(InputHandlerProxyTest, LastInputEventForVSync) {
982 expected_disposition_ = DropEvent;
983 VERIFY_AND_RESET_MOCKS();
984
985 gesture_.type = WebInputEvent::GestureFlingCancel;
986 gesture_.timeStampSeconds = 1234;
987 base::TimeTicks time =
988 base::TimeTicks() +
989 base::TimeDelta::FromSeconds(gesture_.timeStampSeconds);
990 gesture_.modifiers |= WebInputEvent::IsLastInputEventForCurrentVSync;
991 EXPECT_CALL(mock_input_handler_, DidReceiveLastInputEventForVSync(time));
992 input_handler_->HandleInputEvent(gesture_);
993 }
994
995 } // namespace
OLDNEW
« no previous file with comments | « content/renderer/gpu/input_handler_proxy_client.h ('k') | content/renderer/gpu/input_handler_wrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698