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