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

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

Issue 13844021: Move compositor thread input handling logic into content (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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_client_impl.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "content/renderer/gpu/input_handler_client_impl_client.h"
10 #include "third_party/WebKit/Source/Platform/chromium/public/Platform.h"
11 #include "third_party/WebKit/Source/Platform/chromium/public/WebInputHandlerClie nt.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
13
14 using WebKit::WebFloatPoint;
15 using WebKit::WebFloatSize;
16 using WebKit::WebGestureEvent;
17 using WebKit::WebInputEvent;
18 using WebKit::WebInputHandlerClient;
19 using WebKit::WebMouseWheelEvent;
20 using WebKit::WebPoint;
21 using WebKit::WebScrollbar;
22 using WebKit::WebTouchEvent;
23
24 namespace content {
25
26 InputHandlerClientImpl::InputHandlerClientImpl(cc::InputHandler* input_handler)
27 : client_(NULL),
28 input_handler_(input_handler),
29 #ifndef NDEBUG
30 expect_scroll_update_end_(false),
31 expect_pinch_update_end_(false),
32 #endif
33 gesture_scroll_on_impl_thread_(false),
34 gesture_pinch_on_impl_thread_(false),
35 fling_active_on_main_thread_(false) {
36 input_handler_->BindToClient(this);
37 }
38
39 InputHandlerClientImpl::~InputHandlerClientImpl() {
40 if (client_)
41 client_->willShutdown();
42 }
43
44 void InputHandlerClientImpl::SetClient(InputHandlerClientImplClient* client) {
45 // It's valid to set a new client if we've never had one or to clear the
46 // client, but it's not valid to change from having one client to a different
47 // one.
48 DCHECK(!client_ || !client);
49 client_ = client;
50 }
51
52 void InputHandlerClientImpl::HandleInputEvent(const WebInputEvent& event) {
53 DCHECK(client_);
54
55 InputHandlerClientImpl::EventDisposition disposition =
56 HandleInputEventInternal(event);
57 switch (disposition) {
58 case DidHandle:
59 client_->didHandleInputEvent();
60 break;
61 case DidNotHandle:
62 client_->didNotHandleInputEvent(true /* send_to_widget */);
63 break;
64 case DropEvent:
65 client_->didNotHandleInputEvent(false /* send_to_widget */);
66 break;
67 }
68 if (event.modifiers & WebInputEvent::IsLastInputEventForCurrentVSync)
danakj 2013/05/01 19:20:43 nit: {}
69 input_handler_->DidReceiveLastInputEventForVSync(
70 base::TimeTicks::FromInternalValue(event.timeStampSeconds *
71 base::Time::kMicrosecondsPerSecond));
72 }
73
74 InputHandlerClientImpl::EventDisposition
75 InputHandlerClientImpl::HandleInputEventInternal(const WebInputEvent& event) {
76 if (event.type == WebInputEvent::MouseWheel) {
77 const WebMouseWheelEvent& wheel_event =
78 *static_cast<const WebMouseWheelEvent*>(&event);
79 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
80 gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::Wheel);
81 switch (scroll_status) {
82 case cc::InputHandler::ScrollStarted: {
83 TRACE_EVENT_INSTANT2(
84 "renderer",
85 "InputHandlerClientImpl::handle_input wheel scroll",
86 TRACE_EVENT_SCOPE_THREAD,
87 "deltaX",
88 -wheel_event.deltaX,
89 "deltaY",
90 -wheel_event.deltaY);
91 bool did_scroll = false;
92 if (wheel_event.scrollByPage) {
93 DCHECK(!wheel_event.deltaX);
94 WebScrollbar::ScrollDirection direction =
95 (wheel_event.deltaY < 0) ? WebScrollbar::ScrollForward
96 : WebScrollbar::ScrollBackward;
97 did_scroll = input_handler_->ScrollVerticallyByPage(
98 gfx::Point(wheel_event.x, wheel_event.y), direction);
99 } else {
100 did_scroll = input_handler_->ScrollBy(
101 gfx::Point(wheel_event.x, wheel_event.y),
102 gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY));
103 }
104 input_handler_->ScrollEnd();
105 return did_scroll ? DidHandle : DropEvent;
106 }
107 case cc::InputHandler::ScrollIgnored:
108 // FIXME: This should be DropEvent, but in cases where we fail to
109 // properly sync scrollability it's safer to send the
110 // event to the main thread. Change back to DropEvent once we have
111 // synchronization bugs sorted out.
112 return DidNotHandle;
113 case cc::InputHandler::ScrollOnMainThread:
114 return DidNotHandle;
115 }
116 } else if (event.type == WebInputEvent::GestureScrollBegin) {
117 DCHECK(!gesture_scroll_on_impl_thread_);
118 #ifndef NDEBUG
119 DCHECK(!expect_scroll_update_end_);
120 expect_scroll_update_end_ = true;
121 #endif
122 const WebGestureEvent& gesture_event =
123 *static_cast<const WebGestureEvent*>(&event);
124 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
125 gfx::Point(gesture_event.x, gesture_event.y),
126 cc::InputHandler::Gesture);
127 switch (scroll_status) {
128 case cc::InputHandler::ScrollStarted:
129 gesture_scroll_on_impl_thread_ = true;
130 return DidHandle;
131 case cc::InputHandler::ScrollOnMainThread:
132 return DidNotHandle;
133 case cc::InputHandler::ScrollIgnored:
134 return DropEvent;
135 }
136 } else if (event.type == WebInputEvent::GestureScrollUpdate) {
137 #ifndef NDEBUG
138 DCHECK(expect_scroll_update_end_);
139 #endif
140
141 if (!gesture_scroll_on_impl_thread_ && !gesture_pinch_on_impl_thread_)
142 return DidNotHandle;
143
144 const WebGestureEvent& gesture_event =
145 *static_cast<const WebGestureEvent*>(&event);
146 bool did_scroll = input_handler_->ScrollBy(
147 gfx::Point(gesture_event.x, gesture_event.y),
148 gfx::Vector2dF(-gesture_event.data.scrollUpdate.deltaX,
149 -gesture_event.data.scrollUpdate.deltaY));
150 return did_scroll ? DidHandle : DropEvent;
151 } else if (event.type == WebInputEvent::GestureScrollEnd) {
152 #ifndef NDEBUG
153 DCHECK(expect_scroll_update_end_);
154 expect_scroll_update_end_ = false;
155 #endif
156 if (!gesture_scroll_on_impl_thread_)
157 return DidNotHandle;
158
159 input_handler_->ScrollEnd();
160 gesture_scroll_on_impl_thread_ = false;
161 return DidHandle;
162 } else if (event.type == WebInputEvent::GesturePinchBegin) {
163 #ifndef NDEBUG
164 DCHECK(!expect_pinch_update_end_);
165 expect_pinch_update_end_ = true;
166 #endif
167 input_handler_->PinchGestureBegin();
168 gesture_pinch_on_impl_thread_ = true;
169 return DidHandle;
170 } else if (event.type == WebInputEvent::GesturePinchEnd) {
171 #ifndef NDEBUG
172 DCHECK(expect_pinch_update_end_);
173 expect_pinch_update_end_ = false;
174 #endif
175 gesture_pinch_on_impl_thread_ = false;
176 input_handler_->PinchGestureEnd();
177 return DidHandle;
178 } else if (event.type == WebInputEvent::GesturePinchUpdate) {
179 #ifndef NDEBUG
180 DCHECK(expect_pinch_update_end_);
181 #endif
182 const WebGestureEvent& gesture_event =
183 *static_cast<const WebGestureEvent*>(&event);
184 input_handler_->PinchGestureUpdate(
185 gesture_event.data.pinchUpdate.scale,
186 gfx::Point(gesture_event.x, gesture_event.y));
187 return DidHandle;
188 } else if (event.type == WebInputEvent::GestureFlingStart) {
189 const WebGestureEvent& gesture_event =
190 *static_cast<const WebGestureEvent*>(&event);
191 return HandleGestureFling(gesture_event);
192 } else if (event.type == WebInputEvent::GestureFlingCancel) {
193 if (CancelCurrentFling())
194 return DidHandle;
195 else if (!fling_active_on_main_thread_)
196 return DropEvent;
197 } else if (event.type == WebInputEvent::TouchStart) {
198 const WebTouchEvent& touch_event =
199 *static_cast<const WebTouchEvent*>(&event);
200 if (!input_handler_->HaveTouchEventHandlersAt(touch_event.touches[0]
201 .position))
202 return DropEvent;
203 } else if (WebInputEvent::isKeyboardEventType(event.type)) {
204 CancelCurrentFling();
205 }
206
207 return DidNotHandle;
208 }
209
210 InputHandlerClientImpl::EventDisposition
211 InputHandlerClientImpl::HandleGestureFling(
212 const WebGestureEvent& gesture_event) {
213 cc::InputHandler::ScrollStatus scroll_status =
214 input_handler_->ScrollBegin(gfx::Point(gesture_event.x, gesture_event.y),
215 cc::InputHandler::NonBubblingGesture);
216 switch (scroll_status) {
217 case cc::InputHandler::ScrollStarted: {
218 if (gesture_event.sourceDevice == WebGestureEvent::Touchpad)
219 input_handler_->ScrollEnd();
220 fling_curve_.reset(client_->createFlingAnimationCurve(
221 gesture_event.sourceDevice,
222 WebFloatPoint(gesture_event.data.flingStart.velocityX,
223 gesture_event.data.flingStart.velocityY),
224 WebKit::WebSize()));
225 TRACE_EVENT_ASYNC_BEGIN0(
226 "renderer",
227 "InputHandlerClientImpl::HandleGestureFling::started",
228 this);
229 fling_parameters_.delta =
230 WebFloatPoint(gesture_event.data.flingStart.velocityX,
231 gesture_event.data.flingStart.velocityY);
232 fling_parameters_.point = WebPoint(gesture_event.x, gesture_event.y);
233 fling_parameters_.globalPoint =
234 WebPoint(gesture_event.globalX, gesture_event.globalY);
235 fling_parameters_.modifiers = gesture_event.modifiers;
236 fling_parameters_.sourceDevice = gesture_event.sourceDevice;
237 input_handler_->ScheduleAnimation();
238 return DidHandle;
239 }
240 case cc::InputHandler::ScrollOnMainThread: {
241 TRACE_EVENT_INSTANT0("renderer",
242 "InputHandlerClientImpl::HandleGestureFling::"
243 "scroll_on_main_thread",
244 TRACE_EVENT_SCOPE_THREAD);
245 fling_active_on_main_thread_ = true;
246 return DidNotHandle;
247 }
248 case cc::InputHandler::ScrollIgnored: {
249 TRACE_EVENT_INSTANT0(
250 "renderer",
251 "InputHandlerClientImpl::HandleGestureFling::ignored",
252 TRACE_EVENT_SCOPE_THREAD);
253 if (gesture_event.sourceDevice == WebGestureEvent::Touchpad) {
254 // We still pass the curve to the main thread if there's nothing
255 // scrollable, in case something
256 // registers a handler before the curve is over.
257 return DidNotHandle;
258 }
259 return DropEvent;
260 }
261 }
262 return DidNotHandle;
263 }
264
265 void InputHandlerClientImpl::Animate(base::TimeTicks time) {
266 if (!fling_curve_)
267 return;
268
269 double monotonic_time_sec = (time - base::TimeTicks()).InSecondsF();
270 if (!fling_parameters_.startTime) {
271 fling_parameters_.startTime = monotonic_time_sec;
272 input_handler_->ScheduleAnimation();
273 return;
274 }
275
276 if (fling_curve_->apply(monotonic_time_sec - fling_parameters_.startTime,
277 this)) {
278 input_handler_->ScheduleAnimation();
279 } else {
280 TRACE_EVENT_INSTANT0("renderer",
281 "InputHandlerClientImpl::animate::flingOver",
282 TRACE_EVENT_SCOPE_THREAD);
283 CancelCurrentFling();
284 }
285 }
286
287 void InputHandlerClientImpl::MainThreadHasStoppedFlinging() {
288 fling_active_on_main_thread_ = false;
289 }
290
291 bool InputHandlerClientImpl::CancelCurrentFling() {
292 bool had_fling_animation = fling_curve_;
293 if (had_fling_animation &&
294 fling_parameters_.sourceDevice == WebGestureEvent::Touchscreen) {
295 input_handler_->ScrollEnd();
296 TRACE_EVENT_ASYNC_END0(
297 "renderer",
298 "InputHandlerClientImpl::HandleGestureFling::started",
299 this);
300 }
301
302 TRACE_EVENT_INSTANT1("renderer",
303 "InputHandlerClientImpl::CancelCurrentFling",
304 TRACE_EVENT_SCOPE_THREAD,
305 "had_fling_animation",
306 had_fling_animation);
307 fling_curve_.reset();
308 gesture_scroll_on_impl_thread_ = false;
309 fling_parameters_ = WebKit::WebActiveWheelFlingParameters();
310 return had_fling_animation;
311 }
312
313 bool InputHandlerClientImpl::touchpadFlingScroll(
314 const WebFloatSize& increment) {
315 WebMouseWheelEvent synthetic_wheel;
316 synthetic_wheel.type = WebInputEvent::MouseWheel;
317 synthetic_wheel.deltaX = increment.width;
318 synthetic_wheel.deltaY = increment.height;
319 synthetic_wheel.hasPreciseScrollingDeltas = true;
320 synthetic_wheel.x = fling_parameters_.point.x;
321 synthetic_wheel.y = fling_parameters_.point.y;
322 synthetic_wheel.globalX = fling_parameters_.globalPoint.x;
323 synthetic_wheel.globalY = fling_parameters_.globalPoint.y;
324 synthetic_wheel.modifiers = fling_parameters_.modifiers;
325
326 InputHandlerClientImpl::EventDisposition disposition =
327 HandleInputEventInternal(synthetic_wheel);
328 switch (disposition) {
329 case DidHandle:
330 return true;
331 case DropEvent:
332 break;
333 case DidNotHandle:
334 TRACE_EVENT_INSTANT0("renderer",
335 "InputHandlerClientImpl::scrollBy::AbortFling",
336 TRACE_EVENT_SCOPE_THREAD);
337 // If we got a DidNotHandle, that means we need to deliver wheels on the
338 // main thread.
339 // In this case we need to schedule a commit and transfer the fling curve
340 // over to the main
341 // thread and run the rest of the wheels from there.
342 // This can happen when flinging a page that contains a scrollable subarea
343 // that we can't
344 // scroll on the thread if the fling starts outside the subarea but then
345 // is flung "under" the
346 // pointer.
347 client_->transferActiveWheelFlingAnimation(fling_parameters_);
348 fling_active_on_main_thread_ = true;
349 CancelCurrentFling();
350 break;
351 }
352
353 return false;
354 }
355
356 static gfx::Vector2dF toClientScrollIncrement(const WebFloatSize& increment) {
danakj 2013/05/01 19:20:43 webkit style non-virtual
357 return gfx::Vector2dF(-increment.width, -increment.height);
358 }
359
360 void InputHandlerClientImpl::scrollBy(const WebFloatSize& increment) {
361 if (increment == WebFloatSize())
362 return;
363
364 TRACE_EVENT2("renderer",
365 "InputHandlerClientImpl::scrollBy",
366 "x",
367 increment.width,
368 "y",
369 increment.height);
370
371 bool did_scroll = false;
372
373 switch (fling_parameters_.sourceDevice) {
374 case WebGestureEvent::Touchpad:
375 did_scroll = touchpadFlingScroll(increment);
376 break;
377 case WebGestureEvent::Touchscreen:
378 did_scroll = input_handler_->ScrollBy(fling_parameters_.point,
379 toClientScrollIncrement(increment));
380 break;
381 }
382
383 if (did_scroll) {
384 fling_parameters_.cumulativeScroll.width += increment.width;
385 fling_parameters_.cumulativeScroll.height += increment.height;
386 }
387 }
388
389 void InputHandlerClientImpl::notifyCurrentFlingVelocity(
390 const WebFloatSize& velocity) {
391 TRACE_EVENT2("renderer",
392 "InputHandlerClientImpl::notifyCurrentFlingVelocity",
393 "vx",
394 velocity.width,
395 "vy",
396 velocity.height);
397 input_handler_->NotifyCurrentFlingVelocity(toClientScrollIncrement(velocity));
398 }
399
400 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698