OLD | NEW |
(Empty) | |
| 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/geometry/point.h" |
| 18 #include "ui/gfx/native_widget_types.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: |
| 45 virtual ~EventGeneratorDelegate() {} |
| 46 |
| 47 // Set the context of the delegate, whilst it is being used by an active |
| 48 // EventGenerator. |
| 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. |
| 124 void set_current_location(const gfx::Point& location) { |
| 125 current_location_ = location; |
| 126 } |
| 127 const gfx::Point& current_location() const { return current_location_; } |
| 128 |
| 129 void set_async(bool async) { async_ = async; } |
| 130 bool async() const { return async_; } |
| 131 |
| 132 // Dispatch events through the application instead of directly to the |
| 133 // target window. Currently only supported on Mac. |
| 134 void set_targeting_application(bool targeting_application) { |
| 135 targeting_application_ = targeting_application; |
| 136 } |
| 137 bool targeting_application() const { return targeting_application_; } |
| 138 |
| 139 // Resets the event flags bitmask. |
| 140 void set_flags(int flags) { flags_ = flags; } |
| 141 int flags() const { return flags_; } |
| 142 |
| 143 // Generates a left button press event. |
| 144 void PressLeftButton(); |
| 145 |
| 146 // Generates a left button release event. |
| 147 void ReleaseLeftButton(); |
| 148 |
| 149 // Generates events to click (press, release) left button. |
| 150 void ClickLeftButton(); |
| 151 |
| 152 // Generates a double click event using the left button. |
| 153 void DoubleClickLeftButton(); |
| 154 |
| 155 // Generates a right button press event. |
| 156 void PressRightButton(); |
| 157 |
| 158 // Generates a right button release event. |
| 159 void ReleaseRightButton(); |
| 160 |
| 161 // Moves the mouse wheel by |delta_x|, |delta_y|. |
| 162 void MoveMouseWheel(int delta_x, int delta_y); |
| 163 |
| 164 // Generates a mouse exit. |
| 165 void SendMouseExit(); |
| 166 |
| 167 // Generates events to move mouse to be the given |point| in the |
| 168 // |current_root_window_|'s host window coordinates. |
| 169 void MoveMouseToInHost(const gfx::Point& point_in_host); |
| 170 void MoveMouseToInHost(int x, int y) { |
| 171 MoveMouseToInHost(gfx::Point(x, y)); |
| 172 } |
| 173 |
| 174 // Generates events to move mouse to be the given |point| in screen |
| 175 // coordinates. |
| 176 void MoveMouseTo(const gfx::Point& point_in_screen, int count); |
| 177 void MoveMouseTo(const gfx::Point& point_in_screen) { |
| 178 MoveMouseTo(point_in_screen, 1); |
| 179 } |
| 180 void MoveMouseTo(int x, int y) { |
| 181 MoveMouseTo(gfx::Point(x, y)); |
| 182 } |
| 183 |
| 184 // Generates events to move mouse to be the given |point| in |window|'s |
| 185 // coordinates. |
| 186 void MoveMouseRelativeTo(const EventTarget* window, const gfx::Point& point); |
| 187 void MoveMouseRelativeTo(const EventTarget* window, int x, int y) { |
| 188 MoveMouseRelativeTo(window, gfx::Point(x, y)); |
| 189 } |
| 190 |
| 191 void MoveMouseBy(int x, int y) { |
| 192 MoveMouseTo(current_location_ + gfx::Vector2d(x, y)); |
| 193 } |
| 194 |
| 195 // Generates events to drag mouse to given |point|. |
| 196 void DragMouseTo(const gfx::Point& point); |
| 197 |
| 198 void DragMouseTo(int x, int y) { |
| 199 DragMouseTo(gfx::Point(x, y)); |
| 200 } |
| 201 |
| 202 void DragMouseBy(int dx, int dy) { |
| 203 DragMouseTo(current_location_ + gfx::Vector2d(dx, dy)); |
| 204 } |
| 205 |
| 206 // Generates events to move the mouse to the center of the window. |
| 207 void MoveMouseToCenterOf(EventTarget* window); |
| 208 |
| 209 // Generates a touch press event. |
| 210 void PressTouch(); |
| 211 |
| 212 // Generates a touch press event with |touch_id|. |
| 213 void PressTouchId(int touch_id); |
| 214 |
| 215 // Generates a ET_TOUCH_MOVED event to |point|. |
| 216 void MoveTouch(const gfx::Point& point); |
| 217 |
| 218 // Generates a ET_TOUCH_MOVED event to |point| with |touch_id|. |
| 219 void MoveTouchId(const gfx::Point& point, int touch_id); |
| 220 |
| 221 // Generates a touch release event. |
| 222 void ReleaseTouch(); |
| 223 |
| 224 // Generates a touch release event with |touch_id|. |
| 225 void ReleaseTouchId(int touch_id); |
| 226 |
| 227 // Generates press, move and release event to move touch |
| 228 // to be the given |point|. |
| 229 void PressMoveAndReleaseTouchTo(const gfx::Point& point); |
| 230 |
| 231 void PressMoveAndReleaseTouchTo(int x, int y) { |
| 232 PressMoveAndReleaseTouchTo(gfx::Point(x, y)); |
| 233 } |
| 234 |
| 235 void PressMoveAndReleaseTouchBy(int x, int y) { |
| 236 PressMoveAndReleaseTouchTo(current_location_ + gfx::Vector2d(x, y)); |
| 237 } |
| 238 |
| 239 // Generates press, move and release events to move touch |
| 240 // to the center of the window. |
| 241 void PressMoveAndReleaseTouchToCenterOf(EventTarget* window); |
| 242 |
| 243 // Generates and dispatches a Win8 edge-swipe event (swipe up from bottom or |
| 244 // swipe down from top). Note that it is not possible to distinguish between |
| 245 // the two edges with this event. |
| 246 void GestureEdgeSwipe(); |
| 247 |
| 248 // Generates and dispatches touch-events required to generate a TAP gesture. |
| 249 // Note that this can generate a number of other gesture events at the same |
| 250 // time (e.g. GESTURE_BEGIN, TAP_DOWN, END). |
| 251 void GestureTapAt(const gfx::Point& point); |
| 252 |
| 253 // Generates press and release touch-events to generate a TAP_DOWN event, but |
| 254 // without generating any scroll or tap events. This can also generate a few |
| 255 // other gesture events (e.g. GESTURE_BEGIN, END). |
| 256 void GestureTapDownAndUp(const gfx::Point& point); |
| 257 |
| 258 // Calculates a time duration that can be used with the given |start|, |end|, |
| 259 // and |steps| values when calling GestureScrollSequence (or |
| 260 // GestureScrollSequenceWithCallback) to achieve the given |velocity|. |
| 261 base::TimeDelta CalculateScrollDurationForFlingVelocity( |
| 262 const gfx::Point& start, |
| 263 const gfx::Point& end, |
| 264 float velocity, |
| 265 int steps); |
| 266 |
| 267 // Generates press, move, release touch-events to generate a sequence of |
| 268 // scroll events. |duration| and |steps| affect the velocity of the scroll, |
| 269 // and depending on these values, this may also generate FLING scroll |
| 270 // gestures. If velocity/fling is irrelevant for the test, then any non-zero |
| 271 // values for these should be sufficient. |
| 272 void GestureScrollSequence(const gfx::Point& start, |
| 273 const gfx::Point& end, |
| 274 const base::TimeDelta& duration, |
| 275 int steps); |
| 276 |
| 277 // The same as GestureScrollSequence(), with the exception that |callback| is |
| 278 // called at each step of the scroll sequence. |callback| is called at the |
| 279 // start of the sequence with ET_GESTURE_SCROLL_BEGIN, followed by one or more |
| 280 // ET_GESTURE_SCROLL_UPDATE and ends with an ET_GESTURE_SCROLL_END. |
| 281 void GestureScrollSequenceWithCallback(const gfx::Point& start, |
| 282 const gfx::Point& end, |
| 283 const base::TimeDelta& duration, |
| 284 int steps, |
| 285 const ScrollStepCallback& callback); |
| 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. |steps| and |event_separation_time_ms| are |
| 291 // relevant when testing velocity/fling/swipe, otherwise these can be any |
| 292 // non-zero value. |delta_x| and |delta_y| are the amount that each finger |
| 293 // should be moved. Internally calls GestureMultiFingerScrollWithDelays |
| 294 // with zeros as |delay_adding_finger_ms| forcing all touch down events to be |
| 295 // immediate. |
| 296 void GestureMultiFingerScroll(int count, |
| 297 const gfx::Point start[], |
| 298 int event_separation_time_ms, |
| 299 int steps, |
| 300 int move_x, |
| 301 int move_y); |
| 302 |
| 303 // Generates press, move, release touch-events to generate a sequence of |
| 304 // multi-finger scroll events. |count| specifies the number of touch-points |
| 305 // that should generate the scroll events. |start| are the starting positions |
| 306 // of all the touch points. |delay_adding_finger_ms| are delays in ms from the |
| 307 // starting time till touching down of each finger. |delay_adding_finger_ms| |
| 308 // is useful when testing complex gestures that start with 1 or 2 fingers and |
| 309 // add fingers with a delay. |steps| and |event_separation_time_ms| are |
| 310 // relevant when testing velocity/fling/swipe, otherwise these can be any |
| 311 // non-zero value. |delta_x| and |delta_y| are the amount that each finger |
| 312 // should be moved. |
| 313 void GestureMultiFingerScrollWithDelays(int count, |
| 314 const gfx::Point start[], |
| 315 const int delay_adding_finger_ms[], |
| 316 int event_separation_time_ms, |
| 317 int steps, |
| 318 int move_x, |
| 319 int move_y); |
| 320 |
| 321 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with |
| 322 // constant deltas to |x_offset| and |y_offset| in |steps|. |
| 323 void ScrollSequence(const gfx::Point& start, |
| 324 const base::TimeDelta& step_delay, |
| 325 float x_offset, |
| 326 float y_offset, |
| 327 int steps, |
| 328 int num_fingers); |
| 329 |
| 330 // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, sending |
| 331 // scrolls of each of the values in |offsets|. |
| 332 void ScrollSequence(const gfx::Point& start, |
| 333 const base::TimeDelta& step_delay, |
| 334 const std::vector<gfx::PointF>& offsets, |
| 335 int num_fingers); |
| 336 |
| 337 // Generates a key press event. On platforms except Windows and X11, a key |
| 338 // event without native_event() is generated. Note that ui::EF_ flags should |
| 339 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. |
| 340 // TODO(yusukes): Support native_event() on all platforms. |
| 341 void PressKey(KeyboardCode key_code, int flags); |
| 342 |
| 343 // Generates a key release event. On platforms except Windows and X11, a key |
| 344 // event without native_event() is generated. Note that ui::EF_ flags should |
| 345 // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>. |
| 346 // TODO(yusukes): Support native_event() on all platforms. |
| 347 void ReleaseKey(KeyboardCode key_code, int flags); |
| 348 |
| 349 // Dispatch the event to the WindowEventDispatcher. |
| 350 void Dispatch(Event* event); |
| 351 |
| 352 void set_current_target(EventTarget* target) { |
| 353 current_target_ = target; |
| 354 } |
| 355 |
| 356 // Specify an alternative tick clock to be used for simulating time in tests. |
| 357 void SetTickClock(scoped_ptr<base::TickClock> tick_clock); |
| 358 |
| 359 // Get the current time from the tick clock. |
| 360 base::TimeDelta Now(); |
| 361 |
| 362 // Default delegate set by a platform-specific GeneratorDelegate singleton. |
| 363 static EventGeneratorDelegate* default_delegate; |
| 364 |
| 365 private: |
| 366 // Set up the test context using the delegate. |
| 367 void Init(gfx::NativeWindow root_window, gfx::NativeWindow window_context); |
| 368 |
| 369 // Dispatch a key event to the WindowEventDispatcher. |
| 370 void DispatchKeyEvent(bool is_press, KeyboardCode key_code, int flags); |
| 371 |
| 372 void UpdateCurrentDispatcher(const gfx::Point& point); |
| 373 void PressButton(int flag); |
| 374 void ReleaseButton(int flag); |
| 375 |
| 376 gfx::Point GetLocationInCurrentRoot() const; |
| 377 gfx::Point CenterOfWindow(const EventTarget* window) const; |
| 378 |
| 379 void DispatchNextPendingEvent(); |
| 380 void DoDispatchEvent(Event* event, bool async); |
| 381 |
| 382 const EventGeneratorDelegate* delegate() const; |
| 383 EventGeneratorDelegate* delegate(); |
| 384 |
| 385 scoped_ptr<EventGeneratorDelegate> delegate_; |
| 386 gfx::Point current_location_; |
| 387 EventTarget* current_target_; |
| 388 int flags_; |
| 389 bool grab_; |
| 390 std::list<Event*> pending_events_; |
| 391 // Set to true to cause events to be posted asynchronously. |
| 392 bool async_; |
| 393 bool targeting_application_; |
| 394 scoped_ptr<base::TickClock> tick_clock_; |
| 395 |
| 396 DISALLOW_COPY_AND_ASSIGN(EventGenerator); |
| 397 }; |
| 398 |
| 399 } // namespace test |
| 400 } // namespace ui |
| 401 |
| 402 #endif // UI_EVENTS_TEST_EVENT_GENERATOR_H_ |
OLD | NEW |