• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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:
~EventGeneratorDelegate()45   virtual ~EventGeneratorDelegate() {}
46 
47   // Set the context of the delegate, whilst it is being used by an active
48   // EventGenerator.
SetContext(EventGenerator * owner,gfx::NativeWindow root_window,gfx::NativeWindow window)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.
set_current_location(const gfx::Point & location)124   void set_current_location(const gfx::Point& location) {
125     current_location_ = location;
126   }
current_location()127   const gfx::Point& current_location() const { return current_location_; }
128 
set_async(bool async)129   void set_async(bool async) { async_ = async; }
async()130   bool async() const { return async_; }
131 
132   // Resets the event flags bitmask.
set_flags(int flags)133   void set_flags(int flags) { 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);
MoveMouseToInHost(int x,int y)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);
MoveMouseTo(const gfx::Point & point_in_screen)170   void MoveMouseTo(const gfx::Point& point_in_screen) {
171     MoveMouseTo(point_in_screen, 1);
172   }
MoveMouseTo(int x,int y)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);
MoveMouseRelativeTo(const EventTarget * window,int x,int y)180   void MoveMouseRelativeTo(const EventTarget* window, int x, int y) {
181     MoveMouseRelativeTo(window, gfx::Point(x, y));
182   }
183 
MoveMouseBy(int x,int y)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 
DragMouseTo(int x,int y)191   void DragMouseTo(int x, int y) {
192     DragMouseTo(gfx::Point(x, y));
193   }
194 
DragMouseBy(int dx,int dy)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 
PressMoveAndReleaseTouchTo(int x,int y)224   void PressMoveAndReleaseTouchTo(int x, int y) {
225     PressMoveAndReleaseTouchTo(gfx::Point(x, y));
226   }
227 
PressMoveAndReleaseTouchBy(int x,int y)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 
set_current_target(EventTarget * target)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