14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/common/input/web_input_event_traits.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <bitset>
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <limits>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebGestureEvent;
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebInputEvent;
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebKeyboardEvent;
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebMouseEvent;
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebMouseWheelEvent;
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebTouchEvent;
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)using std::numeric_limits;
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace content {
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kInvalidTouchIndex = -1;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const WebKeyboardEvent& event) {
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return false;
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Coalesce(const WebKeyboardEvent& event_to_coalesce,
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              WebKeyboardEvent* event) {
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CanCoalesce(event_to_coalesce, *event));
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const WebMouseEvent& event) {
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return event.type == event_to_coalesce.type &&
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         event.type == WebInputEvent::MouseMove;
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CanCoalesce(event_to_coalesce, *event));
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Accumulate movement deltas.
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int x = event->movementX;
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int y = event->movementY;
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *event = event_to_coalesce;
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->movementX += x;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->movementY += y;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const WebMouseWheelEvent& event) {
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return event.modifiers == event_to_coalesce.modifiers &&
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         event.scrollByPage == event_to_coalesce.scrollByPage &&
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         event.phase == event_to_coalesce.phase &&
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         event.momentumPhase == event_to_coalesce.momentumPhase &&
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         event.hasPreciseScrollingDeltas ==
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             event_to_coalesce.hasPreciseScrollingDeltas;
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return accelerated_delta * acceleration_ratio;
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return 1.f;
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return unaccelerated_delta / accelerated_delta;
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              WebMouseWheelEvent* event) {
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CanCoalesce(event_to_coalesce, *event));
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  float unaccelerated_x =
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetUnacceleratedDelta(event->deltaX,
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            event->accelerationRatioX) +
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetUnacceleratedDelta(event_to_coalesce.deltaX,
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            event_to_coalesce.accelerationRatioX);
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  float unaccelerated_y =
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetUnacceleratedDelta(event->deltaY,
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            event->accelerationRatioY) +
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetUnacceleratedDelta(event_to_coalesce.deltaY,
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            event_to_coalesce.accelerationRatioY);
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->deltaX += event_to_coalesce.deltaX;
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->deltaY += event_to_coalesce.deltaY;
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->wheelTicksX += event_to_coalesce.wheelTicksX;
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->wheelTicksY += event_to_coalesce.wheelTicksY;
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->accelerationRatioX =
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetAccelerationRatio(event->deltaX, unaccelerated_x);
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->accelerationRatioY =
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetAccelerationRatio(event->deltaY, unaccelerated_y);
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_GE(event_to_coalesce.timeStampSeconds, event->timeStampSeconds);
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  event->timeStampSeconds = event_to_coalesce.timeStampSeconds;
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (unsigned i = 0; i < event.touchesLength; ++i) {
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (event.touches[i].id == id)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return i;
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return kInvalidTouchIndex;
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const WebTouchEvent& event) {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (event.type != event_to_coalesce.type ||
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type != WebInputEvent::TouchMove ||
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.modifiers != event_to_coalesce.modifiers ||
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.touchesLength != event_to_coalesce.touchesLength ||
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.touchesLength > WebTouchEvent::touchesLengthCap)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  COMPILE_ASSERT(WebTouchEvent::touchesLengthCap <= sizeof(int32_t) * 8U,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 suboptimal_touches_length_cap_size);
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::bitset<WebTouchEvent::touchesLengthCap> unmatched_event_touches(
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (1 << event.touchesLength) - 1);
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int event_touch_index =
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (event_touch_index == kInvalidTouchIndex)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!unmatched_event_touches[event_touch_index])
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    unmatched_event_touches[event_touch_index] = false;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return unmatched_event_touches.none();
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CanCoalesce(event_to_coalesce, *event));
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The WebTouchPoints include absolute position information. So it is
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // sufficient to simply replace the previous event with the new event->
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // However, it is necessary to make sure that all the points have the
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // correct state, i.e. the touch-points that moved in the last event, but
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // didn't change in the current event, will have Stationary state. It is
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // necessary to change them back to Moved state.
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebTouchEvent old_event = *event;
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *event = event_to_coalesce;
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (unsigned i = 0; i < event->touchesLength; ++i) {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->touches[i].state = blink::WebTouchPoint::StateMoved;
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 const WebGestureEvent& event) {
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (event.type != event_to_coalesce.type ||
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event.sourceDevice != event_to_coalesce.sourceDevice ||
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event.modifiers != event_to_coalesce.modifiers)
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (event.type == WebInputEvent::GestureScrollUpdate)
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return true;
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // GesturePinchUpdate scales can be combined only if they share a focal point,
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // e.g., with double-tap drag zoom.
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (event.type == WebInputEvent::GesturePinchUpdate &&
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event.x == event_to_coalesce.x &&
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event.y == event_to_coalesce.y)
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return true;
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return false;
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Coalesce(const WebGestureEvent& event_to_coalesce,
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              WebGestureEvent* event) {
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(CanCoalesce(event_to_coalesce, *event));
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (event->type == WebInputEvent::GestureScrollUpdate) {
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    event->data.scrollUpdate.deltaX +=
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        event_to_coalesce.data.scrollUpdate.deltaX;
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    event->data.scrollUpdate.deltaY +=
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        event_to_coalesce.data.scrollUpdate.deltaY;
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else if (event->type == WebInputEvent::GesturePinchUpdate) {
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Ensure the scale remains bounded above 0 and below Infinity so that
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // we can reliably perform operations like log on the values.
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      event->data.pinchUpdate.scale = numeric_limits<float>::min();
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      event->data.pinchUpdate.scale = numeric_limits<float>::max();
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct WebInputEventSize {
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  template <class EventType>
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool Execute(WebInputEvent::Type /* type */, size_t* type_size) const {
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *type_size = sizeof(EventType);
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct WebInputEventClone {
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  template <class EventType>
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool Execute(const WebInputEvent& event,
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               ScopedWebInputEvent* scoped_event) const {
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_EQ(sizeof(EventType), event.size);
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *scoped_event = ScopedWebInputEvent(
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        new EventType(static_cast<const EventType&>(event)));
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct WebInputEventDelete {
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  template <class EventType>
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool Execute(WebInputEvent* event, bool* /* dummy_var */) const {
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!event)
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_EQ(sizeof(EventType), event->size);
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    delete static_cast<EventType*>(event);
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct WebInputEventCanCoalesce {
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  template <class EventType>
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool Execute(const WebInputEvent& event_to_coalesce,
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               const WebInputEvent* event) const {
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (event_to_coalesce.type != event->type)
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_EQ(sizeof(EventType), event->size);
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_EQ(sizeof(EventType), event_to_coalesce.size);
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return CanCoalesce(static_cast<const EventType&>(event_to_coalesce),
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       *static_cast<const EventType*>(event));
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct WebInputEventCoalesce {
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  template <class EventType>
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool Execute(const WebInputEvent& event_to_coalesce,
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               WebInputEvent* event) const {
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Coalesce(static_cast<const EventType&>(event_to_coalesce),
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             static_cast<EventType*>(event));
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)template <typename Operator, typename ArgIn, typename ArgOut>
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Apply(Operator op,
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           WebInputEvent::Type type,
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           const ArgIn& arg_in,
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           ArgOut* arg_out) {
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (WebInputEvent::isMouseEventType(type))
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return op.template Execute<WebMouseEvent>(arg_in, arg_out);
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else if (type == WebInputEvent::MouseWheel)
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return op.template Execute<WebMouseWheelEvent>(arg_in, arg_out);
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else if (WebInputEvent::isKeyboardEventType(type))
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return op.template Execute<WebKeyboardEvent>(arg_in, arg_out);
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else if (WebInputEvent::isTouchEventType(type))
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return op.template Execute<WebTouchEvent>(arg_in, arg_out);
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else if (WebInputEvent::isGestureEventType(type))
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return op.template Execute<WebGestureEvent>(arg_in, arg_out);
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NOTREACHED() << "Unknown webkit event type " << type;
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return false;
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char* WebInputEventTraits::GetName(WebInputEvent::Type type) {
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define CASE_TYPE(t) case WebInputEvent::t:  return #t
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch(type) {
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(Undefined);
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseDown);
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseUp);
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseMove);
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseEnter);
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseLeave);
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(ContextMenu);
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(MouseWheel);
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(RawKeyDown);
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(KeyDown);
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(KeyUp);
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(Char);
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureScrollBegin);
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureScrollEnd);
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureScrollUpdate);
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureFlingStart);
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureFlingCancel);
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureShowPress);
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureTap);
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureTapUnconfirmed);
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureTapDown);
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureTapCancel);
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureDoubleTap);
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureTwoFingerTap);
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureLongPress);
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GestureLongTap);
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GesturePinchBegin);
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GesturePinchEnd);
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(GesturePinchUpdate);
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(TouchStart);
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(TouchMove);
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(TouchEnd);
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(TouchCancel);
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    default:
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Must include default to let blink::WebInputEvent add new event types
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // before they're added here.
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      DLOG(WARNING) <<
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "Unhandled WebInputEvent type in WebInputEventTraits::GetName.\n";
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#undef CASE_TYPE
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return "";
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)size_t WebInputEventTraits::GetSize(WebInputEvent::Type type) {
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t size = 0;
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Apply(WebInputEventSize(), type, type, &size);
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return size;
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ScopedWebInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedWebInputEvent scoped_event;
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Apply(WebInputEventClone(), event.type, event, &scoped_event);
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return scoped_event.Pass();
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebInputEventTraits::Delete(WebInputEvent* event) {
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!event)
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool dummy_var = false;
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Apply(WebInputEventDelete(), event->type, event, &dummy_var);
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebInputEventTraits::CanCoalesce(const WebInputEvent& event_to_coalesce,
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                      const WebInputEvent& event) {
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Early out before casting.
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (event_to_coalesce.type != event.type)
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return Apply(WebInputEventCanCoalesce(),
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               event.type,
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               event_to_coalesce,
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               &event);
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                   WebInputEvent* event) {
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(event);
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool WebInputEventTraits::IgnoresAckDisposition(const WebInputEvent& event) {
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  switch (event.type) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WebInputEvent::MouseDown:
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WebInputEvent::MouseUp:
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WebInputEvent::MouseEnter:
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WebInputEvent::MouseLeave:
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WebInputEvent::ContextMenu:
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureScrollBegin:
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureScrollEnd:
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureShowPress:
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureTapUnconfirmed:
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureTapDown:
3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GestureTapCancel:
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GesturePinchBegin:
3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::GesturePinchEnd:
3605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::TouchCancel:
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return true;
3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::TouchStart:
3635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::TouchMove:
3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case WebInputEvent::TouchEnd:
3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return !static_cast<const WebTouchEvent&>(event).cancelable;
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return false;
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace content
372