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 <cmath> 9 10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "ui/events/event.h" 12 #include "ui/events/gestures/motion_event_aura.h" 13 14 namespace { 15 16 ui::TouchEvent TouchWithType(ui::EventType type, int id) { 17 return ui::TouchEvent( 18 type, gfx::PointF(0, 0), id, base::TimeDelta::FromMilliseconds(0)); 19 } 20 21 ui::TouchEvent TouchWithPosition(ui::EventType type, 22 int id, 23 float x, 24 float y, 25 float raw_x, 26 float raw_y) { 27 ui::TouchEvent event(type, 28 gfx::PointF(x, y), 29 0, 30 id, 31 base::TimeDelta::FromMilliseconds(0), 32 0, 33 0, 34 0, 35 0); 36 event.set_root_location(gfx::PointF(raw_x, raw_y)); 37 return event; 38 } 39 40 ui::TouchEvent TouchWithTapParams(ui::EventType type, 41 int id, 42 float radius_x, 43 float radius_y, 44 float rotation_angle, 45 float pressure) { 46 ui::TouchEvent event(type, 47 gfx::PointF(1, 1), 48 0, 49 id, 50 base::TimeDelta::FromMilliseconds(0), 51 radius_x, 52 radius_y, 53 rotation_angle, 54 pressure); 55 event.set_root_location(gfx::PointF(1, 1)); 56 return event; 57 } 58 59 ui::TouchEvent TouchWithTime(ui::EventType type, int id, int ms) { 60 return ui::TouchEvent( 61 type, gfx::PointF(0, 0), id, base::TimeDelta::FromMilliseconds(ms)); 62 } 63 64 base::TimeTicks MsToTicks(int ms) { 65 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(ms); 66 } 67 68 } // namespace 69 70 namespace ui { 71 72 TEST(MotionEventAuraTest, PointerCountAndIds) { 73 // Test that |PointerCount()| returns the correct number of pointers, and ids 74 // are assigned correctly. 75 int ids[] = {4, 6, 1}; 76 77 MotionEventAura event; 78 EXPECT_EQ(0U, event.GetPointerCount()); 79 80 TouchEvent press0 = TouchWithType(ET_TOUCH_PRESSED, ids[0]); 81 event.OnTouch(press0); 82 EXPECT_EQ(1U, event.GetPointerCount()); 83 84 EXPECT_EQ(ids[0], event.GetPointerId(0)); 85 86 TouchEvent press1 = TouchWithType(ET_TOUCH_PRESSED, ids[1]); 87 event.OnTouch(press1); 88 EXPECT_EQ(2U, event.GetPointerCount()); 89 90 EXPECT_EQ(ids[0], event.GetPointerId(0)); 91 EXPECT_EQ(ids[1], event.GetPointerId(1)); 92 93 TouchEvent press2 = TouchWithType(ET_TOUCH_PRESSED, ids[2]); 94 event.OnTouch(press2); 95 EXPECT_EQ(3U, event.GetPointerCount()); 96 97 EXPECT_EQ(ids[0], event.GetPointerId(0)); 98 EXPECT_EQ(ids[1], event.GetPointerId(1)); 99 EXPECT_EQ(ids[2], event.GetPointerId(2)); 100 101 TouchEvent release1 = TouchWithType(ET_TOUCH_RELEASED, ids[1]); 102 event.OnTouch(release1); 103 event.CleanupRemovedTouchPoints(release1); 104 EXPECT_EQ(2U, event.GetPointerCount()); 105 106 EXPECT_EQ(ids[0], event.GetPointerId(0)); 107 EXPECT_EQ(ids[2], event.GetPointerId(1)); 108 109 // Test cloning of pointer count and id information. 110 // TODO(mustaq): Make a separate clone test 111 scoped_ptr<MotionEvent> clone = event.Clone(); 112 EXPECT_EQ(2U, clone->GetPointerCount()); 113 EXPECT_EQ(ids[0], clone->GetPointerId(0)); 114 EXPECT_EQ(ids[2], clone->GetPointerId(1)); 115 116 TouchEvent release0 = TouchWithType(ET_TOUCH_RELEASED, ids[0]); 117 event.OnTouch(release0); 118 event.CleanupRemovedTouchPoints(release0); 119 EXPECT_EQ(1U, event.GetPointerCount()); 120 121 EXPECT_EQ(ids[2], event.GetPointerId(0)); 122 123 TouchEvent release2 = TouchWithType(ET_TOUCH_RELEASED, ids[2]); 124 event.OnTouch(release2); 125 event.CleanupRemovedTouchPoints(release2); 126 EXPECT_EQ(0U, event.GetPointerCount()); 127 } 128 129 TEST(MotionEventAuraTest, GetActionIndexAfterRemoval) { 130 // Test that |GetActionIndex()| returns the correct index when points have 131 // been removed. 132 int ids[] = {4, 6, 9}; 133 134 MotionEventAura event; 135 EXPECT_EQ(0U, event.GetPointerCount()); 136 137 TouchEvent press0 = TouchWithType(ET_TOUCH_PRESSED, ids[0]); 138 event.OnTouch(press0); 139 TouchEvent press1 = TouchWithType(ET_TOUCH_PRESSED, ids[1]); 140 event.OnTouch(press1); 141 TouchEvent press2 = TouchWithType(ET_TOUCH_PRESSED, ids[2]); 142 event.OnTouch(press2); 143 EXPECT_EQ(3U, event.GetPointerCount()); 144 145 TouchEvent release1 = TouchWithType(ET_TOUCH_RELEASED, ids[1]); 146 event.OnTouch(release1); 147 event.CleanupRemovedTouchPoints(release1); 148 EXPECT_EQ(1, event.GetActionIndex()); 149 EXPECT_EQ(2U, event.GetPointerCount()); 150 151 TouchEvent release2 = TouchWithType(ET_TOUCH_RELEASED, ids[0]); 152 event.OnTouch(release2); 153 event.CleanupRemovedTouchPoints(release2); 154 EXPECT_EQ(0, event.GetActionIndex()); 155 EXPECT_EQ(1U, event.GetPointerCount()); 156 157 TouchEvent release0 = TouchWithType(ET_TOUCH_RELEASED, ids[2]); 158 event.OnTouch(release0); 159 event.CleanupRemovedTouchPoints(release0); 160 EXPECT_EQ(0U, event.GetPointerCount()); 161 } 162 163 TEST(MotionEventAuraTest, PointerLocations) { 164 // Test that location information is stored correctly. 165 MotionEventAura event; 166 167 const float kRawOffsetX = 11.1f; 168 const float kRawOffsetY = 13.3f; 169 170 int ids[] = {15, 13}; 171 float x; 172 float y; 173 float raw_x; 174 float raw_y; 175 176 x = 14.4f; 177 y = 17.3f; 178 raw_x = x + kRawOffsetX; 179 raw_y = y + kRawOffsetY; 180 TouchEvent press0 = 181 TouchWithPosition(ET_TOUCH_PRESSED, ids[0], x, y, raw_x, raw_y); 182 event.OnTouch(press0); 183 184 EXPECT_EQ(1U, event.GetPointerCount()); 185 EXPECT_FLOAT_EQ(x, event.GetX(0)); 186 EXPECT_FLOAT_EQ(y, event.GetY(0)); 187 EXPECT_FLOAT_EQ(raw_x, event.GetRawX(0)); 188 EXPECT_FLOAT_EQ(raw_y, event.GetRawY(0)); 189 190 x = 17.8f; 191 y = 12.1f; 192 raw_x = x + kRawOffsetX; 193 raw_y = y + kRawOffsetY; 194 TouchEvent press1 = 195 TouchWithPosition(ET_TOUCH_PRESSED, ids[1], x, y, raw_x, raw_y); 196 event.OnTouch(press1); 197 198 EXPECT_EQ(2U, event.GetPointerCount()); 199 EXPECT_FLOAT_EQ(x, event.GetX(1)); 200 EXPECT_FLOAT_EQ(y, event.GetY(1)); 201 EXPECT_FLOAT_EQ(raw_x, event.GetRawX(1)); 202 EXPECT_FLOAT_EQ(raw_y, event.GetRawY(1)); 203 204 // Test cloning of pointer location information. 205 scoped_ptr<MotionEvent> clone = event.Clone(); 206 { 207 const MotionEventAura* raw_clone_aura = 208 static_cast<MotionEventAura*>(clone.get()); 209 EXPECT_EQ(2U, raw_clone_aura->GetPointerCount()); 210 EXPECT_FLOAT_EQ(x, raw_clone_aura->GetX(1)); 211 EXPECT_FLOAT_EQ(y, raw_clone_aura->GetY(1)); 212 EXPECT_FLOAT_EQ(raw_x, raw_clone_aura->GetRawX(1)); 213 EXPECT_FLOAT_EQ(raw_y, raw_clone_aura->GetRawY(1)); 214 } 215 216 x = 27.9f; 217 y = 22.3f; 218 raw_x = x + kRawOffsetX; 219 raw_y = y + kRawOffsetY; 220 TouchEvent move1 = 221 TouchWithPosition(ET_TOUCH_MOVED, ids[1], x, y, raw_x, raw_y); 222 event.OnTouch(move1); 223 224 EXPECT_FLOAT_EQ(x, event.GetX(1)); 225 EXPECT_FLOAT_EQ(y, event.GetY(1)); 226 EXPECT_FLOAT_EQ(raw_x, event.GetRawX(1)); 227 EXPECT_FLOAT_EQ(raw_y, event.GetRawY(1)); 228 229 x = 34.6f; 230 y = 23.8f; 231 raw_x = x + kRawOffsetX; 232 raw_y = y + kRawOffsetY; 233 TouchEvent move0 = 234 TouchWithPosition(ET_TOUCH_MOVED, ids[0], x, y, raw_x, raw_y); 235 event.OnTouch(move0); 236 237 EXPECT_FLOAT_EQ(x, event.GetX(0)); 238 EXPECT_FLOAT_EQ(y, event.GetY(0)); 239 EXPECT_FLOAT_EQ(raw_x, event.GetRawX(0)); 240 EXPECT_FLOAT_EQ(raw_y, event.GetRawY(0)); 241 } 242 243 TEST(MotionEventAuraTest, TapParams) { 244 // Test that touch params are stored correctly. 245 MotionEventAura event; 246 247 int ids[] = {15, 13}; 248 249 float radius_x; 250 float radius_y; 251 float rotation_angle; 252 float pressure; 253 254 radius_x = 123.45f; 255 radius_y = 67.89f; 256 rotation_angle = 23.f; 257 pressure = 0.123f; 258 TouchEvent press0 = TouchWithTapParams( 259 ET_TOUCH_PRESSED, ids[0], radius_x, radius_y, rotation_angle, pressure); 260 event.OnTouch(press0); 261 262 EXPECT_EQ(1U, event.GetPointerCount()); 263 EXPECT_FLOAT_EQ(radius_x, event.GetTouchMajor(0) / 2); 264 EXPECT_FLOAT_EQ(radius_y, event.GetTouchMinor(0) / 2); 265 EXPECT_FLOAT_EQ(rotation_angle, event.GetOrientation(0) * 180 / M_PI + 90); 266 EXPECT_FLOAT_EQ(pressure, event.GetPressure(0)); 267 268 radius_x = 67.89f; 269 radius_y = 123.45f; 270 rotation_angle = 46.f; 271 pressure = 0.456f; 272 TouchEvent press1 = TouchWithTapParams( 273 ET_TOUCH_PRESSED, ids[1], radius_x, radius_y, rotation_angle, pressure); 274 event.OnTouch(press1); 275 276 EXPECT_EQ(2U, event.GetPointerCount()); 277 EXPECT_FLOAT_EQ(radius_y, event.GetTouchMajor(1) / 2); 278 EXPECT_FLOAT_EQ(radius_x, event.GetTouchMinor(1) / 2); 279 EXPECT_FLOAT_EQ(rotation_angle, event.GetOrientation(1) * 180 / M_PI); 280 EXPECT_FLOAT_EQ(pressure, event.GetPressure(1)); 281 282 // Test cloning of tap params 283 scoped_ptr<MotionEvent> clone = event.Clone(); 284 { 285 const MotionEventAura* raw_clone_aura = 286 static_cast<MotionEventAura*>(clone.get()); 287 EXPECT_EQ(2U, raw_clone_aura->GetPointerCount()); 288 EXPECT_FLOAT_EQ(radius_y, raw_clone_aura->GetTouchMajor(1) / 2); 289 EXPECT_FLOAT_EQ(radius_x, raw_clone_aura->GetTouchMinor(1) / 2); 290 EXPECT_FLOAT_EQ( 291 rotation_angle, raw_clone_aura->GetOrientation(1) * 180 / M_PI); 292 EXPECT_FLOAT_EQ(pressure, raw_clone_aura->GetPressure(1)); 293 } 294 295 radius_x = 76.98f; 296 radius_y = 321.54f; 297 rotation_angle = 64.f; 298 pressure = 0.654f; 299 TouchEvent move1 = TouchWithTapParams( 300 ET_TOUCH_MOVED, ids[1], radius_x, radius_y, rotation_angle, pressure); 301 event.OnTouch(move1); 302 303 EXPECT_EQ(2U, event.GetPointerCount()); 304 EXPECT_FLOAT_EQ(radius_y, event.GetTouchMajor(1) / 2); 305 EXPECT_FLOAT_EQ(radius_x, event.GetTouchMinor(1) / 2); 306 EXPECT_FLOAT_EQ(rotation_angle, event.GetOrientation(1) * 180 / M_PI); 307 EXPECT_FLOAT_EQ(pressure, event.GetPressure(1)); 308 } 309 310 TEST(MotionEventAuraTest, Timestamps) { 311 // Test that timestamp information is stored and converted correctly. 312 MotionEventAura event; 313 int ids[] = {7, 13}; 314 int times_in_ms[] = {59436, 60263, 82175}; 315 316 TouchEvent press0 = TouchWithTime( 317 ui::ET_TOUCH_PRESSED, ids[0], times_in_ms[0]); 318 event.OnTouch(press0); 319 EXPECT_EQ(MsToTicks(times_in_ms[0]), event.GetEventTime()); 320 321 TouchEvent press1 = TouchWithTime( 322 ui::ET_TOUCH_PRESSED, ids[1], times_in_ms[1]); 323 event.OnTouch(press1); 324 EXPECT_EQ(MsToTicks(times_in_ms[1]), event.GetEventTime()); 325 326 TouchEvent move0 = TouchWithTime( 327 ui::ET_TOUCH_MOVED, ids[0], times_in_ms[2]); 328 event.OnTouch(move0); 329 EXPECT_EQ(MsToTicks(times_in_ms[2]), event.GetEventTime()); 330 331 // Test cloning of timestamp information. 332 scoped_ptr<MotionEvent> clone = event.Clone(); 333 EXPECT_EQ(MsToTicks(times_in_ms[2]), clone->GetEventTime()); 334 } 335 336 TEST(MotionEventAuraTest, CachedAction) { 337 // Test that the cached action and cached action index are correct. 338 int ids[] = {4, 6}; 339 MotionEventAura event; 340 341 TouchEvent press0 = TouchWithType(ET_TOUCH_PRESSED, ids[0]); 342 event.OnTouch(press0); 343 EXPECT_EQ(MotionEvent::ACTION_DOWN, event.GetAction()); 344 EXPECT_EQ(1U, event.GetPointerCount()); 345 346 TouchEvent press1 = TouchWithType(ET_TOUCH_PRESSED, ids[1]); 347 event.OnTouch(press1); 348 EXPECT_EQ(MotionEvent::ACTION_POINTER_DOWN, event.GetAction()); 349 EXPECT_EQ(1, event.GetActionIndex()); 350 EXPECT_EQ(2U, event.GetPointerCount()); 351 352 // Test cloning of CachedAction information. 353 scoped_ptr<MotionEvent> clone = event.Clone(); 354 EXPECT_EQ(MotionEvent::ACTION_POINTER_DOWN, clone->GetAction()); 355 EXPECT_EQ(1, clone->GetActionIndex()); 356 357 TouchEvent move0 = TouchWithType(ET_TOUCH_MOVED, ids[0]); 358 event.OnTouch(move0); 359 EXPECT_EQ(MotionEvent::ACTION_MOVE, event.GetAction()); 360 EXPECT_EQ(2U, event.GetPointerCount()); 361 362 TouchEvent release0 = TouchWithType(ET_TOUCH_RELEASED, ids[0]); 363 event.OnTouch(release0); 364 EXPECT_EQ(MotionEvent::ACTION_POINTER_UP, event.GetAction()); 365 EXPECT_EQ(2U, event.GetPointerCount()); 366 event.CleanupRemovedTouchPoints(release0); 367 EXPECT_EQ(1U, event.GetPointerCount()); 368 369 TouchEvent release1 = TouchWithType(ET_TOUCH_RELEASED, ids[1]); 370 event.OnTouch(release1); 371 EXPECT_EQ(MotionEvent::ACTION_UP, event.GetAction()); 372 EXPECT_EQ(1U, event.GetPointerCount()); 373 event.CleanupRemovedTouchPoints(release1); 374 EXPECT_EQ(0U, event.GetPointerCount()); 375 } 376 377 TEST(MotionEventAuraTest, Cancel) { 378 int ids[] = {4, 6}; 379 MotionEventAura event; 380 381 TouchEvent press0 = TouchWithType(ET_TOUCH_PRESSED, ids[0]); 382 event.OnTouch(press0); 383 EXPECT_EQ(MotionEvent::ACTION_DOWN, event.GetAction()); 384 EXPECT_EQ(1U, event.GetPointerCount()); 385 386 TouchEvent press1 = TouchWithType(ET_TOUCH_PRESSED, ids[1]); 387 event.OnTouch(press1); 388 EXPECT_EQ(MotionEvent::ACTION_POINTER_DOWN, event.GetAction()); 389 EXPECT_EQ(1, event.GetActionIndex()); 390 EXPECT_EQ(2U, event.GetPointerCount()); 391 392 scoped_ptr<MotionEvent> cancel = event.Cancel(); 393 EXPECT_EQ(MotionEvent::ACTION_CANCEL, cancel->GetAction()); 394 EXPECT_EQ(2U, static_cast<MotionEventAura*>(cancel.get())->GetPointerCount()); 395 } 396 397 TEST(MotionEventAuraTest, ToolType) { 398 MotionEventAura event; 399 400 // For now, all pointers have an unknown tool type. 401 // TODO(jdduke): Expand this test when ui::TouchEvent identifies the source 402 // touch type, crbug.com/404128. 403 event.OnTouch(TouchWithType(ET_TOUCH_PRESSED, 7)); 404 ASSERT_EQ(1U, event.GetPointerCount()); 405 EXPECT_EQ(MotionEvent::TOOL_TYPE_UNKNOWN, event.GetToolType(0)); 406 } 407 408 TEST(MotionEventAuraTest, Flags) { 409 int ids[] = {7, 11}; 410 MotionEventAura event; 411 412 TouchEvent press0 = TouchWithType(ET_TOUCH_PRESSED, ids[0]); 413 press0.set_flags(EF_CONTROL_DOWN); 414 event.OnTouch(press0); 415 EXPECT_EQ(EF_CONTROL_DOWN, event.GetFlags()); 416 417 TouchEvent press1 = TouchWithType(ET_TOUCH_PRESSED, ids[1]); 418 press1.set_flags(EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN); 419 event.OnTouch(press1); 420 EXPECT_EQ(EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN, event.GetFlags()); 421 } 422 423 } // namespace ui 424