Home | History | Annotate | Download | only in input
      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 #include <vector>
      6 
      7 #include "base/basictypes.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/time/time.h"
     11 #include "content/browser/renderer_host/input/touch_emulator.h"
     12 #include "content/browser/renderer_host/input/touch_emulator_client.h"
     13 #include "content/common/input/web_input_event_traits.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "ui/events/gesture_detection/gesture_config_helper.h"
     16 
     17 #if defined(USE_AURA)
     18 #include "ui/aura/env.h"
     19 #include "ui/aura/test/test_screen.h"
     20 #endif
     21 
     22 using blink::WebGestureEvent;
     23 using blink::WebInputEvent;
     24 using blink::WebKeyboardEvent;
     25 using blink::WebMouseEvent;
     26 using blink::WebMouseWheelEvent;
     27 using blink::WebTouchEvent;
     28 using blink::WebTouchPoint;
     29 
     30 namespace content {
     31 
     32 class TouchEmulatorTest : public testing::Test,
     33                           public TouchEmulatorClient {
     34  public:
     35   TouchEmulatorTest()
     36       : shift_pressed_(false),
     37         mouse_pressed_(false),
     38         last_mouse_x_(-1),
     39         last_mouse_y_(-1) {
     40     last_event_time_seconds_ =
     41         (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
     42     event_time_delta_seconds_ = 0.1;
     43   }
     44 
     45   virtual ~TouchEmulatorTest() {}
     46 
     47   // testing::Test
     48   virtual void SetUp() OVERRIDE {
     49 #if defined(USE_AURA)
     50     aura::Env::CreateInstance(true);
     51     screen_.reset(aura::TestScreen::Create(gfx::Size()));
     52     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
     53 #endif
     54 
     55     emulator_.reset(new TouchEmulator(this));
     56     emulator_->Enable(true /* allow_pinch */);
     57   }
     58 
     59   virtual void TearDown() OVERRIDE {
     60     emulator_->Disable();
     61     EXPECT_EQ("", ExpectedEvents());
     62 
     63 #if defined(USE_AURA)
     64     aura::Env::DeleteInstance();
     65     screen_.reset();
     66 #endif
     67   }
     68 
     69   virtual void ForwardGestureEvent(
     70       const blink::WebGestureEvent& event) OVERRIDE {
     71     forwarded_events_.push_back(event.type);
     72   }
     73 
     74   virtual void ForwardTouchEvent(
     75       const blink::WebTouchEvent& event) OVERRIDE {
     76     forwarded_events_.push_back(event.type);
     77     EXPECT_EQ(1U, event.touchesLength);
     78     EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
     79     EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
     80     int expectedCancelable = event.type != WebInputEvent::TouchCancel;
     81     EXPECT_EQ(expectedCancelable, event.cancelable);
     82     emulator()->HandleTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
     83   }
     84 
     85   virtual void SetCursor(const WebCursor& cursor) OVERRIDE {}
     86 
     87   virtual void ShowContextMenuAtPoint(const gfx::Point& point) OVERRIDE {}
     88 
     89  protected:
     90   TouchEmulator* emulator() const {
     91     return emulator_.get();
     92   }
     93 
     94   int modifiers() const {
     95     return shift_pressed_ ? WebInputEvent::ShiftKey : 0;
     96   }
     97 
     98   std::string ExpectedEvents() {
     99     std::string result;
    100     for (size_t i = 0; i < forwarded_events_.size(); ++i) {
    101       if (i != 0)
    102         result += " ";
    103       result += WebInputEventTraits::GetName(forwarded_events_[i]);
    104     }
    105     forwarded_events_.clear();
    106     return result;
    107   }
    108 
    109   double GetNextEventTimeSeconds() {
    110     last_event_time_seconds_ += event_time_delta_seconds_;
    111     return last_event_time_seconds_;
    112   }
    113 
    114   void set_event_time_delta_seconds_(double delta) {
    115     event_time_delta_seconds_ = delta;
    116   }
    117 
    118   void SendKeyboardEvent(WebInputEvent::Type type) {
    119     WebKeyboardEvent event;
    120     event.timeStampSeconds = GetNextEventTimeSeconds();
    121     event.type = type;
    122     event.modifiers = modifiers();
    123     emulator()->HandleKeyboardEvent(event);
    124   }
    125 
    126   void PressShift() {
    127     DCHECK(!shift_pressed_);
    128     shift_pressed_ = true;
    129     SendKeyboardEvent(WebInputEvent::KeyDown);
    130   }
    131 
    132   void ReleaseShift() {
    133     DCHECK(shift_pressed_);
    134     shift_pressed_ = false;
    135     SendKeyboardEvent(WebInputEvent::KeyUp);
    136   }
    137 
    138   void SendMouseEvent(WebInputEvent::Type type, int  x, int y) {
    139     WebMouseEvent event;
    140     event.timeStampSeconds = GetNextEventTimeSeconds();
    141     event.type = type;
    142     event.button = mouse_pressed_ ? WebMouseEvent::ButtonLeft :
    143         WebMouseEvent::ButtonNone;
    144     event.modifiers = modifiers();
    145     last_mouse_x_ = x;
    146     last_mouse_y_ = y;
    147     event.x = event.windowX = event.globalX = x;
    148     event.y = event.windowY = event.globalY = y;
    149     emulator()->HandleMouseEvent(event);
    150   }
    151 
    152   bool SendMouseWheelEvent() {
    153     WebMouseWheelEvent event;
    154     event.type = WebInputEvent::MouseWheel;
    155     event.timeStampSeconds = GetNextEventTimeSeconds();
    156     // Return whether mouse wheel is forwarded.
    157     return !emulator()->HandleMouseWheelEvent(event);
    158   }
    159 
    160   void MouseDown(int x, int y) {
    161     DCHECK(!mouse_pressed_);
    162     if (x != last_mouse_x_ || y != last_mouse_y_)
    163       SendMouseEvent(WebInputEvent::MouseMove, x, y);
    164     mouse_pressed_ = true;
    165     SendMouseEvent(WebInputEvent::MouseDown, x, y);
    166   }
    167 
    168   void MouseDrag(int x, int y) {
    169     DCHECK(mouse_pressed_);
    170     SendMouseEvent(WebInputEvent::MouseMove, x, y);
    171   }
    172 
    173   void MouseMove(int x, int y) {
    174     DCHECK(!mouse_pressed_);
    175     SendMouseEvent(WebInputEvent::MouseMove, x, y);
    176   }
    177 
    178   void MouseUp(int x, int y) {
    179     DCHECK(mouse_pressed_);
    180     if (x != last_mouse_x_ || y != last_mouse_y_)
    181       SendMouseEvent(WebInputEvent::MouseMove, x, y);
    182     SendMouseEvent(WebInputEvent::MouseUp, x, y);
    183     mouse_pressed_ = false;
    184   }
    185 
    186  private:
    187   scoped_ptr<TouchEmulator> emulator_;
    188   std::vector<WebInputEvent::Type> forwarded_events_;
    189 #if defined(USE_AURA)
    190   scoped_ptr<gfx::Screen> screen_;
    191 #endif
    192   double last_event_time_seconds_;
    193   double event_time_delta_seconds_;
    194   bool shift_pressed_;
    195   bool mouse_pressed_;
    196   int last_mouse_x_;
    197   int last_mouse_y_;
    198   base::MessageLoopForUI message_loop_;
    199 };
    200 
    201 
    202 TEST_F(TouchEmulatorTest, NoTouches) {
    203   MouseMove(100, 200);
    204   MouseMove(300, 300);
    205   EXPECT_EQ("", ExpectedEvents());
    206 }
    207 
    208 TEST_F(TouchEmulatorTest, Touch) {
    209   MouseMove(100, 200);
    210   EXPECT_EQ("", ExpectedEvents());
    211   MouseDown(100, 200);
    212   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    213   MouseUp(200, 200);
    214   EXPECT_EQ(
    215       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
    216       " TouchEnd GestureScrollEnd",
    217       ExpectedEvents());
    218 }
    219 
    220 TEST_F(TouchEmulatorTest, MultipleTouches) {
    221   MouseMove(100, 200);
    222   EXPECT_EQ("", ExpectedEvents());
    223   MouseDown(100, 200);
    224   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    225   MouseUp(200, 200);
    226   EXPECT_EQ(
    227       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
    228       " TouchEnd GestureScrollEnd",
    229       ExpectedEvents());
    230   MouseMove(300, 200);
    231   MouseMove(200, 200);
    232   EXPECT_EQ("", ExpectedEvents());
    233   MouseDown(300, 200);
    234   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    235   MouseDrag(300, 300);
    236   EXPECT_EQ(
    237       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
    238       ExpectedEvents());
    239   MouseDrag(300, 400);
    240   EXPECT_EQ("TouchMove GestureScrollUpdate", ExpectedEvents());
    241   MouseUp(300, 500);
    242   EXPECT_EQ(
    243       "TouchMove GestureScrollUpdate TouchEnd GestureScrollEnd",
    244       ExpectedEvents());
    245 }
    246 
    247 TEST_F(TouchEmulatorTest, Pinch) {
    248   MouseDown(100, 200);
    249   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    250   MouseDrag(200, 200);
    251   EXPECT_EQ(
    252       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
    253       ExpectedEvents());
    254   PressShift();
    255   EXPECT_EQ("", ExpectedEvents());
    256   MouseDrag(300, 200);
    257   EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
    258   ReleaseShift();
    259   EXPECT_EQ("", ExpectedEvents());
    260   MouseDrag(400, 200);
    261   EXPECT_EQ(
    262       "TouchMove GesturePinchEnd GestureScrollUpdate",
    263       ExpectedEvents());
    264   MouseUp(400, 200);
    265   EXPECT_EQ("TouchEnd GestureScrollEnd", ExpectedEvents());
    266 }
    267 
    268 TEST_F(TouchEmulatorTest, DisableAndReenable) {
    269   MouseDown(100, 200);
    270   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    271   MouseDrag(200, 200);
    272   EXPECT_EQ(
    273       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
    274       ExpectedEvents());
    275   PressShift();
    276   MouseDrag(300, 200);
    277   EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
    278 
    279   // Disable while pinch is in progress.
    280   emulator()->Disable();
    281   EXPECT_EQ("TouchCancel GesturePinchEnd GestureScrollEnd", ExpectedEvents());
    282   MouseUp(300, 200);
    283   ReleaseShift();
    284   MouseMove(300, 300);
    285   EXPECT_EQ("", ExpectedEvents());
    286 
    287   emulator()->Enable(true /* allow_pinch */);
    288   MouseDown(300, 300);
    289   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    290   MouseDrag(300, 400);
    291   EXPECT_EQ(
    292       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
    293       ExpectedEvents());
    294 
    295   // Disable while scroll is in progress.
    296   emulator()->Disable();
    297   EXPECT_EQ("TouchCancel GestureScrollEnd", ExpectedEvents());
    298 }
    299 
    300 TEST_F(TouchEmulatorTest, MouseMovesDropped) {
    301   MouseMove(100, 200);
    302   EXPECT_EQ("", ExpectedEvents());
    303   MouseDown(100, 200);
    304   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    305 
    306   // Mouse move after mouse down is never dropped.
    307   set_event_time_delta_seconds_(0.001);
    308   MouseDrag(200, 200);
    309   EXPECT_EQ(
    310       "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
    311       ExpectedEvents());
    312 
    313   // The following mouse moves are dropped.
    314   MouseDrag(300, 200);
    315   EXPECT_EQ("", ExpectedEvents());
    316   MouseDrag(350, 200);
    317   EXPECT_EQ("", ExpectedEvents());
    318 
    319   // Dispatching again.
    320   set_event_time_delta_seconds_(0.1);
    321   MouseDrag(400, 200);
    322   EXPECT_EQ(
    323       "TouchMove GestureScrollUpdate",
    324       ExpectedEvents());
    325   MouseUp(400, 200);
    326   EXPECT_EQ(
    327       "TouchEnd GestureScrollEnd",
    328       ExpectedEvents());
    329 }
    330 
    331 TEST_F(TouchEmulatorTest, MouseWheel) {
    332   MouseMove(100, 200);
    333   EXPECT_EQ("", ExpectedEvents());
    334   EXPECT_TRUE(SendMouseWheelEvent());
    335   MouseDown(100, 200);
    336   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    337   EXPECT_FALSE(SendMouseWheelEvent());
    338   MouseUp(100, 200);
    339   EXPECT_EQ("TouchEnd GestureShowPress GestureTap", ExpectedEvents());
    340   EXPECT_TRUE(SendMouseWheelEvent());
    341   MouseDown(300, 200);
    342   EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
    343   EXPECT_FALSE(SendMouseWheelEvent());
    344   emulator()->Disable();
    345   EXPECT_EQ("TouchCancel GestureTapCancel", ExpectedEvents());
    346   EXPECT_TRUE(SendMouseWheelEvent());
    347   emulator()->Enable(true /* allow_pinch */);
    348   EXPECT_TRUE(SendMouseWheelEvent());
    349 }
    350 
    351 }  // namespace content
    352