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 <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