| // 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/gesture_detection/motion_event_generic.h" |
| |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/numerics/math_constants.h" |
| #include "ui/events/base_event_utils.h" |
| #include "ui/gfx/geometry/angle_conversions.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), |
| tilt_x(0), |
| tilt_y(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)), |
| tilt_x(event.GetTiltX(pointer_index)), |
| tilt_y(event.GetTiltY(pointer_index)), |
| source_device_id(0) {} |
| |
| PointerProperties::PointerProperties(const PointerProperties& other) = default; |
| |
| void PointerProperties::SetAxesAndOrientation(float radius_x, |
| float radius_y, |
| float rotation_angle_degree) { |
| DCHECK(!touch_major && !touch_minor && !orientation); |
| float rotation_angle_rad = gfx::DegToRad(rotation_angle_degree); |
| 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 < base::kPiFloat) |
| << "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 >= base::kPiFloat / 2) { |
| rotation_angle_rad -= base::kPiFloat / 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 - base::kPiFloat / 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_t 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<int>(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; |
| } |
| |
| float MotionEventGeneric::GetTiltX(size_t pointer_index) const { |
| DCHECK_LT(pointer_index, pointers_->size()); |
| return pointers_[pointer_index].tilt_x; |
| } |
| |
| float MotionEventGeneric::GetTiltY(size_t pointer_index) const { |
| DCHECK_LT(pointer_index, pointers_->size()); |
| return pointers_[pointer_index].tilt_y; |
| } |
| |
| 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 |
| std::unique_ptr<MotionEventGeneric> MotionEventGeneric::CloneEvent( |
| const MotionEvent& event) { |
| bool with_history = true; |
| return base::WrapUnique(new MotionEventGeneric(event, with_history)); |
| } |
| |
| // static |
| std::unique_ptr<MotionEventGeneric> MotionEventGeneric::CancelEvent( |
| const MotionEvent& event) { |
| bool with_history = false; |
| std::unique_ptr<MotionEventGeneric> cancel_event( |
| new MotionEventGeneric(event, with_history)); |
| cancel_event->set_action(ACTION_CANCEL); |
| cancel_event->set_unique_event_id(ui::GetNextTouchEventId()); |
| return cancel_event; |
| } |
| |
| 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( |
| std::unique_ptr<MotionEvent> event) { |
| DCHECK(event); |
| DCHECK_EQ(event->GetAction(), ACTION_MOVE); |
| DCHECK_EQ(event->GetPointerCount(), GetPointerCount()); |
| DCHECK_EQ(event->GetAction(), GetAction()); |
| DCHECK_LE(event->GetEventTime(), GetEventTime()); |
| historical_events_.push_back(std::move(event)); |
| } |
| |
| MotionEventGeneric::MotionEventGeneric() |
| : action_(ACTION_NONE), |
| unique_event_id_(ui::GetNextTouchEventId()), |
| action_index_(-1), |
| 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) { |
| std::unique_ptr<MotionEventGeneric> 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(std::move(historical_event)); |
| } |
| } |
| |
| 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 |