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 #ifndef UI_EVENTS_TEST_EVENT_GENERATOR_H_ 6 #define UI_EVENTS_TEST_EVENT_GENERATOR_H_ 7 8 #include <list> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/callback.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/time/time.h" 15 #include "ui/events/event_constants.h" 16 #include "ui/events/keycodes/keyboard_codes.h" 17 #include "ui/gfx/native_widget_types.h" 18 #include "ui/gfx/point.h" 19 20 namespace base { 21 class TickClock; 22 } 23 24 namespace ui { 25 class Event; 26 class EventProcessor; 27 class EventSource; 28 class EventTarget; 29 class KeyEvent; 30 class MouseEvent; 31 class ScrollEvent; 32 class TouchEvent; 33 34 namespace test { 35 36 typedef base::Callback<void(EventType, const gfx::Vector2dF&)> 37 ScrollStepCallback; 38 39 class EventGenerator; 40 41 // A delegate interface for EventGenerator to abstract platform-specific event 42 // targeting and coordinate conversion. 43 class EventGeneratorDelegate { 44 public: ~EventGeneratorDelegate()45 virtual ~EventGeneratorDelegate() {} 46 47 // Set the context of the delegate, whilst it is being used by an active 48 // EventGenerator. SetContext(EventGenerator * owner,gfx::NativeWindow root_window,gfx::NativeWindow window)49 virtual void SetContext(EventGenerator* owner, 50 gfx::NativeWindow root_window, 51 gfx::NativeWindow window) {} 52 53 // The ui::EventTarget at the given |location|. 54 virtual EventTarget* GetTargetAt(const gfx::Point& location) = 0; 55 56 // The ui::EventSource for the given |target|. 57 virtual EventSource* GetEventSource(EventTarget* target) = 0; 58 59 // Helper functions to determine the center point of |target| or |window|. 60 virtual gfx::Point CenterOfTarget(const EventTarget* target) const = 0; 61 virtual gfx::Point CenterOfWindow(gfx::NativeWindow window) const = 0; 62 63 // Convert a point between API's coordinates and |target|'s coordinates. 64 virtual void ConvertPointFromTarget(const EventTarget* target, 65 gfx::Point* point) const = 0; 66 virtual void ConvertPointToTarget(const EventTarget* target, 67 gfx::Point* point) const = 0; 68 69 // Convert a point from the coordinate system in the host that contains 70 // |hosted_target| into the root window's coordinate system. 71 virtual void ConvertPointFromHost(const EventTarget* hosted_target, 72 gfx::Point* point) const = 0; 73 }; 74 75 // ui::test::EventGenerator is a tool that generates and dispatches events. 76 // Unlike |ui_controls| package in ui/base/test, this does not use platform 77 // native message loops. Instead, it sends events to the event dispatcher 78 // synchronously. 79 // 80 // This class is not suited for the following cases: 81 // 82 // 1) If your test depends on native events (ui::Event::native_event()). 83 // This return is empty/NULL event with EventGenerator. 84 // 2) If your test involves nested message loop, such as 85 // menu or drag & drop. Because this class directly 86 // post an event to WindowEventDispatcher, this event will not be 87 // handled in the nested message loop. 88 // 3) Similarly, |base::MessagePumpObserver| will not be invoked. 89 // 4) Any other code that requires native message loops, such as 90 // tests for WindowTreeHostWin/WindowTreeHostX11. 91 // 92 // If one of these applies to your test, please use |ui_controls| 93 // package instead. 94 // 95 // Note: The coordinates of the points in API is determined by the 96 // EventGeneratorDelegate. 97 class EventGenerator { 98 public: 99 // Creates an EventGenerator with the mouse/touch location (0,0), 100 // which uses the |root_window|'s coordinates and the default delegate for 101 // this platform. 102 explicit EventGenerator(gfx::NativeWindow root_window); 103 104 // Create an EventGenerator with EventGeneratorDelegate, 105 // which uses the coordinates conversions and targeting provided by 106 // |delegate|. 107 explicit EventGenerator(EventGeneratorDelegate* delegate); 108 109 // Creates an EventGenerator with the mouse/touch location 110 // at |initial_location|, which uses the |root_window|'s coordinates. 111 EventGenerator(gfx::NativeWindow root_window, 112 const gfx::Point& initial_location); 113 114 // Creates an EventGenerator with the mouse/touch location centered over 115 // |window|. This is currently the only constructor that works on Mac, since 116 // a specific window is required (and there is no root window). 117 EventGenerator(gfx::NativeWindow root_window, gfx::NativeWindow window); 118 119 virtual ~EventGenerator(); 120 121 // Explicitly sets the location used by mouse/touch events. This is set by the 122 // various methods that take a location but can be manipulated directly, 123 // typically for touch. set_current_location(const gfx::Point & location)124 void set_current_location(const gfx::Point& location) { 125 current_location_ = location; 126 } current_location()127 const gfx::Point& current_location() const { return current_location_; } 128 set_async(bool async)129 void set_async(bool async) { async_ = async; } async()130 bool async() const { return async_; } 131 132 // Resets the event flags bitmask. set_flags(int flags)133 void set_flags(int flags) { flags_ = flags; } flags()134 int flags() const { return flags_; } 135 136 // Generates a left button press event. 137 void PressLeftButton(); 138 139 // Generates a left button release event. 140 void ReleaseLeftButton(); 141 142 // Generates events to click (press, release) left button. 143 void ClickLeftButton(); 144 145 // Generates a double click event using the left button. 146 void DoubleClickLeftButton(); 147 148 // Generates a right button press event. 149 void PressRightButton(); 150 151 // Generates a right button release event. 152 void ReleaseRightButton(); 153 154 // Moves the mouse wheel by |delta_x|, |delta_y|. 155 void MoveMouseWheel(int delta_x, int delta_y); 156 157 // Generates a mouse exit. 158 void SendMouseExit(); 159 160 // Generates events to move mouse to be the given |point| in the 161 // |current_root_window_|'s host window coordinates. 162 void MoveMouseToInHost(const gfx::Point& point_in_host); MoveMouseToInHost(int x,int y)163 void MoveMouseToInHost(int x, int y) { 164 MoveMouseToInHost(gfx::Point(x, y)); 165 } 166 167 // Generates events to move mouse to be the given |point| in screen 168 // coordinates. 169 void MoveMouseTo(const gfx::Point& point_in_screen, int count); MoveMouseTo(const gfx::Point & point_in_screen)170 void MoveMouseTo(const gfx::Point& point_in_screen) { 171 MoveMouseTo(point_in_screen, 1); 172 } MoveMouseTo(int x,int y)173 void MoveMouseTo(int x, int y) { 174 MoveMouseTo(gfx::Point(x, y)); 175 } 176 177 // Generates events to move mouse to be the given |point| in |window|'s 178 // coordinates. 179 void MoveMouseRelativeTo(const EventTarget* window, const gfx::Point& point); MoveMouseRelativeTo(const EventTarget * window,int x,int y)180 void MoveMouseRelativeTo(const EventTarget* window, int x, int y) { 181 MoveMouseRelativeTo(window, gfx::Point(x, y)); 182 } 183 MoveMouseBy(int x,int y)184 void MoveMouseBy(int x, int y) { 185 MoveMouseTo(current_location_ + gfx::Vector2d(x, y)); 186 } 187 188 // Generates events to drag mouse to given |point|. 189 void DragMouseTo(const gfx::Point& point); 190 DragMouseTo(int x,int y)191 void DragMouseTo(int x, int y) { 192 DragMouseTo(gfx::Point(x, y)); 193 } 194 DragMouseBy(int dx,int dy)195 void DragMouseBy(int dx, int dy) { 196 DragMouseTo(current_location_ + gfx::Vector2d(dx, dy)); 197 } 198 199 // Generates events to move the mouse to the center of the window. 200 void MoveMouseToCenterOf(EventTarget* window); 201 202 // Generates a touch press event. 203 void PressTouch(); 204 205 // Generates a touch press event with |touch_id|. 206 void PressTouchId(int touch_id); 207 208 // Generates a ET_TOUCH_MOVED event to |point|. 209 void MoveTouch(const gfx::Point& point); 210 211 // Generates a ET_TOUCH_MOVED event to |point| with |touch_id|. 212 void MoveTouchId(const gfx::Point& point, int touch_id); 213 214 // Generates a touch release event. 215 void ReleaseTouch(); 216 217 // Generates a touch release event with |touch_id|. 218 void ReleaseTouchId(int touch_id); 219 220 // Generates press, move and release event to move touch 221 // to be the given |point|. 222 void PressMoveAndReleaseTouchTo(const gfx::Point& point); 223 PressMoveAndReleaseTouchTo(int x,int y)224 void PressMoveAndReleaseTouchTo(int x, int y) { 225 PressMoveAndReleaseTouchTo(gfx::Point(x, y)); 226 } 227 PressMoveAndReleaseTouchBy(int x,int y)228 void PressMoveAndReleaseTouchBy(int x, int y) { 229 PressMoveAndReleaseTouchTo(current_location_ + gfx::Vector2d(x, y)); 230 } 231 232 // Generates press, move and release events to move touch 233 // to the center of the window. 234 void PressMoveAndReleaseTouchToCenterOf(EventTarget* window); 235 236 // Generates and dispatches a Win8 edge-swipe event (swipe up from bottom or 237 // swipe down from top). Note that it is not possible to distinguish between 238 // the two edges with this event. 239 void GestureEdgeSwipe(); 240 241 // Generates and dispatches touch-events required to generate a TAP gesture. 242 // Note that this can generate a number of other gesture events at the same 243 // time (e.g. GESTURE_BEGIN, TAP_DOWN, END). 244 void GestureTapAt(const gfx::Point& point); 245 246 // Generates press and release touch-events to generate a TAP_DOWN event, but 247 // without generating any scroll or tap events. This can also generate a few 248 // other gesture events (e.g. GESTURE_BEGIN, END). 249 void GestureTapDownAndUp(const gfx::Point& point); 250 251 // Generates press, move, release touch-events to generate a sequence of 252 // scroll events. |duration| and |steps| affect the velocity of the scroll, 253 // and depending on these values, this may also generate FLING scroll 254 // gestures. If velocity/fling is irrelevant for the test, then any non-zero 255 // values for these should be sufficient. 256 void GestureScrollSequence(const gfx::Point& start, 257 const gfx::Point& end, 258 const base::TimeDelta& duration, 259 int steps); 260 261 // The same as GestureScrollSequence(), with the exception that |callback| is 262 // called at each step of the scroll sequence. |callback| is called at the 263 // start of the sequence with ET_GESTURE_SCROLL_BEGIN, followed by one or more 264 // ET_GESTURE_SCROLL_UPDATE and ends with an ET_GESTURE_SCROLL_END. 265 void GestureScrollSequenceWithCallback(const gfx::Point& start, 266 const gfx::Point& end, 267 const base::TimeDelta& duration, 268 int steps, 269 const ScrollStepCallback& callback); 270 271 // Generates press, move, release touch-events to generate a sequence of 272 // multi-finger scroll events. |count| specifies the number of touch-points 273 // that should generate the scroll events. |start| are the starting positions 274 // of all the touch points. |steps| and |event_separation_time_ms| are 275 // relevant when testing velocity/fling/swipe, otherwise these can be any 276 // non-zero value. |delta_x| and |delta_y| are the amount that each finger 277 // should be moved. Internally calls GestureMultiFingerScrollWithDelays 278 // with zeros as |delay_adding_finger_ms| forcing all touch down events to be 279 // immediate. 280 void GestureMultiFingerScroll(int count, 281 const gfx::Point start[], 282 int event_separation_time_ms, 283 int steps, 284 int move_x, 285 int move_y); 286 287 // Generates press, move, release touch-events to generate a sequence of 288 // multi-finger scroll events. |count| specifies the number of touch-points 289 // that should generate the scroll events. |start| are the starting positions 290 // of all the touch points. |delay_adding_finger_ms| are delays in ms from the 291 // starting time till touching down of each finger. |delay_adding_finger_ms| 292 // is useful when testing complex gestures that start with 1 or 2 fingers and 293 // add fingers with a delay. |steps| and |event_separation_time_ms| are 294 // relevant when testing velocity/fling/swipe, otherwise these can be any 295 // non-zero value. |delta_x| and |delta_y| are the amount that each finger 296 // should be moved. 297 void GestureMultiFingerScrollWithDelays(int count, 298 const gfx::Point start[], 299 const int delay_adding_finger_ms[], 300 int event_separation_time_ms, 301 int steps, 302 int move_x, 303 int move_y); 304 305 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with 306 // constant deltas to |x_offset| and |y_offset| in |steps|. 307 void ScrollSequence(const gfx::Point& start, 308 const base::TimeDelta& step_delay, 309 float x_offset, 310 float y_offset, 311 int steps, 312 int num_fingers); 313 314 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, sending 315 // scrolls of each of the values in |offsets|. 316 void ScrollSequence(const gfx::Point& start, 317 const base::TimeDelta& step_delay, 318 const std::vector<gfx::Point>& offsets, 319 int num_fingers); 320 321 // Generates a key press event. On platforms except Windows and X11, a key 322 // event without native_event() is generated. Note that ui::EF_ flags should 323 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 324 // TODO(yusukes): Support native_event() on all platforms. 325 void PressKey(KeyboardCode key_code, int flags); 326 327 // Generates a key release event. On platforms except Windows and X11, a key 328 // event without native_event() is generated. Note that ui::EF_ flags should 329 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 330 // TODO(yusukes): Support native_event() on all platforms. 331 void ReleaseKey(KeyboardCode key_code, int flags); 332 333 // Dispatch the event to the WindowEventDispatcher. 334 void Dispatch(Event* event); 335 set_current_target(EventTarget * target)336 void set_current_target(EventTarget* target) { 337 current_target_ = target; 338 } 339 340 // Specify an alternative tick clock to be used for simulating time in tests. 341 void SetTickClock(scoped_ptr<base::TickClock> tick_clock); 342 343 // Get the current time from the tick clock. 344 base::TimeDelta Now(); 345 346 // Default delegate set by a platform-specific GeneratorDelegate singleton. 347 static EventGeneratorDelegate* default_delegate; 348 349 private: 350 // Set up the test context using the delegate. 351 void Init(gfx::NativeWindow root_window, gfx::NativeWindow window_context); 352 353 // Dispatch a key event to the WindowEventDispatcher. 354 void DispatchKeyEvent(bool is_press, KeyboardCode key_code, int flags); 355 356 void UpdateCurrentDispatcher(const gfx::Point& point); 357 void PressButton(int flag); 358 void ReleaseButton(int flag); 359 360 gfx::Point GetLocationInCurrentRoot() const; 361 gfx::Point CenterOfWindow(const EventTarget* window) const; 362 363 void DispatchNextPendingEvent(); 364 void DoDispatchEvent(Event* event, bool async); 365 366 const EventGeneratorDelegate* delegate() const; 367 EventGeneratorDelegate* delegate(); 368 369 scoped_ptr<EventGeneratorDelegate> delegate_; 370 gfx::Point current_location_; 371 EventTarget* current_target_; 372 int flags_; 373 bool grab_; 374 std::list<Event*> pending_events_; 375 // Set to true to cause events to be posted asynchronously. 376 bool async_; 377 scoped_ptr<base::TickClock> tick_clock_; 378 379 DISALLOW_COPY_AND_ASSIGN(EventGenerator); 380 }; 381 382 } // namespace test 383 } // namespace ui 384 385 #endif // UI_EVENTS_TEST_EVENT_GENERATOR_H_ 386