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 14namespace ui { 15 16GestureProviderAura::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 23GestureProviderAura::~GestureProviderAura() {} 24 25bool GestureProviderAura::OnTouchEvent(const TouchEvent& event) { 26 bool pointer_id_is_active = false; 27 for (size_t i = 0; i < pointer_state_.GetPointerCount(); ++i) { 28 if (event.touch_id() != pointer_state_.GetPointerId(i)) 29 continue; 30 pointer_id_is_active = true; 31 break; 32 } 33 34 if (event.type() == ET_TOUCH_PRESSED && pointer_id_is_active) { 35 // Ignore touch press events if we already believe the pointer is down. 36 return false; 37 } else if (event.type() != ET_TOUCH_PRESSED && !pointer_id_is_active) { 38 // We could have an active touch stream transfered to us, resulting in touch 39 // move or touch up events without associated touch down events. Ignore 40 // them. 41 return false; 42 } 43 44 last_touch_event_flags_ = event.flags(); 45 last_touch_event_latency_info_ = *event.latency(); 46 pointer_state_.OnTouch(event); 47 48 bool result = filtered_gesture_provider_.OnTouchEvent(pointer_state_); 49 pointer_state_.CleanupRemovedTouchPoints(event); 50 return result; 51} 52 53void GestureProviderAura::OnTouchEventAck(bool event_consumed) { 54 DCHECK(pending_gestures_.empty()); 55 DCHECK(!handling_event_); 56 base::AutoReset<bool> handling_event(&handling_event_, true); 57 filtered_gesture_provider_.OnTouchEventAck(event_consumed); 58 last_touch_event_latency_info_.Clear(); 59} 60 61void GestureProviderAura::OnGestureEvent( 62 const GestureEventData& gesture) { 63 GestureEventDetails details = gesture.details; 64 65 if (gesture.type() == ET_GESTURE_TAP) { 66 int tap_count = 1; 67 if (previous_tap_ && IsConsideredDoubleTap(*previous_tap_, gesture)) 68 tap_count = 1 + (previous_tap_->details.tap_count() % 3); 69 details.set_tap_count(tap_count); 70 if (!previous_tap_) 71 previous_tap_.reset(new GestureEventData(gesture)); 72 else 73 *previous_tap_ = gesture; 74 previous_tap_->details = details; 75 } else if (gesture.type() == ET_GESTURE_TAP_CANCEL) { 76 previous_tap_.reset(); 77 } 78 79 scoped_ptr<ui::GestureEvent> event( 80 new ui::GestureEvent(gesture.type(), 81 gesture.x, 82 gesture.y, 83 last_touch_event_flags_, 84 gesture.time - base::TimeTicks(), 85 details, 86 // ui::GestureEvent stores a bitfield indicating the 87 // ids of active touch points. This is currently only 88 // used when one finger is down, and will eventually 89 // be cleaned up. See crbug.com/366707. 90 1 << gesture.motion_event_id)); 91 92 93 ui::LatencyInfo* gesture_latency = event->latency(); 94 95 gesture_latency->CopyLatencyFrom( 96 last_touch_event_latency_info_, 97 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT); 98 gesture_latency->CopyLatencyFrom( 99 last_touch_event_latency_info_, 100 ui::INPUT_EVENT_LATENCY_UI_COMPONENT); 101 gesture_latency->CopyLatencyFrom( 102 last_touch_event_latency_info_, 103 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT); 104 105 if (!handling_event_) { 106 // Dispatching event caused by timer. 107 client_->OnGestureEvent(event.get()); 108 } else { 109 // Memory managed by ScopedVector pending_gestures_. 110 pending_gestures_.push_back(event.release()); 111 } 112} 113 114ScopedVector<GestureEvent>* GestureProviderAura::GetAndResetPendingGestures() { 115 if (pending_gestures_.empty()) 116 return NULL; 117 // Caller is responsible for deleting old_pending_gestures. 118 ScopedVector<GestureEvent>* old_pending_gestures = 119 new ScopedVector<GestureEvent>(); 120 old_pending_gestures->swap(pending_gestures_); 121 return old_pending_gestures; 122} 123 124bool GestureProviderAura::IsConsideredDoubleTap( 125 const GestureEventData& previous_tap, 126 const GestureEventData& current_tap) const { 127 if (current_tap.time - previous_tap.time > 128 base::TimeDelta::FromMilliseconds( 129 ui::GestureConfiguration::max_seconds_between_double_click() * 130 1000)) { 131 return false; 132 } 133 134 double double_tap_slop_square = 135 GestureConfiguration::max_distance_between_taps_for_double_tap(); 136 double_tap_slop_square *= double_tap_slop_square; 137 const float delta_x = previous_tap.x - current_tap.x; 138 const float delta_y = previous_tap.y - current_tap.y; 139 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square); 140} 141 142} // namespace content 143