// 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/motion_event_aura.h" #include "base/logging.h" #include "ui/events/gestures/gesture_configuration.h" namespace ui { MotionEventAura::MotionEventAura() : pointer_count_(0), cached_action_index_(-1) { } MotionEventAura::MotionEventAura( size_t pointer_count, const base::TimeTicks& last_touch_time, Action cached_action, int cached_action_index, const PointData (&active_touches)[GestureSequence::kMaxGesturePoints]) : pointer_count_(pointer_count), last_touch_time_(last_touch_time), cached_action_(cached_action), cached_action_index_(cached_action_index) { DCHECK(pointer_count_); for (size_t i = 0; i < pointer_count; ++i) active_touches_[i] = active_touches[i]; } MotionEventAura::~MotionEventAura() {} MotionEventAura::PointData MotionEventAura::GetPointDataFromTouchEvent( const TouchEvent& touch) { PointData point_data; point_data.x = touch.x(); point_data.y = touch.y(); point_data.raw_x = touch.root_location_f().x(); point_data.raw_y = touch.root_location_f().y(); point_data.touch_id = touch.touch_id(); point_data.pressure = touch.force(); point_data.source_device_id = touch.source_device_id(); // TODO(tdresser): at some point we should start using both radii if they are // available, but for now we use the max. point_data.major_radius = std::max(touch.radius_x(), touch.radius_y()); if (!point_data.major_radius) point_data.major_radius = GestureConfiguration::default_radius(); return point_data; } void MotionEventAura::OnTouch(const TouchEvent& touch) { switch (touch.type()) { case ET_TOUCH_PRESSED: AddTouch(touch); break; case ET_TOUCH_RELEASED: case ET_TOUCH_CANCELLED: // Removing these touch points needs to be postponed until after the // MotionEvent has been dispatched. This cleanup occurs in // CleanupRemovedTouchPoints. UpdateTouch(touch); break; case ET_TOUCH_MOVED: UpdateTouch(touch); break; default: NOTREACHED(); break; } UpdateCachedAction(touch); last_touch_time_ = touch.time_stamp() + base::TimeTicks(); } int MotionEventAura::GetId() const { return GetPointerId(0); } MotionEvent::Action MotionEventAura::GetAction() const { return cached_action_; } int MotionEventAura::GetActionIndex() const { DCHECK(cached_action_ == ACTION_POINTER_DOWN || cached_action_ == ACTION_POINTER_UP); DCHECK_GE(cached_action_index_, 0); DCHECK_LE(cached_action_index_, static_cast<int>(pointer_count_)); return cached_action_index_; } size_t MotionEventAura::GetPointerCount() const { return pointer_count_; } int MotionEventAura::GetPointerId(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].touch_id; } float MotionEventAura::GetX(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].x; } float MotionEventAura::GetY(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].y; } float MotionEventAura::GetRawX(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].raw_x; } float MotionEventAura::GetRawY(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].raw_y; } float MotionEventAura::GetTouchMajor(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].major_radius * 2; } float MotionEventAura::GetPressure(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].pressure; } base::TimeTicks MotionEventAura::GetEventTime() const { return last_touch_time_; } size_t MotionEventAura::GetHistorySize() const { return 0; } base::TimeTicks MotionEventAura::GetHistoricalEventTime( size_t historical_index) const { NOTIMPLEMENTED(); return base::TimeTicks(); } float MotionEventAura::GetHistoricalTouchMajor(size_t pointer_index, size_t historical_index) const { NOTIMPLEMENTED(); return 0; } float MotionEventAura::GetHistoricalX(size_t pointer_index, size_t historical_index) const { NOTIMPLEMENTED(); return 0; } float MotionEventAura::GetHistoricalY(size_t pointer_index, size_t historical_index) const { NOTIMPLEMENTED(); return 0; } MotionEvent::ToolType MotionEventAura::GetToolType(size_t pointer_index) const { NOTIMPLEMENTED(); return MotionEvent::TOOL_TYPE_UNKNOWN; } int MotionEventAura::GetButtonState() const { NOTIMPLEMENTED(); return 0; } scoped_ptr<MotionEvent> MotionEventAura::Clone() const { return scoped_ptr<MotionEvent>(new MotionEventAura(pointer_count_, last_touch_time_, cached_action_, cached_action_index_, active_touches_)); } scoped_ptr<MotionEvent> MotionEventAura::Cancel() const { return scoped_ptr<MotionEvent>(new MotionEventAura( pointer_count_, last_touch_time_, ACTION_CANCEL, -1, active_touches_)); } void MotionEventAura::CleanupRemovedTouchPoints(const TouchEvent& event) { if (event.type() != ET_TOUCH_RELEASED && event.type() != ET_TOUCH_CANCELLED) { return; } int index_to_delete = static_cast<int>(GetIndexFromId(event.touch_id())); pointer_count_--; active_touches_[index_to_delete] = active_touches_[pointer_count_]; } MotionEventAura::PointData::PointData() : x(0), y(0), raw_x(0), raw_y(0), touch_id(0), pressure(0), source_device_id(0), major_radius(0) { } int MotionEventAura::GetSourceDeviceId(size_t pointer_index) const { DCHECK_LE(pointer_index, pointer_count_); return active_touches_[pointer_index].source_device_id; } void MotionEventAura::AddTouch(const TouchEvent& touch) { if (pointer_count_ == static_cast<size_t>(GestureSequence::kMaxGesturePoints)) return; active_touches_[pointer_count_] = GetPointDataFromTouchEvent(touch); pointer_count_++; } void MotionEventAura::UpdateTouch(const TouchEvent& touch) { active_touches_[GetIndexFromId(touch.touch_id())] = GetPointDataFromTouchEvent(touch); } void MotionEventAura::UpdateCachedAction(const TouchEvent& touch) { DCHECK(pointer_count_); switch (touch.type()) { case ET_TOUCH_PRESSED: if (pointer_count_ == 1) { cached_action_ = ACTION_DOWN; } else { cached_action_ = ACTION_POINTER_DOWN; cached_action_index_ = static_cast<int>(GetIndexFromId(touch.touch_id())); } break; case ET_TOUCH_RELEASED: if (pointer_count_ == 1) { cached_action_ = ACTION_UP; } else { cached_action_ = ACTION_POINTER_UP; cached_action_index_ = static_cast<int>(GetIndexFromId(touch.touch_id())); DCHECK_LE(cached_action_index_, static_cast<int>(pointer_count_)); } break; case ET_TOUCH_CANCELLED: cached_action_ = ACTION_CANCEL; break; case ET_TOUCH_MOVED: cached_action_ = ACTION_MOVE; break; default: NOTREACHED(); break; } } size_t MotionEventAura::GetIndexFromId(int id) const { for (size_t i = 0; i < pointer_count_; ++i) { if (active_touches_[i].touch_id == id) return i; } NOTREACHED(); return 0; } } // namespace ui