• 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 #include "ui/aura/test/event_generator.h"
6 
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "ui/aura/client/screen_position_client.h"
11 #include "ui/aura/root_window.h"
12 #include "ui/events/event.h"
13 #include "ui/events/event_utils.h"
14 #include "ui/gfx/vector2d_conversions.h"
15 
16 #if defined(USE_X11)
17 #include <X11/Xlib.h>
18 #include "ui/base/x/x11_util.h"
19 #endif
20 
21 #if defined(OS_WIN)
22 #include "ui/events/keycodes/keyboard_code_conversion.h"
23 #endif
24 
25 namespace aura {
26 namespace test {
27 namespace {
28 
DummyCallback(ui::EventType,const gfx::Vector2dF &)29 void DummyCallback(ui::EventType, const gfx::Vector2dF&) {
30 }
31 
32 class DefaultEventGeneratorDelegate : public EventGeneratorDelegate {
33  public:
DefaultEventGeneratorDelegate(Window * root_window)34   explicit DefaultEventGeneratorDelegate(Window* root_window)
35       : root_window_(root_window) {}
~DefaultEventGeneratorDelegate()36   virtual ~DefaultEventGeneratorDelegate() {}
37 
38   // EventGeneratorDelegate overrides:
GetRootWindowAt(const gfx::Point & point) const39   virtual RootWindow* GetRootWindowAt(const gfx::Point& point) const OVERRIDE {
40     return root_window_->GetDispatcher();
41   }
42 
GetScreenPositionClient(const aura::Window * window) const43   virtual client::ScreenPositionClient* GetScreenPositionClient(
44       const aura::Window* window) const OVERRIDE {
45     return NULL;
46   }
47 
48  private:
49   Window* root_window_;
50 
51   DISALLOW_COPY_AND_ASSIGN(DefaultEventGeneratorDelegate);
52 };
53 
54 class TestKeyEvent : public ui::KeyEvent {
55  public:
TestKeyEvent(const base::NativeEvent & native_event,int flags,bool is_char)56   TestKeyEvent(const base::NativeEvent& native_event, int flags, bool is_char)
57       : KeyEvent(native_event, is_char) {
58     set_flags(flags);
59   }
60 };
61 
62 class TestTouchEvent : public ui::TouchEvent {
63  public:
TestTouchEvent(ui::EventType type,const gfx::Point & root_location,int touch_id,int flags)64   TestTouchEvent(ui::EventType type,
65                  const gfx::Point& root_location,
66                  int touch_id,
67                  int flags)
68       : TouchEvent(type, root_location, flags, touch_id, ui::EventTimeForNow(),
69                    1.0f, 1.0f, 1.0f, 1.0f) {
70   }
71 
72  private:
73   DISALLOW_COPY_AND_ASSIGN(TestTouchEvent);
74 };
75 
76 const int kAllButtonMask = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON;
77 
78 }  // namespace
79 
EventGenerator(Window * root_window)80 EventGenerator::EventGenerator(Window* root_window)
81     : delegate_(new DefaultEventGeneratorDelegate(root_window)),
82       current_root_window_(delegate_->GetRootWindowAt(current_location_)),
83       flags_(0),
84       grab_(false),
85       async_(false) {
86 }
87 
EventGenerator(Window * root_window,const gfx::Point & point)88 EventGenerator::EventGenerator(Window* root_window, const gfx::Point& point)
89     : delegate_(new DefaultEventGeneratorDelegate(root_window)),
90       current_location_(point),
91       current_root_window_(delegate_->GetRootWindowAt(current_location_)),
92       flags_(0),
93       grab_(false),
94       async_(false) {
95 }
96 
EventGenerator(Window * root_window,Window * window)97 EventGenerator::EventGenerator(Window* root_window, Window* window)
98     : delegate_(new DefaultEventGeneratorDelegate(root_window)),
99       current_location_(CenterOfWindow(window)),
100       current_root_window_(delegate_->GetRootWindowAt(current_location_)),
101       flags_(0),
102       grab_(false),
103       async_(false) {
104 }
105 
EventGenerator(EventGeneratorDelegate * delegate)106 EventGenerator::EventGenerator(EventGeneratorDelegate* delegate)
107     : delegate_(delegate),
108       current_root_window_(delegate_->GetRootWindowAt(current_location_)),
109       flags_(0),
110       grab_(false),
111       async_(false) {
112 }
113 
~EventGenerator()114 EventGenerator::~EventGenerator() {
115   for (std::list<ui::Event*>::iterator i = pending_events_.begin();
116       i != pending_events_.end(); ++i)
117     delete *i;
118   pending_events_.clear();
119 }
120 
PressLeftButton()121 void EventGenerator::PressLeftButton() {
122   PressButton(ui::EF_LEFT_MOUSE_BUTTON);
123 }
124 
ReleaseLeftButton()125 void EventGenerator::ReleaseLeftButton() {
126   ReleaseButton(ui::EF_LEFT_MOUSE_BUTTON);
127 }
128 
ClickLeftButton()129 void EventGenerator::ClickLeftButton() {
130   PressLeftButton();
131   ReleaseLeftButton();
132 }
133 
DoubleClickLeftButton()134 void EventGenerator::DoubleClickLeftButton() {
135   flags_ |= ui::EF_IS_DOUBLE_CLICK;
136   PressLeftButton();
137   flags_ ^= ui::EF_IS_DOUBLE_CLICK;
138   ReleaseLeftButton();
139 }
140 
PressRightButton()141 void EventGenerator::PressRightButton() {
142   PressButton(ui::EF_RIGHT_MOUSE_BUTTON);
143 }
144 
ReleaseRightButton()145 void EventGenerator::ReleaseRightButton() {
146   ReleaseButton(ui::EF_RIGHT_MOUSE_BUTTON);
147 }
148 
SendMouseExit()149 void EventGenerator::SendMouseExit() {
150   gfx::Point exit_location(current_location_);
151   ConvertPointToTarget(current_root_window_->window(), &exit_location);
152   ui::MouseEvent mouseev(ui::ET_MOUSE_EXITED, exit_location, exit_location,
153                          flags_);
154   Dispatch(&mouseev);
155 }
156 
MoveMouseToInHost(const gfx::Point & point_in_host)157 void EventGenerator::MoveMouseToInHost(const gfx::Point& point_in_host) {
158   const ui::EventType event_type = (flags_ & ui::EF_LEFT_MOUSE_BUTTON) ?
159       ui::ET_MOUSE_DRAGGED : ui::ET_MOUSE_MOVED;
160   ui::MouseEvent mouseev(event_type, point_in_host, point_in_host, flags_);
161   Dispatch(&mouseev);
162 
163   current_location_ = point_in_host;
164   current_root_window_->ConvertPointFromHost(&current_location_);
165 }
166 
MoveMouseTo(const gfx::Point & point_in_screen,int count)167 void EventGenerator::MoveMouseTo(const gfx::Point& point_in_screen,
168                                  int count) {
169   DCHECK_GT(count, 0);
170   const ui::EventType event_type = (flags_ & ui::EF_LEFT_MOUSE_BUTTON) ?
171       ui::ET_MOUSE_DRAGGED : ui::ET_MOUSE_MOVED;
172 
173   gfx::Vector2dF diff(point_in_screen - current_location_);
174   for (float i = 1; i <= count; i++) {
175     gfx::Vector2dF step(diff);
176     step.Scale(i / count);
177     gfx::Point move_point = current_location_ + gfx::ToRoundedVector2d(step);
178     if (!grab_)
179       UpdateCurrentRootWindow(move_point);
180     ConvertPointToTarget(current_root_window_->window(), &move_point);
181     ui::MouseEvent mouseev(event_type, move_point, move_point, flags_);
182     Dispatch(&mouseev);
183   }
184   current_location_ = point_in_screen;
185 }
186 
MoveMouseRelativeTo(const Window * window,const gfx::Point & point_in_parent)187 void EventGenerator::MoveMouseRelativeTo(const Window* window,
188                                          const gfx::Point& point_in_parent) {
189   gfx::Point point(point_in_parent);
190   ConvertPointFromTarget(window, &point);
191   MoveMouseTo(point);
192 }
193 
DragMouseTo(const gfx::Point & point)194 void EventGenerator::DragMouseTo(const gfx::Point& point) {
195   PressLeftButton();
196   MoveMouseTo(point);
197   ReleaseLeftButton();
198 }
199 
MoveMouseToCenterOf(Window * window)200 void EventGenerator::MoveMouseToCenterOf(Window* window) {
201   MoveMouseTo(CenterOfWindow(window));
202 }
203 
PressTouch()204 void EventGenerator::PressTouch() {
205   PressTouchId(0);
206 }
207 
PressTouchId(int touch_id)208 void EventGenerator::PressTouchId(int touch_id) {
209   TestTouchEvent touchev(
210       ui::ET_TOUCH_PRESSED, GetLocationInCurrentRoot(), touch_id, flags_);
211   Dispatch(&touchev);
212 }
213 
MoveTouch(const gfx::Point & point)214 void EventGenerator::MoveTouch(const gfx::Point& point) {
215   MoveTouchId(point, 0);
216 }
217 
MoveTouchId(const gfx::Point & point,int touch_id)218 void EventGenerator::MoveTouchId(const gfx::Point& point, int touch_id) {
219   current_location_ = point;
220   TestTouchEvent touchev(
221       ui::ET_TOUCH_MOVED, GetLocationInCurrentRoot(), touch_id, flags_);
222   Dispatch(&touchev);
223 
224   if (!grab_)
225     UpdateCurrentRootWindow(point);
226 }
227 
ReleaseTouch()228 void EventGenerator::ReleaseTouch() {
229   ReleaseTouchId(0);
230 }
231 
ReleaseTouchId(int touch_id)232 void EventGenerator::ReleaseTouchId(int touch_id) {
233   TestTouchEvent touchev(
234       ui::ET_TOUCH_RELEASED, GetLocationInCurrentRoot(), touch_id, flags_);
235   Dispatch(&touchev);
236 }
237 
PressMoveAndReleaseTouchTo(const gfx::Point & point)238 void EventGenerator::PressMoveAndReleaseTouchTo(const gfx::Point& point) {
239   PressTouch();
240   MoveTouch(point);
241   ReleaseTouch();
242 }
243 
PressMoveAndReleaseTouchToCenterOf(Window * window)244 void EventGenerator::PressMoveAndReleaseTouchToCenterOf(Window* window) {
245   PressMoveAndReleaseTouchTo(CenterOfWindow(window));
246 }
247 
GestureTapAt(const gfx::Point & location)248 void EventGenerator::GestureTapAt(const gfx::Point& location) {
249   const int kTouchId = 2;
250   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
251                        location,
252                        kTouchId,
253                        ui::EventTimeForNow());
254   Dispatch(&press);
255 
256   ui::TouchEvent release(
257       ui::ET_TOUCH_RELEASED, location, kTouchId,
258       press.time_stamp() + base::TimeDelta::FromMilliseconds(50));
259   Dispatch(&release);
260 }
261 
GestureTapDownAndUp(const gfx::Point & location)262 void EventGenerator::GestureTapDownAndUp(const gfx::Point& location) {
263   const int kTouchId = 3;
264   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
265                        location,
266                        kTouchId,
267                        ui::EventTimeForNow());
268   Dispatch(&press);
269 
270   ui::TouchEvent release(
271       ui::ET_TOUCH_RELEASED, location, kTouchId,
272       press.time_stamp() + base::TimeDelta::FromMilliseconds(1000));
273   Dispatch(&release);
274 }
275 
GestureScrollSequence(const gfx::Point & start,const gfx::Point & end,const base::TimeDelta & step_delay,int steps)276 void EventGenerator::GestureScrollSequence(const gfx::Point& start,
277                                            const gfx::Point& end,
278                                            const base::TimeDelta& step_delay,
279                                            int steps) {
280   GestureScrollSequenceWithCallback(start, end, step_delay, steps,
281                                     base::Bind(&DummyCallback));
282 }
283 
GestureScrollSequenceWithCallback(const gfx::Point & start,const gfx::Point & end,const base::TimeDelta & step_delay,int steps,const ScrollStepCallback & callback)284 void EventGenerator::GestureScrollSequenceWithCallback(
285     const gfx::Point& start,
286     const gfx::Point& end,
287     const base::TimeDelta& step_delay,
288     int steps,
289     const ScrollStepCallback& callback) {
290   const int kTouchId = 5;
291   base::TimeDelta timestamp = ui::EventTimeForNow();
292   ui::TouchEvent press(ui::ET_TOUCH_PRESSED, start, kTouchId, timestamp);
293   Dispatch(&press);
294 
295   callback.Run(ui::ET_GESTURE_SCROLL_BEGIN, gfx::Vector2dF());
296 
297   int dx = (end.x() - start.x()) / steps;
298   int dy = (end.y() - start.y()) / steps;
299   gfx::Point location = start;
300   for (int i = 0; i < steps; ++i) {
301     location.Offset(dx, dy);
302     timestamp += step_delay;
303     ui::TouchEvent move(ui::ET_TOUCH_MOVED, location, kTouchId, timestamp);
304     Dispatch(&move);
305     callback.Run(ui::ET_GESTURE_SCROLL_UPDATE, gfx::Vector2dF(dx, dy));
306   }
307 
308   ui::TouchEvent release(ui::ET_TOUCH_RELEASED, end, kTouchId, timestamp);
309   Dispatch(&release);
310 
311   callback.Run(ui::ET_GESTURE_SCROLL_END, gfx::Vector2dF());
312 }
313 
GestureMultiFingerScroll(int count,const gfx::Point start[],int event_separation_time_ms,int steps,int move_x,int move_y)314 void EventGenerator::GestureMultiFingerScroll(int count,
315                                               const gfx::Point start[],
316                                               int event_separation_time_ms,
317                                               int steps,
318                                               int move_x,
319                                               int move_y) {
320   const int kMaxTouchPoints = 10;
321   int delays[kMaxTouchPoints] = { 0 };
322   GestureMultiFingerScrollWithDelays(
323       count, start, delays, event_separation_time_ms, steps, move_x, move_y);
324 }
325 
GestureMultiFingerScrollWithDelays(int count,const gfx::Point start[],const int delay_adding_finger_ms[],int event_separation_time_ms,int steps,int move_x,int move_y)326 void EventGenerator::GestureMultiFingerScrollWithDelays(
327     int count,
328     const gfx::Point start[],
329     const int delay_adding_finger_ms[],
330     int event_separation_time_ms,
331     int steps,
332     int move_x,
333     int move_y) {
334   const int kMaxTouchPoints = 10;
335   gfx::Point points[kMaxTouchPoints];
336   CHECK_LE(count, kMaxTouchPoints);
337   CHECK_GT(steps, 0);
338 
339   int delta_x = move_x / steps;
340   int delta_y = move_y / steps;
341 
342   for (int i = 0; i < count; ++i) {
343     points[i] = start[i];
344   }
345 
346   base::TimeDelta press_time_first = ui::EventTimeForNow();
347   base::TimeDelta press_time[kMaxTouchPoints];
348   bool pressed[kMaxTouchPoints];
349   for (int i = 0; i < count; ++i) {
350     pressed[i] = false;
351     press_time[i] = press_time_first +
352         base::TimeDelta::FromMilliseconds(delay_adding_finger_ms[i]);
353   }
354 
355   int last_id = 0;
356   for (int step = 0; step < steps; ++step) {
357     base::TimeDelta move_time = press_time_first +
358         base::TimeDelta::FromMilliseconds(event_separation_time_ms * step);
359 
360     while (last_id < count &&
361            !pressed[last_id] &&
362            move_time >= press_time[last_id]) {
363       ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
364                            points[last_id],
365                            last_id,
366                            press_time[last_id]);
367       Dispatch(&press);
368       pressed[last_id] = true;
369       last_id++;
370     }
371 
372     for (int i = 0; i < count; ++i) {
373       points[i].Offset(delta_x, delta_y);
374       if (i >= last_id)
375         continue;
376       ui::TouchEvent move(ui::ET_TOUCH_MOVED, points[i], i, move_time);
377       Dispatch(&move);
378     }
379   }
380 
381   base::TimeDelta release_time = press_time_first +
382       base::TimeDelta::FromMilliseconds(event_separation_time_ms * steps);
383   for (int i = 0; i < last_id; ++i) {
384     ui::TouchEvent release(
385         ui::ET_TOUCH_RELEASED, points[i], i, release_time);
386     Dispatch(&release);
387   }
388 }
389 
ScrollSequence(const gfx::Point & start,const base::TimeDelta & step_delay,float x_offset,float y_offset,int steps,int num_fingers)390 void EventGenerator::ScrollSequence(const gfx::Point& start,
391                                     const base::TimeDelta& step_delay,
392                                     float x_offset,
393                                     float y_offset,
394                                     int steps,
395                                     int num_fingers) {
396   base::TimeDelta timestamp = base::TimeDelta::FromInternalValue(
397       base::TimeTicks::Now().ToInternalValue());
398   ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
399                                start,
400                                timestamp,
401                                0,
402                                0, 0,
403                                0, 0,
404                                num_fingers);
405   Dispatch(&fling_cancel);
406 
407   float dx = x_offset / steps;
408   float dy = y_offset / steps;
409   for (int i = 0; i < steps; ++i) {
410     timestamp += step_delay;
411     ui::ScrollEvent move(ui::ET_SCROLL,
412                          start,
413                          timestamp,
414                          0,
415                          dx, dy,
416                          dx, dy,
417                          num_fingers);
418     Dispatch(&move);
419   }
420 
421   ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START,
422                               start,
423                               timestamp,
424                               0,
425                               x_offset, y_offset,
426                               x_offset, y_offset,
427                               num_fingers);
428   Dispatch(&fling_start);
429 }
430 
ScrollSequence(const gfx::Point & start,const base::TimeDelta & step_delay,const std::vector<gfx::Point> & offsets,int num_fingers)431 void EventGenerator::ScrollSequence(const gfx::Point& start,
432                                     const base::TimeDelta& step_delay,
433                                     const std::vector<gfx::Point>& offsets,
434                                     int num_fingers) {
435   int steps = offsets.size();
436   base::TimeDelta timestamp = ui::EventTimeForNow();
437   ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
438                                start,
439                                timestamp,
440                                0,
441                                0, 0,
442                                0, 0,
443                                num_fingers);
444   Dispatch(&fling_cancel);
445 
446   for (int i = 0; i < steps; ++i) {
447     timestamp += step_delay;
448     ui::ScrollEvent scroll(ui::ET_SCROLL,
449                            start,
450                            timestamp,
451                            0,
452                            offsets[i].x(), offsets[i].y(),
453                            offsets[i].x(), offsets[i].y(),
454                            num_fingers);
455     Dispatch(&scroll);
456   }
457 
458   ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START,
459                               start,
460                               timestamp,
461                               0,
462                               offsets[steps - 1].x(), offsets[steps - 1].y(),
463                               offsets[steps - 1].x(), offsets[steps - 1].y(),
464                               num_fingers);
465   Dispatch(&fling_start);
466 }
467 
PressKey(ui::KeyboardCode key_code,int flags)468 void EventGenerator::PressKey(ui::KeyboardCode key_code, int flags) {
469   DispatchKeyEvent(true, key_code, flags);
470 }
471 
ReleaseKey(ui::KeyboardCode key_code,int flags)472 void EventGenerator::ReleaseKey(ui::KeyboardCode key_code, int flags) {
473   DispatchKeyEvent(false, key_code, flags);
474 }
475 
Dispatch(ui::Event * event)476 void EventGenerator::Dispatch(ui::Event* event) {
477   DoDispatchEvent(event, async_);
478 }
479 
DispatchKeyEvent(bool is_press,ui::KeyboardCode key_code,int flags)480 void EventGenerator::DispatchKeyEvent(bool is_press,
481                                       ui::KeyboardCode key_code,
482                                       int flags) {
483 #if defined(OS_WIN)
484   UINT key_press = WM_KEYDOWN;
485   uint16 character = ui::GetCharacterFromKeyCode(key_code, flags);
486   if (is_press && character) {
487     MSG native_event = { NULL, WM_KEYDOWN, key_code, 0 };
488     TestKeyEvent keyev(native_event, flags, false);
489     Dispatch(&keyev);
490     // On Windows, WM_KEYDOWN event is followed by WM_CHAR with a character
491     // if the key event cooresponds to a real character.
492     key_press = WM_CHAR;
493     key_code = static_cast<ui::KeyboardCode>(character);
494   }
495   MSG native_event =
496       { NULL, (is_press ? key_press : WM_KEYUP), key_code, 0 };
497   TestKeyEvent keyev(native_event, flags, key_press == WM_CHAR);
498 #else
499   ui::EventType type = is_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED;
500   ui::KeyEvent keyev(type, key_code, flags, false);
501 #endif  // OS_WIN
502   Dispatch(&keyev);
503 }
504 
UpdateCurrentRootWindow(const gfx::Point & point)505 void EventGenerator::UpdateCurrentRootWindow(const gfx::Point& point) {
506   current_root_window_ = delegate_->GetRootWindowAt(point);
507 }
508 
PressButton(int flag)509 void EventGenerator::PressButton(int flag) {
510   if (!(flags_ & flag)) {
511     flags_ |= flag;
512     grab_ = flags_ & kAllButtonMask;
513     gfx::Point location = GetLocationInCurrentRoot();
514     ui::MouseEvent mouseev(ui::ET_MOUSE_PRESSED, location, location, flags_);
515     Dispatch(&mouseev);
516   }
517 }
518 
ReleaseButton(int flag)519 void EventGenerator::ReleaseButton(int flag) {
520   if (flags_ & flag) {
521     gfx::Point location = GetLocationInCurrentRoot();
522     ui::MouseEvent mouseev(ui::ET_MOUSE_RELEASED, location,
523                            location, flags_);
524     Dispatch(&mouseev);
525     flags_ ^= flag;
526   }
527   grab_ = flags_ & kAllButtonMask;
528 }
529 
ConvertPointFromTarget(const aura::Window * target,gfx::Point * point) const530 void EventGenerator::ConvertPointFromTarget(const aura::Window* target,
531                                             gfx::Point* point) const {
532   DCHECK(point);
533   aura::client::ScreenPositionClient* client =
534       delegate_->GetScreenPositionClient(target);
535   if (client)
536     client->ConvertPointToScreen(target, point);
537   else
538     aura::Window::ConvertPointToTarget(target, target->GetRootWindow(), point);
539 }
540 
ConvertPointToTarget(const aura::Window * target,gfx::Point * point) const541 void EventGenerator::ConvertPointToTarget(const aura::Window* target,
542                                           gfx::Point* point) const {
543   DCHECK(point);
544   aura::client::ScreenPositionClient* client =
545       delegate_->GetScreenPositionClient(target);
546   if (client)
547     client->ConvertPointFromScreen(target, point);
548   else
549     aura::Window::ConvertPointToTarget(target->GetRootWindow(), target, point);
550 }
551 
GetLocationInCurrentRoot() const552 gfx::Point EventGenerator::GetLocationInCurrentRoot() const {
553   gfx::Point p(current_location_);
554   ConvertPointToTarget(current_root_window_->window(), &p);
555   return p;
556 }
557 
CenterOfWindow(const Window * window) const558 gfx::Point EventGenerator::CenterOfWindow(const Window* window) const {
559   gfx::Point center = gfx::Rect(window->bounds().size()).CenterPoint();
560   ConvertPointFromTarget(window, &center);
561   return center;
562 }
563 
DoDispatchEvent(ui::Event * event,bool async)564 void EventGenerator::DoDispatchEvent(ui::Event* event, bool async) {
565   if (async) {
566     ui::Event* pending_event;
567     if (event->IsKeyEvent()) {
568       pending_event = new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event));
569     } else if (event->IsMouseEvent()) {
570       pending_event = new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event));
571     } else if (event->IsTouchEvent()) {
572       pending_event = new ui::TouchEvent(*static_cast<ui::TouchEvent*>(event));
573     } else if (event->IsScrollEvent()) {
574       pending_event =
575           new ui::ScrollEvent(*static_cast<ui::ScrollEvent*>(event));
576     } else {
577       NOTREACHED() << "Invalid event type";
578       return;
579     }
580     if (pending_events_.empty()) {
581       base::MessageLoopProxy::current()->PostTask(
582           FROM_HERE,
583           base::Bind(&EventGenerator::DispatchNextPendingEvent,
584                      base::Unretained(this)));
585     }
586     pending_events_.push_back(pending_event);
587   } else {
588     RootWindowHostDelegate* root_window_host_delegate =
589         current_root_window_->AsRootWindowHostDelegate();
590     if (event->IsKeyEvent()) {
591       root_window_host_delegate->OnHostKeyEvent(
592           static_cast<ui::KeyEvent*>(event));
593     } else if (event->IsMouseEvent()) {
594       root_window_host_delegate->OnHostMouseEvent(
595           static_cast<ui::MouseEvent*>(event));
596     } else if (event->IsTouchEvent()) {
597       root_window_host_delegate->OnHostTouchEvent(
598           static_cast<ui::TouchEvent*>(event));
599     } else if (event->IsScrollEvent()) {
600       root_window_host_delegate->OnHostScrollEvent(
601           static_cast<ui::ScrollEvent*>(event));
602     } else {
603       NOTREACHED() << "Invalid event type";
604     }
605   }
606 }
607 
DispatchNextPendingEvent()608 void EventGenerator::DispatchNextPendingEvent() {
609   DCHECK(!pending_events_.empty());
610   ui::Event* event = pending_events_.front();
611   DoDispatchEvent(event, false);
612   pending_events_.pop_front();
613   delete event;
614   if (!pending_events_.empty()) {
615     base::MessageLoopProxy::current()->PostTask(
616         FROM_HERE,
617         base::Bind(&EventGenerator::DispatchNextPendingEvent,
618                    base::Unretained(this)));
619   }
620 }
621 
622 
623 }  // namespace test
624 }  // namespace aura
625