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(¤t_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, ¢er);
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