Home | History | Annotate | Download | only in test
      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:
     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.
    106   void set_current_location(const gfx::Point& location) {
    107     current_location_ = location;
    108   }
    109   const gfx::Point& current_location() const { return current_location_; }
    110 
    111   void set_async(bool async) { async_ = async; }
    112   bool async() const { return async_; }
    113 
    114   // Resets the event flags bitmask.
    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);
    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);
    151   void MoveMouseTo(const gfx::Point& point_in_screen) {
    152     MoveMouseTo(point_in_screen, 1);
    153   }
    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);
    161   void MoveMouseRelativeTo(const Window* window, int x, int y) {
    162     MoveMouseRelativeTo(window, gfx::Point(x, y));
    163   }
    164 
    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 
    172   void DragMouseTo(int x, int y) {
    173     DragMouseTo(gfx::Point(x, y));
    174   }
    175 
    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 
    205   void PressMoveAndReleaseTouchTo(int x, int y) {
    206     PressMoveAndReleaseTouchTo(gfx::Point(x, y));
    207   }
    208 
    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 
    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