// 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. // MSVC++ requires this to be set before any other includes to get M_PI. #define _USE_MATH_DEFINES #include "ui/events/gesture_detection/motion_event_generic.h" #include #include "base/logging.h" #include "ui/events/base_event_utils.h" namespace ui { PointerProperties::PointerProperties() : PointerProperties(0, 0, 0) { } PointerProperties::PointerProperties(float x, float y, float touch_major) : id(0), tool_type(MotionEvent::TOOL_TYPE_UNKNOWN), x(x), y(y), raw_x(x), raw_y(y), pressure(0), touch_major(touch_major), touch_minor(0), orientation(0), source_device_id(0) { } PointerProperties::PointerProperties(const MotionEvent& event, size_t pointer_index) : id(event.GetPointerId(pointer_index)), tool_type(event.GetToolType(pointer_index)), x(event.GetX(pointer_index)), y(event.GetY(pointer_index)), raw_x(event.GetRawX(pointer_index)), raw_y(event.GetRawY(pointer_index)), pressure(event.GetPressure(pointer_index)), touch_major(event.GetTouchMajor(pointer_index)), touch_minor(event.GetTouchMinor(pointer_index)), orientation(event.GetOrientation(pointer_index)), source_device_id(0) { } void PointerProperties::SetAxesAndOrientation(float radius_x, float radius_y, float rotation_angle_degree) { DCHECK(!touch_major && !touch_minor && !orientation); float rotation_angle_rad = rotation_angle_degree * M_PI / 180.f; DCHECK_GE(radius_x, 0) << "Unexpected x-radius < 0 (" << radius_x << ")"; DCHECK_GE(radius_y, 0) << "Unexpected y-radius < 0 (" << radius_y << ")"; DCHECK(0 <= rotation_angle_rad && rotation_angle_rad < M_PI) << "Unexpected touch rotation angle " << rotation_angle_rad << " rad"; // Make the angle acute to ease subsequent logic. The angle range effectively // changes from [0, pi) to [0, pi/2). if (rotation_angle_rad >= M_PI_2) { rotation_angle_rad -= static_cast(M_PI_2); std::swap(radius_x, radius_y); } if (radius_x > radius_y) { // The case radius_x == radius_y is omitted from here on purpose: for // circles, we want to pass the angle (which could be any value in such // cases but always seem to be set to zero) unchanged. touch_major = 2.f * radius_x; touch_minor = 2.f * radius_y; orientation = rotation_angle_rad - M_PI_2; } else { touch_major = 2.f * radius_y; touch_minor = 2.f * radius_x; orientation = rotation_angle_rad; } } MotionEventGeneric::MotionEventGeneric(Action action, base::TimeTicks event_time, const PointerProperties& pointer) : action_(action), event_time_(event_time), unique_event_id_(ui::GetNextTouchEventId()), action_index_(0), button_state_(0), flags_(0) { PushPointer(pointer); } MotionEventGeneric::MotionEventGeneric(const MotionEventGeneric& other) : action_(other.action_), event_time_(other.event_time_), unique_event_id_(other.unique_event_id_), action_index_(other.action_index_), button_state_(other.button_state_), flags_(other.flags_), pointers_(other.pointers_) { const size_t history_size = other.GetHistorySize(); for (size_t h = 0; h < history_size; ++h) PushHistoricalEvent(other.historical_events_[h]->Clone()); } MotionEventGeneric::~MotionEventGeneric() { } uint32 MotionEventGeneric::GetUniqueEventId() const { return unique_event_id_; } MotionEvent::Action MotionEventGeneric::GetAction() const { return action_; } int MotionEventGeneric::GetActionIndex() const { DCHECK(action_ == ACTION_POINTER_DOWN || action_ == ACTION_POINTER_UP); DCHECK_GE(action_index_, 0); DCHECK_LT(action_index_, static_cast(pointers_->size())); return action_index_; } size_t MotionEventGeneric::GetPointerCount() const { return pointers_->size(); } int MotionEventGeneric::GetPointerId(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].id; } float MotionEventGeneric::GetX(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].x; } float MotionEventGeneric::GetY(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].y; } float MotionEventGeneric::GetRawX(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].raw_x; } float MotionEventGeneric::GetRawY(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].raw_y; } float MotionEventGeneric::GetTouchMajor(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].touch_major; } float MotionEventGeneric::GetTouchMinor(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].touch_minor; } float MotionEventGeneric::GetOrientation(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].orientation; } float MotionEventGeneric::GetPressure(size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].pressure; } MotionEvent::ToolType MotionEventGeneric::GetToolType( size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); return pointers_[pointer_index].tool_type; } int MotionEventGeneric::GetButtonState() const { return button_state_; } int MotionEventGeneric::GetFlags() const { return flags_; } base::TimeTicks MotionEventGeneric::GetEventTime() const { return event_time_; } size_t MotionEventGeneric::GetHistorySize() const { return historical_events_.size(); } base::TimeTicks MotionEventGeneric::GetHistoricalEventTime( size_t historical_index) const { DCHECK_LT(historical_index, historical_events_.size()); return historical_events_[historical_index]->GetEventTime(); } float MotionEventGeneric::GetHistoricalTouchMajor( size_t pointer_index, size_t historical_index) const { DCHECK_LT(historical_index, historical_events_.size()); return historical_events_[historical_index]->GetTouchMajor(pointer_index); } float MotionEventGeneric::GetHistoricalX(size_t pointer_index, size_t historical_index) const { DCHECK_LT(historical_index, historical_events_.size()); return historical_events_[historical_index]->GetX(pointer_index); } float MotionEventGeneric::GetHistoricalY(size_t pointer_index, size_t historical_index) const { DCHECK_LT(historical_index, historical_events_.size()); return historical_events_[historical_index]->GetY(pointer_index); } // static scoped_ptr MotionEventGeneric::CloneEvent( const MotionEvent& event) { bool with_history = true; return make_scoped_ptr(new MotionEventGeneric(event, with_history)); } // static scoped_ptr MotionEventGeneric::CancelEvent( const MotionEvent& event) { bool with_history = false; scoped_ptr cancel_event( new MotionEventGeneric(event, with_history)); cancel_event->set_action(ACTION_CANCEL); cancel_event->set_unique_event_id(ui::GetNextTouchEventId()); return cancel_event.Pass(); } size_t MotionEventGeneric::PushPointer(const PointerProperties& pointer) { DCHECK_EQ(0U, GetHistorySize()); pointers_->push_back(pointer); return pointers_->size() - 1; } void MotionEventGeneric::RemovePointerAt(size_t index) { DCHECK_LT(index, pointers_->size()); pointers_->erase(pointers_->begin() + index); } void MotionEventGeneric::PushHistoricalEvent(scoped_ptr event) { DCHECK(event); DCHECK_EQ(event->GetAction(), ACTION_MOVE); DCHECK_EQ(event->GetPointerCount(), GetPointerCount()); DCHECK_EQ(event->GetAction(), GetAction()); DCHECK_LE(event->GetEventTime().ToInternalValue(), GetEventTime().ToInternalValue()); historical_events_.push_back(event.Pass()); } MotionEventGeneric::MotionEventGeneric() : action_(ACTION_CANCEL), unique_event_id_(ui::GetNextTouchEventId()), action_index_(0), button_state_(0) { } MotionEventGeneric::MotionEventGeneric(const MotionEvent& event, bool with_history) : action_(event.GetAction()), event_time_(event.GetEventTime()), unique_event_id_(event.GetUniqueEventId()), action_index_( (action_ == ACTION_POINTER_UP || action_ == ACTION_POINTER_DOWN) ? event.GetActionIndex() : 0), button_state_(event.GetButtonState()), flags_(event.GetFlags()) { const size_t pointer_count = event.GetPointerCount(); for (size_t i = 0; i < pointer_count; ++i) PushPointer(PointerProperties(event, i)); if (!with_history) return; const size_t history_size = event.GetHistorySize(); for (size_t h = 0; h < history_size; ++h) { scoped_ptr historical_event(new MotionEventGeneric()); historical_event->set_action(ACTION_MOVE); historical_event->set_event_time(event.GetHistoricalEventTime(h)); for (size_t i = 0; i < pointer_count; ++i) { historical_event->PushPointer( PointerProperties(event.GetHistoricalX(i, h), event.GetHistoricalY(i, h), event.GetHistoricalTouchMajor(i, h))); } PushHistoricalEvent(historical_event.Pass()); } } MotionEventGeneric& MotionEventGeneric::operator=( const MotionEventGeneric& other) { action_ = other.action_; event_time_ = other.event_time_; unique_event_id_ = other.unique_event_id_; action_index_ = other.action_index_; button_state_ = other.button_state_; flags_ = other.flags_; pointers_ = other.pointers_; const size_t history_size = other.GetHistorySize(); for (size_t h = 0; h < history_size; ++h) PushHistoricalEvent(other.historical_events_[h]->Clone()); return *this; } void MotionEventGeneric::PopPointer() { DCHECK_GT(pointers_->size(), 0U); pointers_->pop_back(); } } // namespace ui