Home | History | Annotate | Download | only in test
      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:
     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   // 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