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 "ui/events/event_constants.h" 15 #include "ui/events/keycodes/keyboard_codes.h" 16 #include "ui/gfx/point.h" 17 18 namespace base { 19 class TimeDelta; 20 } 21 22 namespace ui { 23 class Event; 24 class KeyEvent; 25 class MouseEvent; 26 class ScrollEvent; 27 class TouchEvent; 28 } 29 30 namespace aura { 31 class RootWindow; 32 class Window; 33 34 namespace client { 35 class ScreenPositionClient; 36 } 37 38 namespace test { 39 40 typedef base::Callback<void(ui::EventType, const gfx::Vector2dF&)> 41 ScrollStepCallback; 42 43 // A delegate interface for EventGenerator that provides a way to 44 // locate aura root window for given point. 45 class EventGeneratorDelegate { 46 public: ~EventGeneratorDelegate()47 virtual ~EventGeneratorDelegate() {} 48 49 // Returns a root window for given point. 50 virtual RootWindow* GetRootWindowAt(const gfx::Point& point) const = 0; 51 52 // Returns the screen position client that determines the 53 // coordinates used in EventGenerator. EventGenerator uses 54 // RootWindow's coordinate if this retruns NULL. 55 virtual client::ScreenPositionClient* GetScreenPositionClient( 56 const aura::Window* window) const = 0; 57 }; 58 59 // EventGenerator is a tool that generates and dispatch events. 60 // Unlike |ui_controls| package in ui/base/test, this does not 61 // generate platform native events. Insetad, it directly posts event 62 // to |aura::RootWindow| synchronously. 63 64 // Advantage of using this class, compared to |ui_controls| is that 65 // you can write the tests that involves events in synchronus 66 // way. There is no need to wait for native 67 // 68 // On the other hand, this class is not suited for the following 69 // cases: 70 // 71 // 1) If your test depends on native events (ui::Event::native_event()). 72 // This return is empty/NULL event with EventGenerator. 73 // 2) If your test involves nested message loop, such as 74 // menu or drag & drop. Because this class directly 75 // post an event to RootWindow, this event will not be 76 // handled in the nested message loop. 77 // 3) Similarly, |base::MessagePumpObserver| will not be invoked. 78 // 4) Any other code that requires native events, such as 79 // tests for RootWindowHostWin/RootWindowHostX11. 80 // 81 // If one of these applies to your test, please use |ui_controls| 82 // package instead. 83 // 84 // Note: The coordinates of the points in API is determined by the 85 // EventGeneratorDelegate. 86 class EventGenerator { 87 public: 88 // Creates an EventGenerator with the mouse/touch location (0,0), 89 // which uses the |root_window|'s coordinates. 90 explicit EventGenerator(Window* root_window); 91 92 // Create an EventGenerator with EventGeneratorDelegate, 93 // which uses the coordinates used by |delegate|. 94 explicit EventGenerator(EventGeneratorDelegate* delegate); 95 96 // Creates an EventGenerator with the mouse/touch location 97 // at |initial_location|, which uses the |root_window|'s coordinates. 98 EventGenerator(Window* root_window, const gfx::Point& initial_location); 99 100 // Creates an EventGenerator with the mouse/touch location 101 // centered over |window|, which uses the |root_window|'s coordinates. 102 EventGenerator(Window* root_window, Window* window); 103 104 virtual ~EventGenerator(); 105 106 // Explicitly sets the location used by mouse/touch events. This is set by the 107 // various methods that take a location but can be manipulated directly, 108 // typically for touch. set_current_location(const gfx::Point & location)109 void set_current_location(const gfx::Point& location) { 110 current_location_ = location; 111 } current_location()112 const gfx::Point& current_location() const { return current_location_; } 113 set_async(bool async)114 void set_async(bool async) { async_ = async; } async()115 bool async() const { return async_; } 116 117 // Resets the event flags bitmask. set_flags(int flags)118 void set_flags(int flags) { flags_ = flags; } 119 120 // Generates a left button press event. 121 void PressLeftButton(); 122 123 // Generates a left button release event. 124 void ReleaseLeftButton(); 125 126 // Generates events to click (press, release) left button. 127 void ClickLeftButton(); 128 129 // Generates a double click event using the left button. 130 void DoubleClickLeftButton(); 131 132 // Generates a right button press event. 133 void PressRightButton(); 134 135 // Generates a right button release event. 136 void ReleaseRightButton(); 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 touch-events required to generate a TAP gesture. 218 // Note that this can generate a number of other gesture events at the same 219 // time (e.g. GESTURE_BEGIN, TAP_DOWN, END). 220 void GestureTapAt(const gfx::Point& point); 221 222 // Generates press and release touch-events to generate a TAP_DOWN event, but 223 // without generating any scroll or tap events. This can also generate a few 224 // other gesture events (e.g. GESTURE_BEGIN, END). 225 void GestureTapDownAndUp(const gfx::Point& point); 226 227 // Generates press, move, release touch-events to generate a sequence of 228 // scroll events. |duration| and |steps| affect the velocity of the scroll, 229 // and depending on these values, this may also generate FLING scroll 230 // gestures. If velocity/fling is irrelevant for the test, then any non-zero 231 // values for these should be sufficient. 232 void GestureScrollSequence(const gfx::Point& start, 233 const gfx::Point& end, 234 const base::TimeDelta& duration, 235 int steps); 236 237 // The same as GestureScrollSequence(), with the exception that |callback| is 238 // called at each step of the scroll sequence. |callback| is called at the 239 // start of the sequence with ET_GESTURE_SCROLL_BEGIN, followed by one or more 240 // ET_GESTURE_SCROLL_UPDATE and ends with an ET_GESTURE_SCROLL_END. 241 void GestureScrollSequenceWithCallback(const gfx::Point& start, 242 const gfx::Point& end, 243 const base::TimeDelta& duration, 244 int steps, 245 const ScrollStepCallback& callback); 246 247 // Generates press, move, release touch-events to generate a sequence of 248 // multi-finger scroll events. |count| specifies the number of touch-points 249 // that should generate the scroll events. |start| are the starting positions 250 // of all the touch points. |steps| and |event_separation_time_ms| are 251 // relevant when testing velocity/fling/swipe, otherwise these can be any 252 // non-zero value. |delta_x| and |delta_y| are the amount that each finger 253 // should be moved. Internally calls GestureMultiFingerScrollWithDelays 254 // with zeros as |delay_adding_finger_ms| forcing all touch down events to be 255 // immediate. 256 void GestureMultiFingerScroll(int count, 257 const gfx::Point start[], 258 int event_separation_time_ms, 259 int steps, 260 int move_x, 261 int move_y); 262 263 // Generates press, move, release touch-events to generate a sequence of 264 // multi-finger scroll events. |count| specifies the number of touch-points 265 // that should generate the scroll events. |start| are the starting positions 266 // of all the touch points. |delay_adding_finger_ms| are delays in ms from the 267 // starting time till touching down of each finger. |delay_adding_finger_ms| 268 // is useful when testing complex gestures that start with 1 or 2 fingers and 269 // add fingers with a delay. |steps| and |event_separation_time_ms| are 270 // relevant when testing velocity/fling/swipe, otherwise these can be any 271 // non-zero value. |delta_x| and |delta_y| are the amount that each finger 272 // should be moved. 273 void GestureMultiFingerScrollWithDelays(int count, 274 const gfx::Point start[], 275 const int delay_adding_finger_ms[], 276 int event_separation_time_ms, 277 int steps, 278 int move_x, 279 int move_y); 280 281 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with 282 // constant deltas to |x_offset| and |y_offset| in |steps|. 283 void ScrollSequence(const gfx::Point& start, 284 const base::TimeDelta& step_delay, 285 float x_offset, 286 float y_offset, 287 int steps, 288 int num_fingers); 289 290 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, sending 291 // scrolls of each of the values in |offsets|. 292 void ScrollSequence(const gfx::Point& start, 293 const base::TimeDelta& step_delay, 294 const std::vector<gfx::Point>& offsets, 295 int num_fingers); 296 297 // Generates a key press event. On platforms except Windows and X11, a key 298 // event without native_event() is generated. Note that ui::EF_ flags should 299 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 300 // TODO(yusukes): Support native_event() on all platforms. 301 void PressKey(ui::KeyboardCode key_code, int flags); 302 303 // Generates a key release event. On platforms except Windows and X11, a key 304 // event without native_event() is generated. Note that ui::EF_ flags should 305 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 306 // TODO(yusukes): Support native_event() on all platforms. 307 void ReleaseKey(ui::KeyboardCode key_code, int flags); 308 309 // Dispatch the event to the RootWindow. 310 void Dispatch(ui::Event* event); 311 set_current_root_window(RootWindow * root_window)312 void set_current_root_window(RootWindow* root_window) { 313 current_root_window_ = root_window; 314 } 315 316 private: 317 // Dispatch a key event to the RootWindow. 318 void DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags); 319 320 void UpdateCurrentRootWindow(const gfx::Point& point); 321 void PressButton(int flag); 322 void ReleaseButton(int flag); 323 324 // Convert a point between API's coordinates and 325 // |target|'s coordinates. 326 void ConvertPointFromTarget(const aura::Window* target, 327 gfx::Point* point) const; 328 void ConvertPointToTarget(const aura::Window* target, 329 gfx::Point* point) const; 330 331 gfx::Point GetLocationInCurrentRoot() const; 332 gfx::Point CenterOfWindow(const Window* window) const; 333 334 void DispatchNextPendingEvent(); 335 void DoDispatchEvent(ui::Event* event, bool async); 336 337 scoped_ptr<EventGeneratorDelegate> delegate_; 338 gfx::Point current_location_; 339 RootWindow* current_root_window_; 340 int flags_; 341 bool grab_; 342 std::list<ui::Event*> pending_events_; 343 // Set to true to cause events to be posted asynchronously. 344 bool async_; 345 346 DISALLOW_COPY_AND_ASSIGN(EventGenerator); 347 }; 348 349 } // namespace test 350 } // namespace aura 351 352 #endif // UI_AURA_TEST_EVENT_GENERATOR_H_ 353