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/base/events/event_constants.h" 15 #include "ui/base/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: 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(RootWindow* 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(RootWindow* 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(RootWindow* 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. 109 void set_current_location(const gfx::Point& location) { 110 current_location_ = location; 111 } 112 const gfx::Point& current_location() const { return current_location_; } 113 114 void set_async(bool async) { async_ = async; } 115 bool async() const { return async_; } 116 117 // Resets the event flags bitmask. 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 events to move mouse to be the given |point| in the 139 // |current_root_window_|'s host window coordinates. 140 void MoveMouseToInHost(const gfx::Point& point_in_host); 141 void MoveMouseToInHost(int x, int y) { 142 MoveMouseToInHost(gfx::Point(x, y)); 143 } 144 145 // Generates events to move mouse to be the given |point| in screen 146 // coordinates. 147 void MoveMouseTo(const gfx::Point& point_in_screen, int count); 148 void MoveMouseTo(const gfx::Point& point_in_screen) { 149 MoveMouseTo(point_in_screen, 1); 150 } 151 void MoveMouseTo(int x, int y) { 152 MoveMouseTo(gfx::Point(x, y)); 153 } 154 155 // Generates events to move mouse to be the given |point| in |window|'s 156 // coordinates. 157 void MoveMouseRelativeTo(const Window* window, const gfx::Point& point); 158 void MoveMouseRelativeTo(const Window* window, int x, int y) { 159 MoveMouseRelativeTo(window, gfx::Point(x, y)); 160 } 161 162 void MoveMouseBy(int x, int y) { 163 MoveMouseTo(current_location_ + gfx::Vector2d(x, y)); 164 } 165 166 // Generates events to drag mouse to given |point|. 167 void DragMouseTo(const gfx::Point& point); 168 169 void DragMouseTo(int x, int y) { 170 DragMouseTo(gfx::Point(x, y)); 171 } 172 173 void DragMouseBy(int dx, int dy) { 174 DragMouseTo(current_location_ + gfx::Vector2d(dx, dy)); 175 } 176 177 // Generates events to move the mouse to the center of the window. 178 void MoveMouseToCenterOf(Window* window); 179 180 // Generates a touch press event. 181 void PressTouch(); 182 183 // Generates a ET_TOUCH_MOVED event to |point|. 184 void MoveTouch(const gfx::Point& point); 185 186 // Generates a touch release event. 187 void ReleaseTouch(); 188 189 // Generates press, move and release event to move touch 190 // to be the given |point|. 191 void PressMoveAndReleaseTouchTo(const gfx::Point& point); 192 193 void PressMoveAndReleaseTouchTo(int x, int y) { 194 PressMoveAndReleaseTouchTo(gfx::Point(x, y)); 195 } 196 197 void PressMoveAndReleaseTouchBy(int x, int y) { 198 PressMoveAndReleaseTouchTo(current_location_ + gfx::Vector2d(x, y)); 199 } 200 201 // Generates press, move and release events to move touch 202 // to the center of the window. 203 void PressMoveAndReleaseTouchToCenterOf(Window* window); 204 205 // Generates and dispatches touch-events required to generate a TAP gesture. 206 // Note that this can generate a number of other gesture events at the same 207 // time (e.g. GESTURE_BEGIN, TAP_DOWN, END). 208 void GestureTapAt(const gfx::Point& point); 209 210 // Generates press and release touch-events to generate a TAP_DOWN event, but 211 // without generating any scroll or tap events. This can also generate a few 212 // other gesture events (e.g. GESTURE_BEGIN, END). 213 void GestureTapDownAndUp(const gfx::Point& point); 214 215 // Generates press, move, release touch-events to generate a sequence of 216 // scroll events. |duration| and |steps| affect the velocity of the scroll, 217 // and depending on these values, this may also generate FLING scroll 218 // gestures. If velocity/fling is irrelevant for the test, then any non-zero 219 // values for these should be sufficient. 220 void GestureScrollSequence(const gfx::Point& start, 221 const gfx::Point& end, 222 const base::TimeDelta& duration, 223 int steps); 224 225 // The same as GestureScrollSequence(), with the exception that |callback| is 226 // called at each step of the scroll sequence. |callback| is called at the 227 // start of the sequence with ET_GESTURE_SCROLL_BEGIN, followed by one or more 228 // ET_GESTURE_SCROLL_UPDATE and ends with an ET_GESTURE_SCROLL_END. 229 void GestureScrollSequenceWithCallback(const gfx::Point& start, 230 const gfx::Point& end, 231 const base::TimeDelta& duration, 232 int steps, 233 const ScrollStepCallback& callback); 234 235 // Generates press, move, release touch-events to generate a sequence of 236 // multi-finger scroll events. |count| specifies the number of touch-points 237 // that should generate the scroll events. |start| are the starting positions 238 // of all the touch points. |steps| and |event_separation_time_ms| are 239 // relevant when testing velocity/fling/swipe, otherwise these can be any 240 // non-zero value. |delta_x| and |delta_y| are the amount that each finger 241 // should be moved. 242 void GestureMultiFingerScroll(int count, 243 const gfx::Point* start, 244 int event_separation_time_ms, 245 int steps, 246 int move_x, 247 int move_y); 248 249 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with 250 // constant deltas to |x_offset| and |y_offset| in |steps|. 251 void ScrollSequence(const gfx::Point& start, 252 const base::TimeDelta& step_delay, 253 float x_offset, 254 float y_offset, 255 int steps, 256 int num_fingers); 257 258 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, sending 259 // scrolls of each of the values in |offsets|. 260 void ScrollSequence(const gfx::Point& start, 261 const base::TimeDelta& step_delay, 262 const std::vector<gfx::Point>& offsets, 263 int num_fingers); 264 265 // Generates a key press event. On platforms except Windows and X11, a key 266 // event without native_event() is generated. Note that ui::EF_ flags should 267 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 268 // TODO(yusukes): Support native_event() on all platforms. 269 void PressKey(ui::KeyboardCode key_code, int flags); 270 271 // Generates a key release event. On platforms except Windows and X11, a key 272 // event without native_event() is generated. Note that ui::EF_ flags should 273 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. 274 // TODO(yusukes): Support native_event() on all platforms. 275 void ReleaseKey(ui::KeyboardCode key_code, int flags); 276 277 // Dispatch the event to the RootWindow. 278 void Dispatch(ui::Event* event); 279 280 void set_current_root_window(RootWindow* root_window) { 281 current_root_window_ = root_window; 282 } 283 284 private: 285 // Dispatch a key event to the RootWindow. 286 void DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags); 287 288 void UpdateCurrentRootWindow(const gfx::Point& point); 289 void PressButton(int flag); 290 void ReleaseButton(int flag); 291 292 // Convert a point between API's coordinates and 293 // |target|'s coordinates. 294 void ConvertPointFromTarget(const aura::Window* target, 295 gfx::Point* point) const; 296 void ConvertPointToTarget(const aura::Window* target, 297 gfx::Point* point) const; 298 299 gfx::Point GetLocationInCurrentRoot() const; 300 gfx::Point CenterOfWindow(const Window* window) const; 301 302 void DispatchNextPendingEvent(); 303 void DoDispatchEvent(ui::Event* event, bool async); 304 305 scoped_ptr<EventGeneratorDelegate> delegate_; 306 gfx::Point current_location_; 307 RootWindow* current_root_window_; 308 int flags_; 309 bool grab_; 310 std::list<ui::Event*> pending_events_; 311 // Set to true to cause events to be posted asynchronously. 312 bool async_; 313 314 DISALLOW_COPY_AND_ASSIGN(EventGenerator); 315 }; 316 317 } // namespace test 318 } // namespace aura 319 320 #endif // UI_AURA_TEST_EVENT_GENERATOR_H_ 321