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

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

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

Powered by Google App Engine
This is Rietveld 408576698