15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gestures/gesture_sequence.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/command_line.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event_constants.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gestures/gesture_configuration.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gestures/gesture_util.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/ui_base_switches.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui::EventType is mapped to TouchState so it can fit into 3 bits of
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Signature.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum TouchState {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_RELEASED,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_PRESSED,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_MOVED,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_STATIONARY,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_CANCELLED,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TS_UNKNOWN,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui::EventResult is mapped to TouchStatusInternal to simply indicate whether a
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processed touch-event should affect gesture-recognition or not.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum TouchStatusInternal {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TSI_NOT_PROCESSED,  // The touch-event should take-part into
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // gesture-recognition only if the touch-event has not
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // been processed.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TSI_PROCESSED,      // The touch-event should affect gesture-recognition only
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // if the touch-event has been processed. For example,,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // this means that a JavaScript touch handler called
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // |preventDefault| on the associated touch event
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // or was processed by an aura-window or views-view.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TSI_ALWAYS          // The touch-event should always affect gesture
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      // recognition.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get equivalent TouchState from EventType |type|.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchState TouchEventTypeToTouchState(ui::EventType type) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_RELEASED:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TS_RELEASED;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_PRESSED:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TS_PRESSED;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_MOVED:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TS_MOVED;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_STATIONARY:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TS_STATIONARY;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_CANCELLED:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TS_CANCELLED;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Unknown Touch Event type";
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TS_UNKNOWN;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gesture signature types for different values of combination (GestureState,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// touch_id, ui::EventType, touch_handled), see Signature for more info.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: New addition of types should be placed as per their Signature value.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define G(gesture_state, id, touch_state, handled) 1 + ( \
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (((touch_state) & 0x7) << 1) |                         \
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ((handled & 0x3) << 4) |                               \
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (((id) & 0xfff) << 6) |                                \
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ((gesture_state) << 18))
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum EdgeStateSignatureType {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_INVALID = -1,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_NO_GESTURE_FIRST_PRESSED =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_NO_GESTURE, 0, TS_PRESSED, TSI_NOT_PROCESSED),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED =
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_RELEASED, TSI_NOT_PROCESSED),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED =
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_RELEASED, TSI_PROCESSED),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore processed touch-move events until gesture-scroll starts.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED =
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_MOVED, TSI_NOT_PROCESSED),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED =
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_MOVED, TSI_PROCESSED),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_STATIONARY, TSI_NOT_PROCESSED),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED =
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 0, TS_CANCELLED, TSI_ALWAYS),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED =
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_SYNTHETIC_CLICK, 1, TS_PRESSED, TSI_NOT_PROCESSED),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_SCROLL_FIRST_RELEASED =
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_SCROLL, 0, TS_RELEASED, TSI_ALWAYS),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once scroll has started, process all touch-move events.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_SCROLL_FIRST_MOVED =
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_SCROLL, 0, TS_MOVED, TSI_ALWAYS),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_SCROLL_FIRST_CANCELLED =
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_SCROLL_SECOND_PRESSED =
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_SCROLL, 1, TS_PRESSED, TSI_NOT_PROCESSED),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED =
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 0, TS_RELEASED, TSI_NOT_PROCESSED),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED_HANDLED =
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 0, TS_RELEASED, TSI_PROCESSED),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED =
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 1, TS_RELEASED, TSI_NOT_PROCESSED),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED_HANDLED =
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 1, TS_RELEASED, TSI_PROCESSED),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_FIRST_MOVED =
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 0, TS_MOVED, TSI_ALWAYS),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_SECOND_MOVED =
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 1, TS_MOVED, TSI_ALWAYS),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_FIRST_CANCELLED =
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 0, TS_CANCELLED, TSI_ALWAYS),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_SECOND_CANCELLED =
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 1, TS_CANCELLED, TSI_ALWAYS),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PENDING_TWO_FINGER_TAP_THIRD_PRESSED =
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PENDING_TWO_FINGER_TAP, 2, TS_PRESSED, TSI_NOT_PROCESSED),
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIRST_MOVED =
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 0, TS_MOVED, TSI_NOT_PROCESSED),
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GST_PINCH_FIRST_MOVED_HANDLED =
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 0, TS_MOVED, TSI_PROCESSED),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_SECOND_MOVED =
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 1, TS_MOVED, TSI_NOT_PROCESSED),
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GST_PINCH_SECOND_MOVED_HANDLED =
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 1, TS_MOVED, TSI_PROCESSED),
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIRST_RELEASED =
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 0, TS_RELEASED, TSI_ALWAYS),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_SECOND_RELEASED =
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 1, TS_RELEASED, TSI_ALWAYS),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIRST_CANCELLED =
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 0, TS_CANCELLED, TSI_ALWAYS),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_SECOND_CANCELLED =
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 1, TS_CANCELLED, TSI_ALWAYS),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_THIRD_PRESSED =
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 2, TS_PRESSED, TSI_NOT_PROCESSED),
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_THIRD_MOVED =
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 2, TS_MOVED, TSI_NOT_PROCESSED),
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GST_PINCH_THIRD_MOVED_HANDLED =
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 2, TS_MOVED, TSI_PROCESSED),
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_THIRD_RELEASED =
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 2, TS_RELEASED, TSI_ALWAYS),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_THIRD_CANCELLED =
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 2, TS_CANCELLED, TSI_ALWAYS),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FOURTH_PRESSED =
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 3, TS_PRESSED, TSI_NOT_PROCESSED),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FOURTH_MOVED =
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 3, TS_MOVED, TSI_NOT_PROCESSED),
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GST_PINCH_FOURTH_MOVED_HANDLED =
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 3, TS_MOVED, TSI_PROCESSED),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FOURTH_RELEASED =
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 3, TS_RELEASED, TSI_ALWAYS),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FOURTH_CANCELLED =
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 3, TS_CANCELLED, TSI_ALWAYS),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIFTH_PRESSED =
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 4, TS_PRESSED, TSI_NOT_PROCESSED),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIFTH_MOVED =
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 4, TS_MOVED, TSI_NOT_PROCESSED),
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GST_PINCH_FIFTH_MOVED_HANDLED =
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      G(GS_PINCH, 4, TS_MOVED, TSI_PROCESSED),
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIFTH_RELEASED =
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 4, TS_RELEASED, TSI_ALWAYS),
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GST_PINCH_FIFTH_CANCELLED =
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      G(GS_PINCH, 4, TS_CANCELLED, TSI_ALWAYS),
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Builds a signature. Signatures are assembled by joining together
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiple bits.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1 LSB bit so that the computed signature is always greater than 0
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3 bits for the |type|.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2 bit for |touch_status|
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 12 bits for |touch_id|
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 14 bits for the |gesture_state|.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EdgeStateSignatureType Signature(GestureState gesture_state,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 unsigned int touch_id,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ui::EventType type,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 TouchStatusInternal touch_status) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK((touch_id & 0xfff) == touch_id);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchState touch_state = TouchEventTypeToTouchState(type);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EdgeStateSignatureType signature = static_cast<EdgeStateSignatureType>
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (G(gesture_state, touch_id, touch_state, touch_status));
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (signature) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_NO_GESTURE_FIRST_PRESSED:
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED:
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED:
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED:
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED:
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED:
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_RELEASED:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_MOVED:
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_CANCELLED:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_SECOND_PRESSED:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED_HANDLED:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED_HANDLED:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_MOVED:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_MOVED:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_CANCELLED:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_CANCELLED:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_THIRD_PRESSED:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_MOVED:
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FIRST_MOVED_HANDLED:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_MOVED:
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_SECOND_MOVED_HANDLED:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_RELEASED:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_RELEASED:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_CANCELLED:
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_CANCELLED:
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_PRESSED:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_MOVED:
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_THIRD_MOVED_HANDLED:
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_RELEASED:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_CANCELLED:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_PRESSED:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_MOVED:
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FOURTH_MOVED_HANDLED:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_RELEASED:
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_CANCELLED:
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_PRESSED:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_MOVED:
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FIFTH_MOVED_HANDLED:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_RELEASED:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_CANCELLED:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signature = GST_INVALID;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return signature;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef G
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float BoundingBoxDiagonal(const gfx::Rect& rect) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float width = rect.width() * rect.width();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float height = rect.height() * rect.height();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqrt(width + height);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int ComputeTouchBitmask(const GesturePoint* points) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int touch_bitmask = 0;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (points[i].in_use())
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      touch_bitmask |= 1 << points[i].touch_id();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return touch_bitmask;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kFlingCurveNormalization = 1.0f / 1875.f;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)float CalibrateFlingVelocity(float velocity) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const unsigned last_coefficient =
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GestureConfiguration::NumAccelParams - 1;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float normalized_velocity = fabs(velocity * kFlingCurveNormalization);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float nu = 0.0f, x = 1.f;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = last_coefficient ; i >= 0; i--) {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float a = GestureConfiguration::fling_acceleration_curve_coefficients(i);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nu += x * a;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x *= normalized_velocity;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (velocity < 0.f)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::max(nu * velocity, -GestureConfiguration::fling_velocity_cap());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::min(nu * velocity, GestureConfiguration::fling_velocity_cap());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GestureSequence Public:
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GestureSequence::GestureSequence(GestureEventHelper* helper)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : state_(GS_NO_GESTURE),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_(0),
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_start_(0.f),
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_current_(0.f),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scroll_type_(ST_FREE),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point_count_(0),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helper_(helper) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GestureSequence::~GestureSequence() {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TouchEvent& event,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventResult result) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopLongPressTimerIfRequired(event);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_touch_location_ = event.location();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result & ER_CONSUMED)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set a limit on the number of simultaneous touches in a gesture.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.touch_id() >= kMaxGesturePoints)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.type() == ui::ET_TOUCH_PRESSED) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point_count_ == kMaxGesturePoints)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GesturePoint* new_point = &points_[event.touch_id()];
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We shouldn't be able to get two PRESSED events from the same
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // finger without either a RELEASE or CANCEL in between. But let's not crash
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in a release build.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_point->in_use()) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Received a second press for a point: " << event.touch_id();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_point->ResetVelocity();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_point->UpdateValues(event);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_point->set_point_id(point_count_++);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_point->set_touch_id(event.touch_id());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GestureState last_state = state_;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: when modifying these state transitions, also update gestures.dot
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Gestures> gestures(new Gestures());
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GesturePoint& point = GesturePointForEvent(event);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  point.UpdateValues(event);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecreateBoundingBox();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags_ = event.flags();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int point_id = point.point_id();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point_id < 0)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send GESTURE_BEGIN for any touch pressed.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.type() == ui::ET_TOUCH_PRESSED)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendBeginGestureEvent(point, gestures.get());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchStatusInternal status_internal = (result == ER_UNHANDLED) ?
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TSI_NOT_PROCESSED : TSI_PROCESSED;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EdgeStateSignatureType signature = Signature(state_, point_id,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.type(), status_internal);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (signature == GST_INVALID)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signature = Signature(state_, point_id, event.type(), TSI_ALWAYS);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (signature) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_INVALID:
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_NO_GESTURE_FIRST_PRESSED:
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TouchDown(event, point, gestures.get());
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_PENDING_SYNTHETIC_CLICK);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED:
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Click(event, point, gestures.get()))
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        point.UpdateForTap();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PrependTapCancelGestureEvent(point, gestures.get());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_NO_GESTURE);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY:
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ScrollStart(event, point, gestures.get())) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PrependTapCancelGestureEvent(point, gestures.get());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_state(GS_SCROLL);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ScrollUpdate(event, point, gestures.get()))
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          point.UpdateForScroll();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED:
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(rbyers): This should be able to trigger a TapCancel
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if we moved far enough. crbug.com/146397
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED:
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrependTapCancelGestureEvent(point, gestures.get());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_NO_GESTURE);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_MOVED:
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (scroll_type_ == ST_VERTICAL ||
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          scroll_type_ == ST_HORIZONTAL)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BreakRailScroll(event, point, gestures.get());
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ScrollUpdate(event, point, gestures.get()))
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        point.UpdateForScroll();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_RELEASED:
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_SCROLL_FIRST_CANCELLED:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScrollEnd(event, point, gestures.get());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_NO_GESTURE);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrependTapCancelGestureEvent(point, gestures.get());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsSecondTouchDownCloseEnoughForTwoFingerTap()) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TwoFingerTouchDown(event, point, gestures.get());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_state(GS_PENDING_TWO_FINGER_TAP);
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // fall through
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GST_SCROLL_SECOND_PRESSED:
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PinchStart(event, point, gestures.get());
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      set_state(GS_PINCH);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED:
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED:
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TwoFingerTouchReleased(event, point, gestures.get());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_SCROLL);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_MOVED:
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_MOVED:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (TwoFingerTouchMove(event, point, gestures.get()))
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_state(GS_PINCH);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED_HANDLED:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED_HANDLED:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_FIRST_CANCELLED:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_SECOND_CANCELLED:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scroll_type_ = ST_FREE;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_SCROLL);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PENDING_TWO_FINGER_TAP_THIRD_PRESSED:
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PinchStart(event, point, gestures.get());
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_state(GS_PINCH);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FIRST_MOVED_HANDLED:
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_SECOND_MOVED_HANDLED:
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_THIRD_MOVED_HANDLED:
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FOURTH_MOVED_HANDLED:
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GST_PINCH_FIFTH_MOVED_HANDLED:
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_MOVED:
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_MOVED:
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_MOVED:
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_MOVED:
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_MOVED:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (PinchUpdate(event, point, gestures.get())) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int i = 0; i < point_count_; ++i)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetPointByPointId(i)->UpdateForScroll();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_RELEASED:
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_RELEASED:
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_RELEASED:
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_RELEASED:
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_RELEASED:
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIRST_CANCELLED:
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_SECOND_CANCELLED:
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_CANCELLED:
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_CANCELLED:
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_CANCELLED:
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Was it a swipe? i.e. were all the fingers moving in the same
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // direction?
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeSwipe(event, point, gestures.get());
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (point_count_ == 2) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PinchEnd(event, point, gestures.get());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Once pinch ends, it should still be possible to scroll with the
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // remaining finger on the screen.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_state(GS_SCROLL);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Nothing else to do if we have more than 2 fingers active, since after
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the release/cancel, there are still enough fingers to do pinch.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // pinch_distance_current_ and pinch_distance_start_ will be updated
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // when the bounding-box is updated.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetVelocities();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_THIRD_PRESSED:
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FOURTH_PRESSED:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GST_PINCH_FIFTH_PRESSED:
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_start_ = pinch_distance_current_;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.type() == ui::ET_TOUCH_RELEASED ||
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.type() == ui::ET_TOUCH_CANCELLED)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendEndGestureEvent(point, gestures.get());
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ != last_state)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(4) << "Gesture Sequence"
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " State: " << state_
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " touch id: " << event.touch_id();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetLongPressTimer()->Stop();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of point_ids must be contiguous and include 0.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When a touch point is released, all points with ids greater than the
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // released point must have their ids decremented, or the set of point_ids
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // could end up with gaps.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.type() == ui::ET_TOUCH_RELEASED ||
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.type() == ui::ET_TOUCH_CANCELLED) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMaxGesturePoints; ++i) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GesturePoint& iter_point = points_[i];
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (iter_point.point_id() > point.point_id())
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iter_point.set_point_id(iter_point.point_id() - 1);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    point.Reset();
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --point_count_;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(point_count_, 0);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecreateBoundingBox();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state_ == GS_PINCH) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pinch_distance_start_ = pinch_distance_current_;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const ui::LatencyInfo* touch_latency = event.latency();
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Gestures::iterator it = gestures->begin();
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (; it != gestures->end(); it++) {
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    (*it)->latency()->MergeWith(*touch_latency);
566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gestures.release();
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::RecreateBoundingBox() {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Recreating the bounding box at every touch-event is not very
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // efficient. This should be made better.
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (point_count_ == 0) {
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bounding_box_.SetRect(0, 0, 0, 0);
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (point_count_ == 1) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounding_box_ = GetPointByPointId(0)->enclosing_rectangle();
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int left = INT_MAX / 20, top = INT_MAX / 20;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int right = INT_MIN / 20, bottom = INT_MIN / 20;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMaxGesturePoints; ++i) {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!points_[i].in_use())
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Using the |enclosing_rectangle()| for the touch-points would be ideal.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // However, this becomes brittle especially when a finger is in motion
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // because the change in radius can overshadow the actual change in
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // position. So the actual position of the point is used instead.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const gfx::Point& point = points_[i].last_touch_position();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left = std::min(left, point.x());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      right = std::max(right, point.x());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top = std::min(top, point.y());
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bottom = std::max(bottom, point.y());
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounding_box_.SetRect(left, top, right - left, bottom - top);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::ResetVelocities() {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kMaxGesturePoints; ++i) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (points_[i].in_use())
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      points_[i].ResetVelocity();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GestureSequence Protected:
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::OneShotTimer<GestureSequence>* GestureSequence::CreateTimer() {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new base::OneShotTimer<GestureSequence>();
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::OneShotTimer<GestureSequence>* GestureSequence::GetLongPressTimer() {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!long_press_timer_.get())
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long_press_timer_.reset(CreateTimer());
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return long_press_timer_.get();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GestureSequence Private:
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GesturePoint& GestureSequence::GesturePointForEvent(
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TouchEvent& event) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return points_[event.touch_id()];
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GesturePoint* GestureSequence::GetPointByPointId(int point_id) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(0 <= point_id && point_id < kMaxGesturePoints);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kMaxGesturePoints; ++i) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GesturePoint& point = points_[i];
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point.in_use() && point.point_id() == point_id)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &point;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::IsSecondTouchDownCloseEnoughForTwoFingerTap() {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point p1 = GetPointByPointId(0)->last_touch_position();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point p2 = GetPointByPointId(1)->last_touch_position();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double max_distance =
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureConfiguration::max_distance_for_two_finger_tap_in_pixels();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double distance = (p1.x() - p2.x()) * (p1.x() - p2.x()) +
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (p1.y() - p2.y()) * (p1.y() - p2.y());
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (distance < max_distance * max_distance)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GestureEvent* GestureSequence::CreateGestureEvent(
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GestureEventDetails& details,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& location,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int flags,
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time timestamp,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int touch_id_bitmask) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GestureEventDetails gesture_details(details);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gesture_details.set_touch_points(point_count_);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gesture_details.set_bounding_box(bounding_box_);
65890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::TimeDelta time_stamp =
65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::TimeDelta::FromMicroseconds(timestamp.ToDoubleT() * 1000000);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new GestureEvent(gesture_details.type(), location.x(), location.y(),
66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          flags, time_stamp, gesture_details,
66290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          touch_id_bitmask);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                Gestures* gestures) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0),
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point.first_touch_position(),
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::PrependTapCancelGestureEvent(const GesturePoint& point,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            Gestures* gestures) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->insert(gestures->begin(), CreateGestureEvent(
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GestureEventDetails(ui::ET_GESTURE_TAP_CANCEL, 0, 0),
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    point.first_touch_position(),
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags_,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time::FromDoubleT(point.last_touch_time()),
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1 << point.touch_id()));
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendBeginGestureEvent(const GesturePoint& point,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Gestures* gestures) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0),
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point.first_touch_position(),
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendEndGestureEvent(const GesturePoint& point,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Gestures* gestures) {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_END, 0, 0),
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point.first_touch_position(),
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendClickGestureEvent(const GesturePoint& point,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int tap_count,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Gestures* gestures) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect er = point.enclosing_rectangle();
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point center = er.CenterPoint();
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_TAP, tap_count, 0),
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      center,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendScrollGestureBegin(const GesturePoint& point,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const gfx::Point& location,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               Gestures* gestures) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      location,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const gfx::Point& location,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             Gestures* gestures,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             float x_velocity,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             float y_velocity) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float railed_x_velocity = x_velocity;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float railed_y_velocity = y_velocity;
736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  last_scroll_prediction_offset_.set_x(0);
737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  last_scroll_prediction_offset_.set_y(0);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scroll_type_ == ST_HORIZONTAL)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    railed_y_velocity = 0;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (scroll_type_ == ST_VERTICAL)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    railed_x_velocity = 0;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (railed_x_velocity != 0 || railed_y_velocity != 0) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gestures->push_back(CreateGestureEvent(
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GestureEventDetails(ui::ET_SCROLL_FLING_START,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CalibrateFlingVelocity(railed_x_velocity),
749f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch            CalibrateFlingVelocity(railed_y_velocity),
750f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch            CalibrateFlingVelocity(x_velocity),
751f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch            CalibrateFlingVelocity(y_velocity)),
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flags_,
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Time::FromDoubleT(point.last_touch_time()),
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        1 << point.touch_id()));
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gestures->push_back(CreateGestureEvent(
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0),
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flags_,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Time::FromDoubleT(point.last_touch_time()),
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        1 << point.touch_id()));
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendScrollGestureUpdate(GesturePoint& point,
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                Gestures* gestures) {
768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static bool use_scroll_prediction = CommandLine::ForCurrentProcess()->
769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HasSwitch(switches::kEnableScrollPrediction);
770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Vector2dF d;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point location;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point_count_ == 1) {
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    d = point.ScrollDelta();
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    location = point.last_touch_position();
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    location = bounding_box_.CenterPoint();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    d = location - latest_multi_scroll_update_location_;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    latest_multi_scroll_update_location_ = location;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (use_scroll_prediction) {
782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Remove the extra distance added by the last scroll prediction and add
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // the new prediction offset.
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d -= last_scroll_prediction_offset_;
785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    last_scroll_prediction_offset_.set_x(
786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GestureConfiguration::scroll_prediction_seconds() * point.XVelocity());
787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    last_scroll_prediction_offset_.set_y(
788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GestureConfiguration::scroll_prediction_seconds() * point.YVelocity());
789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d += last_scroll_prediction_offset_;
790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    location += gfx::Vector2d(last_scroll_prediction_offset_.x(),
791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              last_scroll_prediction_offset_.y());
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
794f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  gfx::Vector2dF o = d;
795f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scroll_type_ == ST_HORIZONTAL)
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    d.set_y(0);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (scroll_type_ == ST_VERTICAL)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    d.set_x(0);
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (d.IsZero())
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
803f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  GestureEventDetails details(ui::ET_GESTURE_SCROLL_UPDATE,
804f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch                              d.x(), d.y(), o.x(), o.y());
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details.SetScrollVelocity(
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scroll_type_ == ST_VERTICAL ? 0 : point.XVelocity(),
807f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch      scroll_type_ == ST_HORIZONTAL ? 0 : point.YVelocity(),
808f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch      point.XVelocity(),
809f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch      point.YVelocity());
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      details,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      location,
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ComputeTouchBitmask(points_)));
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1,
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const GesturePoint& p2,
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Gestures* gestures) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point center = bounding_box_.CenterPoint();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_PINCH_BEGIN, 0, 0),
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      center,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(p1.last_touch_time()),
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << p1.touch_id() | 1 << p2.touch_id()));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1,
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const GesturePoint& p2,
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            float scale,
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            Gestures* gestures) {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point center = bounding_box_.CenterPoint();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_PINCH_END, 0, 0),
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      center,
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(p1.last_touch_time()),
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << p1.touch_id() | 1 << p2.touch_id()));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point,
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               float scale,
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               Gestures* gestures) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Compute rotation and include it in delta_y.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/113145
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_PINCH_UPDATE, scale, 0),
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounding_box_.CenterPoint(),
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ComputeTouchBitmask(points_)));
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendSwipeGesture(const GesturePoint& point,
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int swipe_x,
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int swipe_y,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Gestures* gestures) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_MULTIFINGER_SWIPE, swipe_x, swipe_y),
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounding_box_.CenterPoint(),
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ComputeTouchBitmask(points_)));
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendTwoFingerTapGestureEvent(Gestures* gestures) {
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GesturePoint* point = GetPointByPointId(0);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect rect = point->enclosing_rectangle();
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_TWO_FINGER_TAP,
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          rect.width(),
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          rect.height()),
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point->enclosing_rectangle().CenterPoint(),
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point->last_touch_time()),
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point->touch_id()));
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::Click(const TouchEvent& event,
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const GesturePoint& point,
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            Gestures* gestures) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point.IsInClickWindow(event)) {
88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tap_count = 1;
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (point.IsInTripleClickWindow(event))
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      tap_count = 3;
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else if (point.IsInDoubleClickWindow(event))
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      tap_count = 2;
89190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AppendClickGestureEvent(point, tap_count, gestures);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (point.IsInsideManhattanSquare(event) &&
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetLongPressTimer()->IsRunning()) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendLongTapGestureEvent(point, gestures);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::ScrollStart(const TouchEvent& event,
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  GesturePoint& point,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  Gestures* gestures) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK);
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!point.IsConsistentScrollingActionUnderway() &&
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !point.IsInScrollWindow(event))
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendScrollGestureBegin(point, point.first_touch_position(), gestures);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point.IsInHorizontalRailWindow())
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scroll_type_ = ST_HORIZONTAL;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (point.IsInVerticalRailWindow())
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scroll_type_ = ST_VERTICAL;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scroll_type_ = ST_FREE;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::BreakRailScroll(const TouchEvent& event,
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      GesturePoint& point,
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      Gestures* gestures) {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_SCROLL);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scroll_type_ == ST_HORIZONTAL &&
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point.BreaksHorizontalRail())
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scroll_type_ = ST_FREE;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (scroll_type_ == ST_VERTICAL &&
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           point.BreaksVerticalRail())
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scroll_type_ = ST_FREE;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::ScrollUpdate(const TouchEvent& event,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   GesturePoint& point,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Gestures* gestures) {
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_SCROLL);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point.DidScroll(event, 0))
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendScrollGestureUpdate(point, gestures);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::TouchDown(const TouchEvent& event,
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const GesturePoint& point,
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Gestures* gestures) {
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_NO_GESTURE);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendTapDownGestureEvent(point, gestures);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressTimer()->Start(
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GestureConfiguration::long_press_time_in_seconds() * 1000),
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &GestureSequence::AppendLongPressGestureEvent);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::TwoFingerTouchDown(const TouchEvent& event,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const GesturePoint& point,
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Gestures* gestures) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || state_ == GS_SCROLL);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == GS_SCROLL) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendScrollGestureEnd(point, point.last_touch_position(), gestures,
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0.f, 0.f);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  second_touch_time_ = event.time_stamp();
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::TwoFingerTouchMove(const TouchEvent& event,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const GesturePoint& point,
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Gestures* gestures) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PENDING_TWO_FINGER_TAP);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta time_delta = event.time_stamp() - second_touch_time_;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta max_delta = base::TimeDelta::FromMilliseconds(1000 *
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::GestureConfiguration::max_touch_down_duration_in_seconds_for_click());
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time_delta > max_delta || !point.IsInsideManhattanSquare(event)) {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PinchStart(event, point, gestures);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::TwoFingerTouchReleased(const TouchEvent& event,
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const GesturePoint& point,
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             Gestures* gestures) {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PENDING_TWO_FINGER_TAP);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta time_delta = event.time_stamp() - second_touch_time_;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta max_delta = base::TimeDelta::FromMilliseconds(1000 *
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::GestureConfiguration::max_touch_down_duration_in_seconds_for_click());
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time_delta < max_delta && point.IsInsideManhattanSquare(event))
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendTwoFingerTapGestureEvent(gestures);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendLongPressGestureEvent() {
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GesturePoint* point = GetPointByPointId(0);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<GestureEvent> gesture(CreateGestureEvent(
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 0, 0),
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      point->first_touch_position(),
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point->last_touch_time()),
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point->touch_id()));
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper_->DispatchLongPressGestureEvent(gesture.get());
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::AppendLongTapGestureEvent(const GesturePoint& point,
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                Gestures* gestures) {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect er = point.enclosing_rectangle();
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point center = er.CenterPoint();
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gestures->push_back(CreateGestureEvent(
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureEventDetails(ui::ET_GESTURE_LONG_TAP, 0, 0),
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      center,
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_,
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::FromDoubleT(point.last_touch_time()),
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1 << point.touch_id()));
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::ScrollEnd(const TouchEvent& event,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                GesturePoint& point,
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Gestures* gestures) {
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_SCROLL);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point.IsInFlickWindow(event)) {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendScrollGestureEnd(point, point.last_touch_position(), gestures,
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        point.XVelocity(), point.YVelocity());
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendScrollGestureEnd(point, point.last_touch_position(), gestures,
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0.f, 0.f);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::PinchStart(const TouchEvent& event,
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const GesturePoint& point,
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 Gestures* gestures) {
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_SCROLL ||
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         state_ == GS_PENDING_SYNTHETIC_CLICK ||
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         state_ == GS_PENDING_TWO_FINGER_TAP);
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once pinch starts, we immediately break rail scroll.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scroll_type_ = ST_FREE;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GesturePoint* point1 = GetPointByPointId(0);
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GesturePoint* point2 = GetPointByPointId(1);
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pinch_distance_start_ = pinch_distance_current_;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  latest_multi_scroll_update_location_ = bounding_box_.CenterPoint();
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendPinchGestureBegin(*point1, *point2, gestures);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == GS_PENDING_SYNTHETIC_CLICK ||
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ == GS_PENDING_TWO_FINGER_TAP) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point center = bounding_box_.CenterPoint();
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendScrollGestureBegin(point, center, gestures);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::PinchUpdate(const TouchEvent& event,
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  GesturePoint& point,
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  Gestures* gestures) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PINCH);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is possible that the none of the touch-points changed their position,
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but their radii changed, and that caused the bounding box to also change.
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But in such cases, we do not want to either pinch or scroll.
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To avoid small jiggles, it is also necessary to make sure that at least one
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the fingers moved enough before a pinch or scroll update is created.
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_scroll = false;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kMaxGesturePoints; ++i) {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!points_[i].in_use() || !points_[i].DidScroll(event, 0))
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_scroll = true;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!did_scroll)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float distance = BoundingBoxDiagonal(bounding_box_);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (abs(distance - pinch_distance_current_) >=
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GestureConfiguration::min_pinch_update_distance_in_pixels()) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendPinchGestureUpdate(point,
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        distance / pinch_distance_current_, gestures);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pinch_distance_current_ = distance;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendScrollGestureUpdate(point, gestures);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::PinchEnd(const TouchEvent& event,
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const GesturePoint& point,
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               Gestures* gestures) {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PINCH);
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GesturePoint* point1 = GetPointByPointId(0);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GesturePoint* point2 = GetPointByPointId(1);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float distance = BoundingBoxDiagonal(bounding_box_);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendPinchGestureEnd(*point1, *point2,
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distance / pinch_distance_start_, gestures);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pinch_distance_start_ = 0;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pinch_distance_current_ = 0;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GestureSequence::MaybeSwipe(const TouchEvent& event,
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const GesturePoint& point,
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 Gestures* gestures) {
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state_ == GS_PINCH);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float velocity_x = 0.f, velocity_y = 0.f;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool swipe_x = true, swipe_y = true;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sign_x = 0, sign_y = 0;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = 0;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < kMaxGesturePoints; ++i) {
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (points_[i].in_use())
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(i < kMaxGesturePoints);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  velocity_x = points_[i].XVelocity();
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  velocity_y = points_[i].YVelocity();
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sign_x = velocity_x < 0.f ? -1 : 1;
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sign_y = velocity_y < 0.f ? -1 : 1;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (++i; i < kMaxGesturePoints; ++i) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!points_[i].in_use())
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sign_x * points_[i].XVelocity() < 0)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      swipe_x = false;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sign_y * points_[i].YVelocity() < 0)
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      swipe_y = false;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    velocity_x += points_[i].XVelocity();
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    velocity_y += points_[i].YVelocity();
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float min_velocity = GestureConfiguration::min_swipe_speed();
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  min_velocity *= min_velocity;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  velocity_x = fabs(velocity_x / point_count_);
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  velocity_y = fabs(velocity_y / point_count_);
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (velocity_x < min_velocity)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    swipe_x = false;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (velocity_y < min_velocity)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    swipe_y = false;
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!swipe_x && !swipe_y)
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!swipe_x)
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    velocity_x = 0.001f;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!swipe_y)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    velocity_y = 0.001f;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float ratio = velocity_x > velocity_y ? velocity_x / velocity_y :
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          velocity_y / velocity_x;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ratio < GestureConfiguration::max_swipe_deviation_ratio())
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (velocity_x > velocity_y)
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sign_y = 0;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sign_x = 0;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendSwipeGesture(point, sign_x, sign_y, gestures);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GestureSequence::StopLongPressTimerIfRequired(const TouchEvent& event) {
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetLongPressTimer()->IsRunning() ||
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.type() != ui::ET_TOUCH_MOVED)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since long press timer has been started, there should be a non-NULL point.
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GesturePoint* point = GetPointByPointId(0);
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(),
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.location()))
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetLongPressTimer()->Stop();
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
1187