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 "ui/base/events/event_constants.h"
     15 #include "ui/base/keycodes/keyboard_codes.h"
     16 #include "ui/gfx/point.h"
     17 
     18 namespace base {
     19 class TimeDelta;
     20 }
     21 
     22 namespace ui {
     23 class Event;
     24 class KeyEvent;
     25 class MouseEvent;
     26 class ScrollEvent;
     27 class TouchEvent;
     28 }
     29 
     30 namespace aura {
     31 class RootWindow;
     32 class Window;
     33 
     34 namespace client {
     35 class ScreenPositionClient;
     36 }
     37 
     38 namespace test {
     39 
     40 typedef base::Callback<void(ui::EventType, const gfx::Vector2dF&)>
     41         ScrollStepCallback;
     42 
     43 // A delegate interface for EventGenerator that provides a way to
     44 // locate aura root window for given point.
     45 class EventGeneratorDelegate {
     46  public:
     47   virtual ~EventGeneratorDelegate() {}
     48 
     49   // Returns a root window for given point.
     50   virtual RootWindow* GetRootWindowAt(const gfx::Point& point) const = 0;
     51 
     52   // Returns the screen position client that determines the
     53   // coordinates used in EventGenerator. EventGenerator uses
     54   // RootWindow's coordinate if this retruns NULL.
     55   virtual client::ScreenPositionClient* GetScreenPositionClient(
     56       const aura::Window* window) const = 0;
     57 };
     58 
     59 // EventGenerator is a tool that generates and dispatch events.
     60 // Unlike |ui_controls| package in ui/base/test, this does not
     61 // generate platform native events. Insetad, it directly posts event
     62 // to |aura::RootWindow| synchronously.
     63 
     64 // Advantage of using this class, compared to |ui_controls| is that
     65 // you can write the tests that involves events in synchronus
     66 // way. There is no need to wait for native
     67 //
     68 // On the other hand, this class is not suited for the following
     69 // cases:
     70 //
     71 // 1) If your test depends on native events (ui::Event::native_event()).
     72 //   This return is empty/NULL event with EventGenerator.
     73 // 2) If your test involves nested message loop, such as
     74 //    menu or drag & drop. Because this class directly
     75 //    post an event to RootWindow, this event will not be
     76 //    handled in the nested message loop.
     77 // 3) Similarly, |base::MessagePumpObserver| will not be invoked.
     78 // 4) Any other code that requires native events, such as
     79 //    tests for RootWindowHostWin/RootWindowHostX11.
     80 //
     81 // If one of these applies to your test, please use |ui_controls|
     82 // package instead.
     83 //
     84 // Note: The coordinates of the points in API is determined by the
     85 // EventGeneratorDelegate.
     86 class EventGenerator {
     87  public:
     88   // Creates an EventGenerator with the mouse/touch location (0,0),
     89   // which uses the |root_window|'s coordinates.
     90   explicit EventGenerator(RootWindow* root_window);
     91 
     92   // Create an EventGenerator with EventGeneratorDelegate,
     93   // which uses the coordinates used by |delegate|.
     94   explicit EventGenerator(EventGeneratorDelegate* delegate);
     95 
     96   // Creates an EventGenerator with the mouse/touch location
     97   // at |initial_location|, which uses the |root_window|'s coordinates.
     98   EventGenerator(RootWindow* root_window, const gfx::Point& initial_location);
     99 
    100   // Creates an EventGenerator with the mouse/touch location
    101   // centered over |window|, which uses the |root_window|'s coordinates.
    102   EventGenerator(RootWindow* root_window, Window* window);
    103 
    104   virtual ~EventGenerator();
    105 
    106   // Explicitly sets the location used by mouse/touch events. This is set by the
    107   // various methods that take a location but can be manipulated directly,
    108   // typically for touch.
    109   void set_current_location(const gfx::Point& location) {
    110     current_location_ = location;
    111   }
    112   const gfx::Point& current_location() const { return current_location_; }
    113 
    114   void set_async(bool async) { async_ = async; }
    115   bool async() const { return async_; }
    116 
    117   // Resets the event flags bitmask.
    118   void set_flags(int flags) { flags_ = flags; }
    119 
    120   // Generates a left button press event.
    121   void PressLeftButton();
    122 
    123   // Generates a left button release event.
    124   void ReleaseLeftButton();
    125 
    126   // Generates events to click (press, release) left button.
    127   void ClickLeftButton();
    128 
    129   // Generates a double click event using the left button.
    130   void DoubleClickLeftButton();
    131 
    132   // Generates a right button press event.
    133   void PressRightButton();
    134 
    135   // Generates a right button release event.
    136   void ReleaseRightButton();
    137 
    138   // Generates events to move mouse to be the given |point| in the
    139   // |current_root_window_|'s host window coordinates.
    140   void MoveMouseToInHost(const gfx::Point& point_in_host);
    141   void MoveMouseToInHost(int x, int y) {
    142     MoveMouseToInHost(gfx::Point(x, y));
    143   }
    144 
    145   // Generates events to move mouse to be the given |point| in screen
    146   // coordinates.
    147   void MoveMouseTo(const gfx::Point& point_in_screen, int count);
    148   void MoveMouseTo(const gfx::Point& point_in_screen) {
    149     MoveMouseTo(point_in_screen, 1);
    150   }
    151   void MoveMouseTo(int x, int y) {
    152     MoveMouseTo(gfx::Point(x, y));
    153   }
    154 
    155   // Generates events to move mouse to be the given |point| in |window|'s
    156   // coordinates.
    157   void MoveMouseRelativeTo(const Window* window, const gfx::Point& point);
    158   void MoveMouseRelativeTo(const Window* window, int x, int y) {
    159     MoveMouseRelativeTo(window, gfx::Point(x, y));
    160   }
    161 
    162   void MoveMouseBy(int x, int y) {
    163     MoveMouseTo(current_location_ + gfx::Vector2d(x, y));
    164   }
    165 
    166   // Generates events to drag mouse to given |point|.
    167   void DragMouseTo(const gfx::Point& point);
    168 
    169   void DragMouseTo(int x, int y) {
    170     DragMouseTo(gfx::Point(x, y));
    171   }
    172 
    173   void DragMouseBy(int dx, int dy) {
    174     DragMouseTo(current_location_ + gfx::Vector2d(dx, dy));
    175   }
    176 
    177   // Generates events to move the mouse to the center of the window.
    178   void MoveMouseToCenterOf(Window* window);
    179 
    180   // Generates a touch press event.
    181   void PressTouch();
    182 
    183   // Generates a ET_TOUCH_MOVED event to |point|.
    184   void MoveTouch(const gfx::Point& point);
    185 
    186   // Generates a touch release event.
    187   void ReleaseTouch();
    188 
    189   // Generates press, move and release event to move touch
    190   // to be the given |point|.
    191   void PressMoveAndReleaseTouchTo(const gfx::Point& point);
    192 
    193   void PressMoveAndReleaseTouchTo(int x, int y) {
    194     PressMoveAndReleaseTouchTo(gfx::Point(x, y));
    195   }
    196 
    197   void PressMoveAndReleaseTouchBy(int x, int y) {
    198     PressMoveAndReleaseTouchTo(current_location_ + gfx::Vector2d(x, y));
    199   }
    200 
    201   // Generates press, move and release events to move touch
    202   // to the center of the window.
    203   void PressMoveAndReleaseTouchToCenterOf(Window* window);
    204 
    205   // Generates and dispatches touch-events required to generate a TAP gesture.
    206   // Note that this can generate a number of other gesture events at the same
    207   // time (e.g. GESTURE_BEGIN, TAP_DOWN, END).
    208   void GestureTapAt(const gfx::Point& point);
    209 
    210   // Generates press and release touch-events to generate a TAP_DOWN event, but
    211   // without generating any scroll or tap events. This can also generate a few
    212   // other gesture events (e.g. GESTURE_BEGIN, END).
    213   void GestureTapDownAndUp(const gfx::Point& point);
    214 
    215   // Generates press, move, release touch-events to generate a sequence of
    216   // scroll events. |duration| and |steps| affect the velocity of the scroll,
    217   // and depending on these values, this may also generate FLING scroll
    218   // gestures. If velocity/fling is irrelevant for the test, then any non-zero
    219   // values for these should be sufficient.
    220   void GestureScrollSequence(const gfx::Point& start,
    221                              const gfx::Point& end,
    222                              const base::TimeDelta& duration,
    223                              int steps);
    224 
    225   // The same as GestureScrollSequence(), with the exception that |callback| is
    226   // called at each step of the scroll sequence. |callback| is called at the
    227   // start of the sequence with ET_GESTURE_SCROLL_BEGIN, followed by one or more
    228   // ET_GESTURE_SCROLL_UPDATE and ends with an ET_GESTURE_SCROLL_END.
    229   void GestureScrollSequenceWithCallback(const gfx::Point& start,
    230                                          const gfx::Point& end,
    231                                          const base::TimeDelta& duration,
    232                                          int steps,
    233                                          const ScrollStepCallback& callback);
    234 
    235   // Generates press, move, release touch-events to generate a sequence of
    236   // multi-finger scroll events. |count| specifies the number of touch-points
    237   // that should generate the scroll events. |start| are the starting positions
    238   // of all the touch points. |steps| and |event_separation_time_ms| are
    239   // relevant when testing velocity/fling/swipe, otherwise these can be any
    240   // non-zero value. |delta_x| and |delta_y| are the amount that each finger
    241   // should be moved.
    242   void GestureMultiFingerScroll(int count,
    243                                 const gfx::Point* start,
    244                                 int event_separation_time_ms,
    245                                 int steps,
    246                                 int move_x,
    247                                 int move_y);
    248 
    249   // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with
    250   // constant deltas to |x_offset| and |y_offset| in |steps|.
    251   void ScrollSequence(const gfx::Point& start,
    252                       const base::TimeDelta& step_delay,
    253                       float x_offset,
    254                       float y_offset,
    255                       int steps,
    256                       int num_fingers);
    257 
    258   // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, sending
    259   // scrolls of each of the values in |offsets|.
    260   void ScrollSequence(const gfx::Point& start,
    261                       const base::TimeDelta& step_delay,
    262                       const std::vector<gfx::Point>& offsets,
    263                       int num_fingers);
    264 
    265   // Generates a key press event. On platforms except Windows and X11, a key
    266   // event without native_event() is generated. Note that ui::EF_ flags should
    267   // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>.
    268   // TODO(yusukes): Support native_event() on all platforms.
    269   void PressKey(ui::KeyboardCode key_code, int flags);
    270 
    271   // Generates a key release event. On platforms except Windows and X11, a key
    272   // event without native_event() is generated. Note that ui::EF_ flags should
    273   // be passed as |flags|, not the native ones like 'ShiftMask' in <X11/X.h>.
    274   // TODO(yusukes): Support native_event() on all platforms.
    275   void ReleaseKey(ui::KeyboardCode key_code, int flags);
    276 
    277   // Dispatch the event to the RootWindow.
    278   void Dispatch(ui::Event* event);
    279 
    280   void set_current_root_window(RootWindow* root_window) {
    281     current_root_window_ = root_window;
    282   }
    283 
    284  private:
    285   // Dispatch a key event to the RootWindow.
    286   void DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags);
    287 
    288   void UpdateCurrentRootWindow(const gfx::Point& point);
    289   void PressButton(int flag);
    290   void ReleaseButton(int flag);
    291 
    292   // Convert a point between API's coordinates and
    293   // |target|'s coordinates.
    294   void ConvertPointFromTarget(const aura::Window* target,
    295                               gfx::Point* point) const;
    296   void ConvertPointToTarget(const aura::Window* target,
    297                             gfx::Point* point) const;
    298 
    299   gfx::Point GetLocationInCurrentRoot() const;
    300   gfx::Point CenterOfWindow(const Window* window) const;
    301 
    302   void DispatchNextPendingEvent();
    303   void DoDispatchEvent(ui::Event* event, bool async);
    304 
    305   scoped_ptr<EventGeneratorDelegate> delegate_;
    306   gfx::Point current_location_;
    307   RootWindow* current_root_window_;
    308   int flags_;
    309   bool grab_;
    310   std::list<ui::Event*> pending_events_;
    311   // Set to true to cause events to be posted asynchronously.
    312   bool async_;
    313 
    314   DISALLOW_COPY_AND_ASSIGN(EventGenerator);
    315 };
    316 
    317 }  // namespace test
    318 }  // namespace aura
    319 
    320 #endif  // UI_AURA_TEST_EVENT_GENERATOR_H_
    321