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