// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/events/gestures/gesture_provider_aura.h" #include "base/auto_reset.h" #include "base/logging.h" #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_config_helper.h" #include "ui/events/gesture_detection/gesture_event_data.h" #include "ui/events/gestures/gesture_configuration.h" namespace ui { GestureProviderAura::GestureProviderAura(GestureProviderAuraClient* client) : client_(client), filtered_gesture_provider_(ui::DefaultGestureProviderConfig(), this), handling_event_(false) { filtered_gesture_provider_.SetDoubleTapSupportForPlatformEnabled(false); } GestureProviderAura::~GestureProviderAura() {} bool GestureProviderAura::OnTouchEvent(const TouchEvent& event) { int index = pointer_state_.FindPointerIndexOfId(event.touch_id()); bool pointer_id_is_active = index != -1; if (event.type() == ET_TOUCH_PRESSED && pointer_id_is_active) { // Ignore touch press events if we already believe the pointer is down. return false; } else if (event.type() != ET_TOUCH_PRESSED && !pointer_id_is_active) { // We could have an active touch stream transfered to us, resulting in touch // move or touch up events without associated touch down events. Ignore // them. return false; } // If this is a touchmove event, and it isn't different from the last // event, ignore it. if (event.type() == ET_TOUCH_MOVED && event.x() == pointer_state_.GetX(index) && event.y() == pointer_state_.GetY(index)) { return false; } last_touch_event_latency_info_ = *event.latency(); pointer_state_.OnTouch(event); bool result = filtered_gesture_provider_.OnTouchEvent(pointer_state_); pointer_state_.CleanupRemovedTouchPoints(event); return result; } void GestureProviderAura::OnTouchEventAck(bool event_consumed) { DCHECK(pending_gestures_.empty()); DCHECK(!handling_event_); base::AutoReset<bool> handling_event(&handling_event_, true); filtered_gesture_provider_.OnTouchEventAck(event_consumed); last_touch_event_latency_info_.Clear(); } void GestureProviderAura::OnGestureEvent( const GestureEventData& gesture) { GestureEventDetails details = gesture.details; details.set_oldest_touch_id(gesture.motion_event_id); if (gesture.type() == ET_GESTURE_TAP) { int tap_count = 1; if (previous_tap_ && IsConsideredDoubleTap(*previous_tap_, gesture)) tap_count = 1 + (previous_tap_->details.tap_count() % 3); details.set_tap_count(tap_count); if (!previous_tap_) previous_tap_.reset(new GestureEventData(gesture)); else *previous_tap_ = gesture; previous_tap_->details = details; } else if (gesture.type() == ET_GESTURE_TAP_CANCEL) { previous_tap_.reset(); } scoped_ptr<ui::GestureEvent> event( new ui::GestureEvent(gesture.x, gesture.y, gesture.flags, gesture.time - base::TimeTicks(), details)); ui::LatencyInfo* gesture_latency = event->latency(); gesture_latency->CopyLatencyFrom( last_touch_event_latency_info_, ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT); gesture_latency->CopyLatencyFrom( last_touch_event_latency_info_, ui::INPUT_EVENT_LATENCY_UI_COMPONENT); gesture_latency->CopyLatencyFrom( last_touch_event_latency_info_, ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT); if (!handling_event_) { // Dispatching event caused by timer. client_->OnGestureEvent(event.get()); } else { // Memory managed by ScopedVector pending_gestures_. pending_gestures_.push_back(event.release()); } } ScopedVector<GestureEvent>* GestureProviderAura::GetAndResetPendingGestures() { if (pending_gestures_.empty()) return NULL; // Caller is responsible for deleting old_pending_gestures. ScopedVector<GestureEvent>* old_pending_gestures = new ScopedVector<GestureEvent>(); old_pending_gestures->swap(pending_gestures_); return old_pending_gestures; } bool GestureProviderAura::IsConsideredDoubleTap( const GestureEventData& previous_tap, const GestureEventData& current_tap) const { if (current_tap.time - previous_tap.time > base::TimeDelta::FromMilliseconds( ui::GestureConfiguration::max_seconds_between_double_click() * 1000)) { return false; } double double_tap_slop_square = GestureConfiguration::max_distance_between_taps_for_double_tap(); double_tap_slop_square *= double_tap_slop_square; const float delta_x = previous_tap.x - current_tap.x; const float delta_y = previous_tap.y - current_tap.y; return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square); } } // namespace content