1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/events/gestures/gesture_provider_aura.h" 6 7 #include "base/auto_reset.h" 8 #include "base/logging.h" 9 #include "ui/events/event.h" 10 #include "ui/events/gesture_detection/gesture_config_helper.h" 11 #include "ui/events/gesture_detection/gesture_event_data.h" 12 #include "ui/events/gestures/gesture_configuration.h" 13 14 namespace ui { 15 16 GestureProviderAura::GestureProviderAura(GestureProviderAuraClient* client) 17 : client_(client), 18 filtered_gesture_provider_(ui::DefaultGestureProviderConfig(), this), 19 handling_event_(false) { 20 filtered_gesture_provider_.SetDoubleTapSupportForPlatformEnabled(false); 21 } 22 23 GestureProviderAura::~GestureProviderAura() {} 24 25 bool GestureProviderAura::OnTouchEvent(const TouchEvent& event) { 26 int index = pointer_state_.FindPointerIndexOfId(event.touch_id()); 27 bool pointer_id_is_active = index != -1; 28 29 if (event.type() == ET_TOUCH_PRESSED && pointer_id_is_active) { 30 // Ignore touch press events if we already believe the pointer is down. 31 return false; 32 } else if (event.type() != ET_TOUCH_PRESSED && !pointer_id_is_active) { 33 // We could have an active touch stream transfered to us, resulting in touch 34 // move or touch up events without associated touch down events. Ignore 35 // them. 36 return false; 37 } 38 39 // If this is a touchmove event, and it isn't different from the last 40 // event, ignore it. 41 if (event.type() == ET_TOUCH_MOVED && 42 event.x() == pointer_state_.GetX(index) && 43 event.y() == pointer_state_.GetY(index)) { 44 return false; 45 } 46 47 last_touch_event_latency_info_ = *event.latency(); 48 pointer_state_.OnTouch(event); 49 50 bool result = filtered_gesture_provider_.OnTouchEvent(pointer_state_); 51 pointer_state_.CleanupRemovedTouchPoints(event); 52 return result; 53 } 54 55 void GestureProviderAura::OnTouchEventAck(bool event_consumed) { 56 DCHECK(pending_gestures_.empty()); 57 DCHECK(!handling_event_); 58 base::AutoReset<bool> handling_event(&handling_event_, true); 59 filtered_gesture_provider_.OnTouchEventAck(event_consumed); 60 last_touch_event_latency_info_.Clear(); 61 } 62 63 void GestureProviderAura::OnGestureEvent( 64 const GestureEventData& gesture) { 65 GestureEventDetails details = gesture.details; 66 details.set_oldest_touch_id(gesture.motion_event_id); 67 68 if (gesture.type() == ET_GESTURE_TAP) { 69 int tap_count = 1; 70 if (previous_tap_ && IsConsideredDoubleTap(*previous_tap_, gesture)) 71 tap_count = 1 + (previous_tap_->details.tap_count() % 3); 72 details.set_tap_count(tap_count); 73 if (!previous_tap_) 74 previous_tap_.reset(new GestureEventData(gesture)); 75 else 76 *previous_tap_ = gesture; 77 previous_tap_->details = details; 78 } else if (gesture.type() == ET_GESTURE_TAP_CANCEL) { 79 previous_tap_.reset(); 80 } 81 82 scoped_ptr<ui::GestureEvent> event( 83 new ui::GestureEvent(gesture.x, 84 gesture.y, 85 gesture.flags, 86 gesture.time - base::TimeTicks(), 87 details)); 88 89 ui::LatencyInfo* gesture_latency = event->latency(); 90 91 gesture_latency->CopyLatencyFrom( 92 last_touch_event_latency_info_, 93 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT); 94 gesture_latency->CopyLatencyFrom( 95 last_touch_event_latency_info_, 96 ui::INPUT_EVENT_LATENCY_UI_COMPONENT); 97 gesture_latency->CopyLatencyFrom( 98 last_touch_event_latency_info_, 99 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT); 100 101 if (!handling_event_) { 102 // Dispatching event caused by timer. 103 client_->OnGestureEvent(event.get()); 104 } else { 105 // Memory managed by ScopedVector pending_gestures_. 106 pending_gestures_.push_back(event.release()); 107 } 108 } 109 110 ScopedVector<GestureEvent>* GestureProviderAura::GetAndResetPendingGestures() { 111 if (pending_gestures_.empty()) 112 return NULL; 113 // Caller is responsible for deleting old_pending_gestures. 114 ScopedVector<GestureEvent>* old_pending_gestures = 115 new ScopedVector<GestureEvent>(); 116 old_pending_gestures->swap(pending_gestures_); 117 return old_pending_gestures; 118 } 119 120 bool GestureProviderAura::IsConsideredDoubleTap( 121 const GestureEventData& previous_tap, 122 const GestureEventData& current_tap) const { 123 if (current_tap.time - previous_tap.time > 124 base::TimeDelta::FromMilliseconds( 125 ui::GestureConfiguration::max_seconds_between_double_click() * 126 1000)) { 127 return false; 128 } 129 130 double double_tap_slop_square = 131 GestureConfiguration::max_distance_between_taps_for_double_tap(); 132 double_tap_slop_square *= double_tap_slop_square; 133 const float delta_x = previous_tap.x - current_tap.x; 134 const float delta_y = previous_tap.y - current_tap.y; 135 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square); 136 } 137 138 } // namespace content 139