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