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

Side by Side Diff: ui/events/blink/blink_event_util.cc

Issue 2429953002: Implement compositor thread VSync aligned event queue (Closed)
Patch Set: tdresser's review: Move CanCoalesce/Coalesce; Test queueing time 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // MSVC++ requires this to be set before any other includes to get M_PI. 5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES 6 #define _USE_MATH_DEFINES
7 7
8 #include "ui/events/blink/blink_event_util.h" 8 #include "ui/events/blink/blink_event_util.h"
9 9
10 #include <stddef.h> 10 #include <stddef.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <bitset>
13 #include <cmath> 14 #include <cmath>
15 #include <limits>
14 16
15 #include "base/time/time.h" 17 #include "base/time/time.h"
16 #include "build/build_config.h" 18 #include "build/build_config.h"
17 #include "third_party/WebKit/public/platform/WebInputEvent.h" 19 #include "third_party/WebKit/public/platform/WebInputEvent.h"
18 #include "ui/events/base_event_utils.h" 20 #include "ui/events/base_event_utils.h"
19 #include "ui/events/event_constants.h" 21 #include "ui/events/event_constants.h"
20 #include "ui/events/gesture_detection/gesture_event_data.h" 22 #include "ui/events/gesture_detection/gesture_event_data.h"
21 #include "ui/events/gesture_detection/motion_event.h" 23 #include "ui/events/gesture_detection/motion_event.h"
22 #include "ui/events/gesture_event_details.h" 24 #include "ui/events/gesture_event_details.h"
23 #include "ui/events/keycodes/dom/keycode_converter.h" 25 #include "ui/events/keycodes/dom/keycode_converter.h"
24 #include "ui/gfx/geometry/safe_integer_conversions.h" 26 #include "ui/gfx/geometry/safe_integer_conversions.h"
25 #include "ui/gfx/geometry/vector2d.h" 27 #include "ui/gfx/geometry/vector2d.h"
26 28
27 using blink::WebGestureEvent; 29 using blink::WebGestureEvent;
28 using blink::WebInputEvent; 30 using blink::WebInputEvent;
31 using blink::WebMouseEvent;
32 using blink::WebMouseWheelEvent;
29 using blink::WebPointerProperties; 33 using blink::WebPointerProperties;
30 using blink::WebTouchEvent; 34 using blink::WebTouchEvent;
31 using blink::WebTouchPoint; 35 using blink::WebTouchPoint;
36 using std::numeric_limits;
32 37
33 namespace ui { 38 namespace ui {
34 namespace { 39 namespace {
35 40
41 const int kInvalidTouchIndex = -1;
42
36 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) { 43 WebInputEvent::Type ToWebInputEventType(MotionEvent::Action action) {
37 switch (action) { 44 switch (action) {
38 case MotionEvent::ACTION_DOWN: 45 case MotionEvent::ACTION_DOWN:
39 return WebInputEvent::TouchStart; 46 return WebInputEvent::TouchStart;
40 case MotionEvent::ACTION_MOVE: 47 case MotionEvent::ACTION_MOVE:
41 return WebInputEvent::TouchMove; 48 return WebInputEvent::TouchMove;
42 case MotionEvent::ACTION_UP: 49 case MotionEvent::ACTION_UP:
43 return WebInputEvent::TouchEnd; 50 return WebInputEvent::TouchEnd;
44 case MotionEvent::ACTION_CANCEL: 51 case MotionEvent::ACTION_CANCEL:
45 return WebInputEvent::TouchCancel; 52 return WebInputEvent::TouchCancel;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 float z = cos(tilt_rad); 160 float z = cos(tilt_rad);
154 touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); 161 touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI);
155 touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); 162 touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI);
156 } else { 163 } else {
157 touch.tiltX = touch.tiltY = 0; 164 touch.tiltX = touch.tiltY = 0;
158 } 165 }
159 166
160 return touch; 167 return touch;
161 } 168 }
162 169
170 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
171 return accelerated_delta * acceleration_ratio;
172 }
173
174 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
175 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
176 return 1.f;
177 return unaccelerated_delta / accelerated_delta;
178 }
179
180 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
181 int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
182 for (unsigned i = 0; i < event.touchesLength; ++i) {
183 if (event.touches[i].id == id)
184 return i;
185 }
186 return kInvalidTouchIndex;
187 }
188
189 WebInputEvent::DispatchType MergeDispatchTypes(
190 WebInputEvent::DispatchType type_1,
191 WebInputEvent::DispatchType type_2) {
192 static_assert(WebInputEvent::DispatchType::Blocking <
193 WebInputEvent::DispatchType::EventNonBlocking,
194 "Enum not ordered correctly");
195 static_assert(WebInputEvent::DispatchType::EventNonBlocking <
196 WebInputEvent::DispatchType::ListenersNonBlockingPassive,
197 "Enum not ordered correctly");
198 static_assert(
199 WebInputEvent::DispatchType::ListenersNonBlockingPassive <
200 WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling,
201 "Enum not ordered correctly");
202 return static_cast<WebInputEvent::DispatchType>(
203 std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
204 }
205
206 bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
207 const WebMouseEvent& event) {
208 return event.type == event_to_coalesce.type &&
209 event.type == WebInputEvent::MouseMove;
210 }
211
212 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
213 DCHECK(CanCoalesce(event_to_coalesce, *event));
214 // Accumulate movement deltas.
215 int x = event->movementX;
216 int y = event->movementY;
217 *event = event_to_coalesce;
218 event->movementX += x;
219 event->movementY += y;
220 }
221
222 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
223 const WebMouseWheelEvent& event) {
224 return event.modifiers == event_to_coalesce.modifiers &&
225 event.scrollByPage == event_to_coalesce.scrollByPage &&
226 event.phase == event_to_coalesce.phase &&
227 event.momentumPhase == event_to_coalesce.momentumPhase &&
228 event.hasPreciseScrollingDeltas ==
229 event_to_coalesce.hasPreciseScrollingDeltas;
230 }
231
232 void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
233 WebMouseWheelEvent* event) {
234 DCHECK(CanCoalesce(event_to_coalesce, *event));
235 float unaccelerated_x =
236 GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) +
237 GetUnacceleratedDelta(event_to_coalesce.deltaX,
238 event_to_coalesce.accelerationRatioX);
239 float unaccelerated_y =
240 GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) +
241 GetUnacceleratedDelta(event_to_coalesce.deltaY,
242 event_to_coalesce.accelerationRatioY);
243 float old_deltaX = event->deltaX;
244 float old_deltaY = event->deltaY;
245 float old_wheelTicksX = event->wheelTicksX;
246 float old_wheelTicksY = event->wheelTicksY;
247 float old_movementX = event->movementX;
248 float old_movementY = event->movementY;
249 *event = event_to_coalesce;
250 event->deltaX += old_deltaX;
251 event->deltaY += old_deltaY;
252 event->wheelTicksX += old_wheelTicksX;
253 event->wheelTicksY += old_wheelTicksY;
254 event->movementX += old_movementX;
255 event->movementY += old_movementY;
256 event->accelerationRatioX =
257 GetAccelerationRatio(event->deltaX, unaccelerated_x);
258 event->accelerationRatioY =
259 GetAccelerationRatio(event->deltaY, unaccelerated_y);
260 }
261
262 bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
263 const WebTouchEvent& event) {
264 if (event.type != event_to_coalesce.type ||
265 event.type != WebInputEvent::TouchMove ||
266 event.modifiers != event_to_coalesce.modifiers ||
267 event.touchesLength != event_to_coalesce.touchesLength ||
268 event.touchesLength > WebTouchEvent::kTouchesLengthCap)
269 return false;
270
271 static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U,
272 "suboptimal kTouchesLengthCap size");
273 // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
274 std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches(
275 (1 << event.touchesLength) - 1);
276 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
277 int event_touch_index =
278 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
279 if (event_touch_index == kInvalidTouchIndex)
280 return false;
281 if (!unmatched_event_touches[event_touch_index])
282 return false;
283 unmatched_event_touches[event_touch_index] = false;
284 }
285 return unmatched_event_touches.none();
286 }
287
288 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
289 DCHECK(CanCoalesce(event_to_coalesce, *event));
290 // The WebTouchPoints include absolute position information. So it is
291 // sufficient to simply replace the previous event with the new event->
292 // However, it is necessary to make sure that all the points have the
293 // correct state, i.e. the touch-points that moved in the last event, but
294 // didn't change in the current event, will have Stationary state. It is
295 // necessary to change them back to Moved state.
296 WebTouchEvent old_event = *event;
297 *event = event_to_coalesce;
298 for (unsigned i = 0; i < event->touchesLength; ++i) {
299 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
300 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
301 event->touches[i].state = blink::WebTouchPoint::StateMoved;
302 }
303 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
304 event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
305 event_to_coalesce.dispatchType);
306 }
307
308 bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
309 const WebGestureEvent& event) {
310 if (event.type != event_to_coalesce.type ||
311 event.sourceDevice != event_to_coalesce.sourceDevice ||
312 event.modifiers != event_to_coalesce.modifiers)
313 return false;
314
315 if (event.type == WebInputEvent::GestureScrollUpdate)
316 return true;
317
318 // GesturePinchUpdate scales can be combined only if they share a focal point,
319 // e.g., with double-tap drag zoom.
320 if (event.type == WebInputEvent::GesturePinchUpdate &&
321 event.x == event_to_coalesce.x && event.y == event_to_coalesce.y)
322 return true;
323
324 return false;
325 }
326
327 void Coalesce(const WebGestureEvent& event_to_coalesce,
328 WebGestureEvent* event) {
329 DCHECK(CanCoalesce(event_to_coalesce, *event));
330 if (event->type == WebInputEvent::GestureScrollUpdate) {
331 event->data.scrollUpdate.deltaX +=
332 event_to_coalesce.data.scrollUpdate.deltaX;
333 event->data.scrollUpdate.deltaY +=
334 event_to_coalesce.data.scrollUpdate.deltaY;
335 DCHECK_EQ(
336 event->data.scrollUpdate.previousUpdateInSequencePrevented,
337 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
338 } else if (event->type == WebInputEvent::GesturePinchUpdate) {
339 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
340 // Ensure the scale remains bounded above 0 and below Infinity so that
341 // we can reliably perform operations like log on the values.
342 if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
343 event->data.pinchUpdate.scale = numeric_limits<float>::min();
344 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
345 event->data.pinchUpdate.scale = numeric_limits<float>::max();
346 }
347 }
348
163 } // namespace 349 } // namespace
164 350
351 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
352 const blink::WebInputEvent& event) {
353 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
354 blink::WebInputEvent::isGestureEventType(event.type)) {
355 return CanCoalesce(
356 static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
357 static_cast<const blink::WebGestureEvent&>(event));
358 }
359 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
360 blink::WebInputEvent::isMouseEventType(event.type)) {
361 return CanCoalesce(
362 static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
363 static_cast<const blink::WebMouseEvent&>(event));
364 }
365 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
366 blink::WebInputEvent::isTouchEventType(event.type)) {
367 return CanCoalesce(
368 static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
369 static_cast<const blink::WebTouchEvent&>(event));
370 }
371 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
372 event.type == blink::WebInputEvent::MouseWheel) {
373 return CanCoalesce(
374 static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
375 static_cast<const blink::WebMouseWheelEvent&>(event));
376 }
377 return false;
378 }
379
380 void Coalesce(const blink::WebInputEvent& event_to_coalesce,
381 blink::WebInputEvent* event) {
382 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
383 blink::WebInputEvent::isGestureEventType(event->type)) {
384 Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
385 static_cast<blink::WebGestureEvent*>(event));
386 return;
387 }
388 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
389 blink::WebInputEvent::isMouseEventType(event->type)) {
390 Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
391 static_cast<blink::WebMouseEvent*>(event));
392 return;
393 }
394 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
395 blink::WebInputEvent::isTouchEventType(event->type)) {
396 Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
397 static_cast<blink::WebTouchEvent*>(event));
398 return;
399 }
400 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
401 event->type == blink::WebInputEvent::MouseWheel) {
402 Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
403 static_cast<blink::WebMouseWheelEvent*>(event));
404 }
405 }
406
165 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent( 407 blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
166 const MotionEvent& event, 408 const MotionEvent& event,
167 bool moved_beyond_slop_region) { 409 bool moved_beyond_slop_region) {
168 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) == 410 static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
169 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap), 411 static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap),
170 "inconsistent maximum number of active touch points"); 412 "inconsistent maximum number of active touch points");
171 413
172 blink::WebTouchEvent result; 414 blink::WebTouchEvent result;
173 415
174 result.type = ToWebInputEventType(event.GetAction()); 416 result.type = ToWebInputEventType(event.GetAction());
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 case DomKeyLocation::RIGHT: 776 case DomKeyLocation::RIGHT:
535 return blink::WebInputEvent::IsRight; 777 return blink::WebInputEvent::IsRight;
536 case DomKeyLocation::NUMPAD: 778 case DomKeyLocation::NUMPAD:
537 return blink::WebInputEvent::IsKeyPad; 779 return blink::WebInputEvent::IsKeyPad;
538 case DomKeyLocation::STANDARD: 780 case DomKeyLocation::STANDARD:
539 break; 781 break;
540 } 782 }
541 return static_cast<blink::WebInputEvent::Modifiers>(0); 783 return static_cast<blink::WebInputEvent::Modifiers>(0);
542 } 784 }
543 785
786 bool IsGestureScollOrPinch(WebInputEvent::Type type) {
787 switch (type) {
788 case blink::WebGestureEvent::GestureScrollBegin:
789 case blink::WebGestureEvent::GestureScrollUpdate:
790 case blink::WebGestureEvent::GestureScrollEnd:
791 case blink::WebGestureEvent::GesturePinchBegin:
792 case blink::WebGestureEvent::GesturePinchUpdate:
793 case blink::WebGestureEvent::GesturePinchEnd:
794 return true;
795 default:
796 return false;
797 }
798 }
799
800 bool IsContinuousGestureEvent(WebInputEvent::Type type) {
801 switch (type) {
802 case blink::WebGestureEvent::GestureScrollUpdate:
803 case blink::WebGestureEvent::GesturePinchUpdate:
804 return true;
805 default:
806 return false;
807 }
808 }
809
544 } // namespace ui 810 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698