Home | History | Annotate | Download | only in gestures
      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 // MSVC++ requires this to be set before any other includes to get M_PI.
      6 #define _USE_MATH_DEFINES
      7 
      8 #include "ui/events/gestures/motion_event_aura.h"
      9 
     10 #include <cmath>
     11 
     12 #include "base/logging.h"
     13 #include "ui/events/gestures/gesture_configuration.h"
     14 
     15 namespace ui {
     16 
     17 MotionEventAura::MotionEventAura()
     18     : pointer_count_(0), cached_action_index_(-1) {
     19 }
     20 
     21 MotionEventAura::MotionEventAura(
     22     size_t pointer_count,
     23     const base::TimeTicks& last_touch_time,
     24     Action cached_action,
     25     int cached_action_index,
     26     int flags,
     27     const PointData (&active_touches)[MotionEvent::MAX_TOUCH_POINT_COUNT])
     28     : pointer_count_(pointer_count),
     29       last_touch_time_(last_touch_time),
     30       cached_action_(cached_action),
     31       cached_action_index_(cached_action_index),
     32       flags_(flags) {
     33   DCHECK(pointer_count_);
     34   for (size_t i = 0; i < pointer_count; ++i)
     35     active_touches_[i] = active_touches[i];
     36 }
     37 
     38 MotionEventAura::~MotionEventAura() {}
     39 
     40 MotionEventAura::PointData MotionEventAura::GetPointDataFromTouchEvent(
     41     const TouchEvent& touch) {
     42   PointData point_data;
     43   point_data.x = touch.x();
     44   point_data.y = touch.y();
     45   point_data.raw_x = touch.root_location_f().x();
     46   point_data.raw_y = touch.root_location_f().y();
     47   point_data.touch_id = touch.touch_id();
     48   point_data.pressure = touch.force();
     49   point_data.source_device_id = touch.source_device_id();
     50 
     51   float radius_x = touch.radius_x();
     52   float radius_y = touch.radius_y();
     53   float rotation_angle_rad = touch.rotation_angle() * M_PI / 180.f;
     54   DCHECK_GE(radius_x, 0) << "Unexpected x-radius < 0";
     55   DCHECK_GE(radius_y, 0) << "Unexpected y-radius < 0";
     56   DCHECK(0 <= rotation_angle_rad && rotation_angle_rad <= M_PI_2)
     57       << "Unexpected touch rotation angle";
     58 
     59   if (radius_x > radius_y) {
     60     // The case radius_x == radius_y is omitted from here on purpose: for
     61     // circles, we want to pass the angle (which could be any value in such
     62     // cases but always seem to be set to zero) unchanged.
     63     point_data.touch_major = 2.f * radius_x;
     64     point_data.touch_minor = 2.f * radius_y;
     65     point_data.orientation = rotation_angle_rad - M_PI_2;
     66   } else {
     67     point_data.touch_major = 2.f * radius_y;
     68     point_data.touch_minor = 2.f * radius_x;
     69     point_data.orientation = rotation_angle_rad;
     70   }
     71 
     72   if (!point_data.touch_major) {
     73     point_data.touch_major = 2.f * GestureConfiguration::default_radius();
     74     point_data.touch_minor = 2.f * GestureConfiguration::default_radius();
     75     point_data.orientation = 0;
     76   }
     77 
     78   return point_data;
     79 }
     80 
     81 void MotionEventAura::OnTouch(const TouchEvent& touch) {
     82   switch (touch.type()) {
     83     case ET_TOUCH_PRESSED:
     84       AddTouch(touch);
     85       break;
     86     case ET_TOUCH_RELEASED:
     87     case ET_TOUCH_CANCELLED:
     88       // Removing these touch points needs to be postponed until after the
     89       // MotionEvent has been dispatched. This cleanup occurs in
     90       // CleanupRemovedTouchPoints.
     91       UpdateTouch(touch);
     92       break;
     93     case ET_TOUCH_MOVED:
     94       UpdateTouch(touch);
     95       break;
     96     default:
     97       NOTREACHED();
     98       break;
     99   }
    100 
    101   UpdateCachedAction(touch);
    102   flags_ = touch.flags();
    103   last_touch_time_ = touch.time_stamp() + base::TimeTicks();
    104 }
    105 
    106 int MotionEventAura::GetId() const {
    107   return GetPointerId(0);
    108 }
    109 
    110 MotionEvent::Action MotionEventAura::GetAction() const {
    111   return cached_action_;
    112 }
    113 
    114 int MotionEventAura::GetActionIndex() const {
    115   DCHECK(cached_action_ == ACTION_POINTER_DOWN ||
    116          cached_action_ == ACTION_POINTER_UP);
    117   DCHECK_GE(cached_action_index_, 0);
    118   DCHECK_LT(cached_action_index_, static_cast<int>(pointer_count_));
    119   return cached_action_index_;
    120 }
    121 
    122 size_t MotionEventAura::GetPointerCount() const { return pointer_count_; }
    123 
    124 int MotionEventAura::GetPointerId(size_t pointer_index) const {
    125   DCHECK_LT(pointer_index, pointer_count_);
    126   return active_touches_[pointer_index].touch_id;
    127 }
    128 
    129 float MotionEventAura::GetX(size_t pointer_index) const {
    130   DCHECK_LT(pointer_index, pointer_count_);
    131   return active_touches_[pointer_index].x;
    132 }
    133 
    134 float MotionEventAura::GetY(size_t pointer_index) const {
    135   DCHECK_LT(pointer_index, pointer_count_);
    136   return active_touches_[pointer_index].y;
    137 }
    138 
    139 float MotionEventAura::GetRawX(size_t pointer_index) const {
    140   DCHECK_LT(pointer_index, pointer_count_);
    141   return active_touches_[pointer_index].raw_x;
    142 }
    143 
    144 float MotionEventAura::GetRawY(size_t pointer_index) const {
    145   DCHECK_LT(pointer_index, pointer_count_);
    146   return active_touches_[pointer_index].raw_y;
    147 }
    148 
    149 float MotionEventAura::GetTouchMajor(size_t pointer_index) const {
    150   DCHECK_LT(pointer_index, pointer_count_);
    151   return active_touches_[pointer_index].touch_major;
    152 }
    153 
    154 float MotionEventAura::GetTouchMinor(size_t pointer_index) const {
    155   DCHECK_LE(pointer_index, pointer_count_);
    156   return active_touches_[pointer_index].touch_minor;
    157 }
    158 
    159 float MotionEventAura::GetOrientation(size_t pointer_index) const {
    160   DCHECK_LE(pointer_index, pointer_count_);
    161   return active_touches_[pointer_index].orientation;
    162 }
    163 
    164 float MotionEventAura::GetPressure(size_t pointer_index) const {
    165   DCHECK_LT(pointer_index, pointer_count_);
    166   return active_touches_[pointer_index].pressure;
    167 }
    168 
    169 MotionEvent::ToolType MotionEventAura::GetToolType(size_t pointer_index) const {
    170   // TODO(jdduke): Plumb tool type from the platform, crbug.com/404128.
    171   DCHECK_LT(pointer_index, pointer_count_);
    172   return MotionEvent::TOOL_TYPE_UNKNOWN;
    173 }
    174 
    175 int MotionEventAura::GetButtonState() const {
    176   NOTIMPLEMENTED();
    177   return 0;
    178 }
    179 
    180 int MotionEventAura::GetFlags() const {
    181   return flags_;
    182 }
    183 
    184 base::TimeTicks MotionEventAura::GetEventTime() const {
    185   return last_touch_time_;
    186 }
    187 
    188 scoped_ptr<MotionEvent> MotionEventAura::Clone() const {
    189   return scoped_ptr<MotionEvent>(new MotionEventAura(pointer_count_,
    190                                                      last_touch_time_,
    191                                                      cached_action_,
    192                                                      cached_action_index_,
    193                                                      flags_,
    194                                                      active_touches_));
    195 }
    196 scoped_ptr<MotionEvent> MotionEventAura::Cancel() const {
    197   return scoped_ptr<MotionEvent>(new MotionEventAura(
    198       pointer_count_, last_touch_time_, ACTION_CANCEL, -1, 0, active_touches_));
    199 }
    200 
    201 void MotionEventAura::CleanupRemovedTouchPoints(const TouchEvent& event) {
    202   if (event.type() != ET_TOUCH_RELEASED &&
    203       event.type() != ET_TOUCH_CANCELLED) {
    204     return;
    205   }
    206 
    207   int index_to_delete = static_cast<int>(GetIndexFromId(event.touch_id()));
    208   pointer_count_--;
    209   active_touches_[index_to_delete] = active_touches_[pointer_count_];
    210 }
    211 
    212 MotionEventAura::PointData::PointData()
    213     : x(0),
    214       y(0),
    215       raw_x(0),
    216       raw_y(0),
    217       touch_id(0),
    218       pressure(0),
    219       source_device_id(0),
    220       touch_major(0),
    221       touch_minor(0),
    222       orientation(0) {
    223 }
    224 
    225 int MotionEventAura::GetSourceDeviceId(size_t pointer_index) const {
    226   DCHECK_LT(pointer_index, pointer_count_);
    227   return active_touches_[pointer_index].source_device_id;
    228 }
    229 
    230 void MotionEventAura::AddTouch(const TouchEvent& touch) {
    231   if (pointer_count_ == MotionEvent::MAX_TOUCH_POINT_COUNT)
    232     return;
    233 
    234   active_touches_[pointer_count_] = GetPointDataFromTouchEvent(touch);
    235   pointer_count_++;
    236 }
    237 
    238 
    239 void MotionEventAura::UpdateTouch(const TouchEvent& touch) {
    240   active_touches_[GetIndexFromId(touch.touch_id())] =
    241       GetPointDataFromTouchEvent(touch);
    242 }
    243 
    244 void MotionEventAura::UpdateCachedAction(const TouchEvent& touch) {
    245   DCHECK(pointer_count_);
    246   switch (touch.type()) {
    247     case ET_TOUCH_PRESSED:
    248       if (pointer_count_ == 1) {
    249         cached_action_ = ACTION_DOWN;
    250       } else {
    251         cached_action_ = ACTION_POINTER_DOWN;
    252         cached_action_index_ =
    253             static_cast<int>(GetIndexFromId(touch.touch_id()));
    254       }
    255       break;
    256     case ET_TOUCH_RELEASED:
    257       if (pointer_count_ == 1) {
    258         cached_action_ = ACTION_UP;
    259       } else {
    260         cached_action_ = ACTION_POINTER_UP;
    261         cached_action_index_ =
    262             static_cast<int>(GetIndexFromId(touch.touch_id()));
    263         DCHECK_LT(cached_action_index_, static_cast<int>(pointer_count_));
    264       }
    265       break;
    266     case ET_TOUCH_CANCELLED:
    267       cached_action_ = ACTION_CANCEL;
    268       break;
    269     case ET_TOUCH_MOVED:
    270       cached_action_ = ACTION_MOVE;
    271       break;
    272     default:
    273       NOTREACHED();
    274       break;
    275   }
    276 }
    277 
    278 size_t MotionEventAura::GetIndexFromId(int id) const {
    279   for (size_t i = 0; i < pointer_count_; ++i) {
    280     if (active_touches_[i].touch_id == id)
    281       return i;
    282   }
    283   NOTREACHED();
    284   return 0;
    285 }
    286 
    287 }  // namespace ui
    288