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