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

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

Powered by Google App Engine
This is Rietveld 408576698