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
20namespace base {
21class TickClock;
22}
23
24namespace ui {
25class Event;
26class EventProcessor;
27class EventSource;
28class EventTarget;
29class KeyEvent;
30class MouseEvent;
31class ScrollEvent;
32class TouchEvent;
33
34namespace test {
35
36typedef base::Callback<void(EventType, const gfx::Vector2dF&)>
37        ScrollStepCallback;
38
39class EventGenerator;
40
41// A delegate interface for EventGenerator to abstract platform-specific event
42// targeting and coordinate conversion.
43class 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.
97class 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  // Resets the event flags bitmask.
133  void set_flags(int 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);
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);
170  void MoveMouseTo(const gfx::Point& point_in_screen) {
171    MoveMouseTo(point_in_screen, 1);
172  }
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);
180  void MoveMouseRelativeTo(const EventTarget* window, int x, int y) {
181    MoveMouseRelativeTo(window, gfx::Point(x, y));
182  }
183
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
191  void DragMouseTo(int x, int y) {
192    DragMouseTo(gfx::Point(x, y));
193  }
194
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
224  void PressMoveAndReleaseTouchTo(int x, int y) {
225    PressMoveAndReleaseTouchTo(gfx::Point(x, y));
226  }
227
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
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