Update V8 to version 4.7.16.
[chromium-blink-merge.git] / ui / events / test / event_generator.cc
blob6e619d0d71128bed66c474edfeb8b5f4347f50a3
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.
5 #include "ui/events/test/event_generator.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/time/tick_clock.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_source.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/events/test/events_test_utils.h"
17 #include "ui/gfx/geometry/vector2d_conversions.h"
19 #if defined(USE_X11)
20 #include <X11/Xlib.h>
21 #include "ui/events/test/events_test_utils_x11.h"
22 #endif
24 #if defined(OS_WIN)
25 #include "ui/events/keycodes/keyboard_code_conversion.h"
26 #endif
28 namespace ui {
29 namespace test {
30 namespace {
32 void DummyCallback(EventType, const gfx::Vector2dF&) {
35 class TestTickClock : public base::TickClock {
36 public:
37 // Starts off with a clock set to TimeTicks().
38 TestTickClock() {}
40 base::TimeTicks NowTicks() override {
41 return base::TimeTicks::FromInternalValue(ticks_++ * 1000);
44 private:
45 int64 ticks_ = 1;
47 DISALLOW_COPY_AND_ASSIGN(TestTickClock);
50 class TestKeyEvent : public ui::KeyEvent {
51 public:
52 TestKeyEvent(const base::NativeEvent& native_event, int flags)
53 : KeyEvent(native_event) {
54 set_flags(flags);
58 class TestTouchEvent : public ui::TouchEvent {
59 public:
60 TestTouchEvent(ui::EventType type,
61 const gfx::Point& root_location,
62 int touch_id,
63 int flags,
64 base::TimeDelta timestamp)
65 : TouchEvent(type, root_location, flags, touch_id, timestamp,
66 1.0f, 1.0f, 0.0f, 0.0f) {
69 private:
70 DISALLOW_COPY_AND_ASSIGN(TestTouchEvent);
73 const int kAllButtonMask = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON;
75 } // namespace
77 EventGeneratorDelegate* EventGenerator::default_delegate = NULL;
79 EventGenerator::EventGenerator(gfx::NativeWindow root_window)
80 : current_target_(NULL),
81 flags_(0),
82 grab_(false),
83 async_(false),
84 targeting_application_(false),
85 tick_clock_(new TestTickClock()) {
86 Init(root_window, NULL);
89 EventGenerator::EventGenerator(gfx::NativeWindow root_window,
90 const gfx::Point& point)
91 : current_location_(point),
92 current_target_(NULL),
93 flags_(0),
94 grab_(false),
95 async_(false),
96 targeting_application_(false),
97 tick_clock_(new TestTickClock()) {
98 Init(root_window, NULL);
101 EventGenerator::EventGenerator(gfx::NativeWindow root_window,
102 gfx::NativeWindow window)
103 : current_target_(NULL),
104 flags_(0),
105 grab_(false),
106 async_(false),
107 targeting_application_(false),
108 tick_clock_(new TestTickClock()) {
109 Init(root_window, window);
112 EventGenerator::EventGenerator(EventGeneratorDelegate* delegate)
113 : delegate_(delegate),
114 current_target_(NULL),
115 flags_(0),
116 grab_(false),
117 async_(false),
118 targeting_application_(false),
119 tick_clock_(new TestTickClock()) {
120 Init(NULL, NULL);
123 EventGenerator::~EventGenerator() {
124 for (std::list<ui::Event*>::iterator i = pending_events_.begin();
125 i != pending_events_.end(); ++i)
126 delete *i;
127 pending_events_.clear();
128 delegate()->SetContext(NULL, NULL, NULL);
131 void EventGenerator::PressLeftButton() {
132 PressButton(ui::EF_LEFT_MOUSE_BUTTON);
135 void EventGenerator::ReleaseLeftButton() {
136 ReleaseButton(ui::EF_LEFT_MOUSE_BUTTON);
139 void EventGenerator::ClickLeftButton() {
140 PressLeftButton();
141 ReleaseLeftButton();
144 void EventGenerator::DoubleClickLeftButton() {
145 flags_ &= ~ui::EF_IS_DOUBLE_CLICK;
146 ClickLeftButton();
147 flags_ |= ui::EF_IS_DOUBLE_CLICK;
148 ClickLeftButton();
149 flags_ &= ~ui::EF_IS_DOUBLE_CLICK;
152 void EventGenerator::PressRightButton() {
153 PressButton(ui::EF_RIGHT_MOUSE_BUTTON);
156 void EventGenerator::ReleaseRightButton() {
157 ReleaseButton(ui::EF_RIGHT_MOUSE_BUTTON);
160 void EventGenerator::MoveMouseWheel(int delta_x, int delta_y) {
161 gfx::Point location = GetLocationInCurrentRoot();
162 ui::MouseEvent mouseev(ui::ET_MOUSEWHEEL, location, location,
163 ui::EventTimeForNow(), flags_, 0);
164 ui::MouseWheelEvent wheelev(mouseev, delta_x, delta_y);
165 Dispatch(&wheelev);
168 void EventGenerator::SendMouseExit() {
169 gfx::Point exit_location(current_location_);
170 delegate()->ConvertPointToTarget(current_target_, &exit_location);
171 ui::MouseEvent mouseev(ui::ET_MOUSE_EXITED, exit_location, exit_location,
172 ui::EventTimeForNow(), flags_, 0);
173 Dispatch(&mouseev);
176 void EventGenerator::MoveMouseToWithNative(const gfx::Point& point_in_host,
177 const gfx::Point& point_for_native) {
178 #if defined(USE_X11)
179 ui::ScopedXI2Event xevent;
180 xevent.InitMotionEvent(point_in_host, point_for_native, flags_);
181 static_cast<XEvent*>(xevent)->xmotion.time = Now().InMicroseconds();
182 ui::MouseEvent mouseev(xevent);
183 #elif defined(USE_OZONE)
184 // Ozone uses the location in native event as a system location.
185 // Create a fake event with the point in host, which will be passed
186 // to the non native event, then update the native event with the native
187 // (root) one.
188 scoped_ptr<ui::MouseEvent> native_event(new ui::MouseEvent(
189 ui::ET_MOUSE_MOVED, point_in_host, point_in_host, Now(), flags_, 0));
190 ui::MouseEvent mouseev(native_event.get());
191 native_event->set_location(point_for_native);
192 #else
193 ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, point_in_host, point_for_native,
194 Now(), flags_, 0);
195 LOG(FATAL)
196 << "Generating a native motion event is not supported on this platform";
197 #endif
198 Dispatch(&mouseev);
200 current_location_ = point_in_host;
201 delegate()->ConvertPointFromHost(current_target_, &current_location_);
204 void EventGenerator::MoveMouseToInHost(const gfx::Point& point_in_host) {
205 const ui::EventType event_type = (flags_ & ui::EF_LEFT_MOUSE_BUTTON) ?
206 ui::ET_MOUSE_DRAGGED : ui::ET_MOUSE_MOVED;
207 ui::MouseEvent mouseev(event_type, point_in_host, point_in_host,
208 ui::EventTimeForNow(), flags_, 0);
209 Dispatch(&mouseev);
211 current_location_ = point_in_host;
212 delegate()->ConvertPointFromHost(current_target_, &current_location_);
215 void EventGenerator::MoveMouseTo(const gfx::Point& point_in_screen,
216 int count) {
217 DCHECK_GT(count, 0);
218 const ui::EventType event_type = (flags_ & ui::EF_LEFT_MOUSE_BUTTON) ?
219 ui::ET_MOUSE_DRAGGED : ui::ET_MOUSE_MOVED;
221 gfx::Vector2dF diff(point_in_screen - current_location_);
222 for (float i = 1; i <= count; i++) {
223 gfx::Vector2dF step(diff);
224 step.Scale(i / count);
225 gfx::Point move_point = current_location_ + gfx::ToRoundedVector2d(step);
226 if (!grab_)
227 UpdateCurrentDispatcher(move_point);
228 delegate()->ConvertPointToTarget(current_target_, &move_point);
229 ui::MouseEvent mouseev(event_type, move_point, move_point,
230 ui::EventTimeForNow(), flags_, 0);
231 Dispatch(&mouseev);
233 current_location_ = point_in_screen;
236 void EventGenerator::MoveMouseRelativeTo(const EventTarget* window,
237 const gfx::Point& point_in_parent) {
238 gfx::Point point(point_in_parent);
239 delegate()->ConvertPointFromTarget(window, &point);
240 MoveMouseTo(point);
243 void EventGenerator::DragMouseTo(const gfx::Point& point) {
244 PressLeftButton();
245 MoveMouseTo(point);
246 ReleaseLeftButton();
249 void EventGenerator::MoveMouseToCenterOf(EventTarget* window) {
250 MoveMouseTo(CenterOfWindow(window));
253 void EventGenerator::PressTouch() {
254 PressTouchId(0);
257 void EventGenerator::PressTouchId(int touch_id) {
258 TestTouchEvent touchev(
259 ui::ET_TOUCH_PRESSED, GetLocationInCurrentRoot(), touch_id, flags_,
260 Now());
261 Dispatch(&touchev);
264 void EventGenerator::MoveTouch(const gfx::Point& point) {
265 MoveTouchId(point, 0);
268 void EventGenerator::MoveTouchId(const gfx::Point& point, int touch_id) {
269 current_location_ = point;
270 TestTouchEvent touchev(
271 ui::ET_TOUCH_MOVED, GetLocationInCurrentRoot(), touch_id, flags_,
272 Now());
273 Dispatch(&touchev);
275 if (!grab_)
276 UpdateCurrentDispatcher(point);
279 void EventGenerator::ReleaseTouch() {
280 ReleaseTouchId(0);
283 void EventGenerator::ReleaseTouchId(int touch_id) {
284 TestTouchEvent touchev(
285 ui::ET_TOUCH_RELEASED, GetLocationInCurrentRoot(), touch_id, flags_,
286 Now());
287 Dispatch(&touchev);
290 void EventGenerator::PressMoveAndReleaseTouchTo(const gfx::Point& point) {
291 PressTouch();
292 MoveTouch(point);
293 ReleaseTouch();
296 void EventGenerator::PressMoveAndReleaseTouchToCenterOf(EventTarget* window) {
297 PressMoveAndReleaseTouchTo(CenterOfWindow(window));
300 void EventGenerator::GestureEdgeSwipe() {
301 ui::GestureEvent gesture(
302 0, 0, 0, Now(), ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE));
303 Dispatch(&gesture);
306 void EventGenerator::GestureTapAt(const gfx::Point& location) {
307 const int kTouchId = 2;
308 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
309 location,
310 kTouchId,
311 Now());
312 Dispatch(&press);
314 ui::TouchEvent release(
315 ui::ET_TOUCH_RELEASED, location, kTouchId,
316 press.time_stamp() + base::TimeDelta::FromMilliseconds(50));
317 Dispatch(&release);
320 void EventGenerator::GestureTapDownAndUp(const gfx::Point& location) {
321 const int kTouchId = 3;
322 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
323 location,
324 kTouchId,
325 Now());
326 Dispatch(&press);
328 ui::TouchEvent release(
329 ui::ET_TOUCH_RELEASED, location, kTouchId,
330 press.time_stamp() + base::TimeDelta::FromMilliseconds(1000));
331 Dispatch(&release);
334 base::TimeDelta EventGenerator::CalculateScrollDurationForFlingVelocity(
335 const gfx::Point& start,
336 const gfx::Point& end,
337 float velocity,
338 int steps) {
339 const float kGestureDistance = (start - end).Length();
340 const float kFlingStepDelay = (kGestureDistance / velocity) / steps * 1000000;
341 return base::TimeDelta::FromMicroseconds(kFlingStepDelay);
344 void EventGenerator::GestureScrollSequence(const gfx::Point& start,
345 const gfx::Point& end,
346 const base::TimeDelta& step_delay,
347 int steps) {
348 GestureScrollSequenceWithCallback(start, end, step_delay, steps,
349 base::Bind(&DummyCallback));
352 void EventGenerator::GestureScrollSequenceWithCallback(
353 const gfx::Point& start,
354 const gfx::Point& end,
355 const base::TimeDelta& step_delay,
356 int steps,
357 const ScrollStepCallback& callback) {
358 const int kTouchId = 5;
359 base::TimeDelta timestamp = Now();
360 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, start, kTouchId, timestamp);
361 Dispatch(&press);
363 callback.Run(ui::ET_GESTURE_SCROLL_BEGIN, gfx::Vector2dF());
365 float dx = static_cast<float>(end.x() - start.x()) / steps;
366 float dy = static_cast<float>(end.y() - start.y()) / steps;
367 gfx::PointF location = start;
368 for (int i = 0; i < steps; ++i) {
369 location.Offset(dx, dy);
370 timestamp += step_delay;
371 ui::TouchEvent move(ui::ET_TOUCH_MOVED, location, kTouchId, timestamp);
372 Dispatch(&move);
373 callback.Run(ui::ET_GESTURE_SCROLL_UPDATE, gfx::Vector2dF(dx, dy));
376 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, end, kTouchId, timestamp);
377 Dispatch(&release);
379 callback.Run(ui::ET_GESTURE_SCROLL_END, gfx::Vector2dF());
382 void EventGenerator::GestureMultiFingerScroll(int count,
383 const gfx::Point start[],
384 int event_separation_time_ms,
385 int steps,
386 int move_x,
387 int move_y) {
388 const int kMaxTouchPoints = 10;
389 int delays[kMaxTouchPoints] = { 0 };
390 GestureMultiFingerScrollWithDelays(
391 count, start, delays, event_separation_time_ms, steps, move_x, move_y);
394 void EventGenerator::GestureMultiFingerScrollWithDelays(
395 int count,
396 const gfx::Point start[],
397 const int delay_adding_finger_ms[],
398 int event_separation_time_ms,
399 int steps,
400 int move_x,
401 int move_y) {
402 const int kMaxTouchPoints = 10;
403 gfx::Point points[kMaxTouchPoints];
404 CHECK_LE(count, kMaxTouchPoints);
405 CHECK_GT(steps, 0);
407 int delta_x = move_x / steps;
408 int delta_y = move_y / steps;
410 for (int i = 0; i < count; ++i) {
411 points[i] = start[i];
414 base::TimeDelta press_time_first = Now();
415 base::TimeDelta press_time[kMaxTouchPoints];
416 bool pressed[kMaxTouchPoints];
417 for (int i = 0; i < count; ++i) {
418 pressed[i] = false;
419 press_time[i] = press_time_first +
420 base::TimeDelta::FromMilliseconds(delay_adding_finger_ms[i]);
423 int last_id = 0;
424 for (int step = 0; step < steps; ++step) {
425 base::TimeDelta move_time = press_time_first +
426 base::TimeDelta::FromMilliseconds(event_separation_time_ms * step);
428 while (last_id < count &&
429 !pressed[last_id] &&
430 move_time >= press_time[last_id]) {
431 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
432 points[last_id],
433 last_id,
434 press_time[last_id]);
435 Dispatch(&press);
436 pressed[last_id] = true;
437 last_id++;
440 for (int i = 0; i < count; ++i) {
441 points[i].Offset(delta_x, delta_y);
442 if (i >= last_id)
443 continue;
444 ui::TouchEvent move(ui::ET_TOUCH_MOVED, points[i], i, move_time);
445 Dispatch(&move);
449 base::TimeDelta release_time = press_time_first +
450 base::TimeDelta::FromMilliseconds(event_separation_time_ms * steps);
451 for (int i = 0; i < last_id; ++i) {
452 ui::TouchEvent release(
453 ui::ET_TOUCH_RELEASED, points[i], i, release_time);
454 Dispatch(&release);
458 void EventGenerator::ScrollSequence(const gfx::Point& start,
459 const base::TimeDelta& step_delay,
460 float x_offset,
461 float y_offset,
462 int steps,
463 int num_fingers) {
464 base::TimeDelta timestamp = Now();
465 ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
466 start,
467 timestamp,
469 0, 0,
470 0, 0,
471 num_fingers);
472 Dispatch(&fling_cancel);
474 float dx = x_offset / steps;
475 float dy = y_offset / steps;
476 for (int i = 0; i < steps; ++i) {
477 timestamp += step_delay;
478 ui::ScrollEvent move(ui::ET_SCROLL,
479 start,
480 timestamp,
482 dx, dy,
483 dx, dy,
484 num_fingers);
485 Dispatch(&move);
488 ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START,
489 start,
490 timestamp,
492 x_offset, y_offset,
493 x_offset, y_offset,
494 num_fingers);
495 Dispatch(&fling_start);
498 void EventGenerator::ScrollSequence(const gfx::Point& start,
499 const base::TimeDelta& step_delay,
500 const std::vector<gfx::PointF>& offsets,
501 int num_fingers) {
502 size_t steps = offsets.size();
503 base::TimeDelta timestamp = Now();
504 ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
505 start,
506 timestamp,
508 0, 0,
509 0, 0,
510 num_fingers);
511 Dispatch(&fling_cancel);
513 for (size_t i = 0; i < steps; ++i) {
514 timestamp += step_delay;
515 ui::ScrollEvent scroll(ui::ET_SCROLL,
516 start,
517 timestamp,
519 offsets[i].x(), offsets[i].y(),
520 offsets[i].x(), offsets[i].y(),
521 num_fingers);
522 Dispatch(&scroll);
525 ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START,
526 start,
527 timestamp,
529 offsets[steps - 1].x(), offsets[steps - 1].y(),
530 offsets[steps - 1].x(), offsets[steps - 1].y(),
531 num_fingers);
532 Dispatch(&fling_start);
535 void EventGenerator::PressKey(ui::KeyboardCode key_code, int flags) {
536 DispatchKeyEvent(true, key_code, flags);
539 void EventGenerator::ReleaseKey(ui::KeyboardCode key_code, int flags) {
540 DispatchKeyEvent(false, key_code, flags);
543 void EventGenerator::Dispatch(ui::Event* event) {
544 DoDispatchEvent(event, async_);
547 void EventGenerator::SetTickClock(scoped_ptr<base::TickClock> tick_clock) {
548 tick_clock_ = tick_clock.Pass();
551 base::TimeDelta EventGenerator::Now() {
552 // This is the same as what EventTimeForNow() does, but here we do it
553 // with a tick clock that can be replaced with a simulated clock for tests.
554 return base::TimeDelta::FromInternalValue(
555 tick_clock_->NowTicks().ToInternalValue());
558 void EventGenerator::Init(gfx::NativeWindow root_window,
559 gfx::NativeWindow window_context) {
560 delegate()->SetContext(this, root_window, window_context);
561 if (window_context)
562 current_location_ = delegate()->CenterOfWindow(window_context);
563 current_target_ = delegate()->GetTargetAt(current_location_);
566 void EventGenerator::DispatchKeyEvent(bool is_press,
567 ui::KeyboardCode key_code,
568 int flags) {
569 #if defined(OS_WIN)
570 UINT key_press = WM_KEYDOWN;
571 uint16 character = ui::GetCharacterFromKeyCode(key_code, flags);
572 if (is_press && character) {
573 MSG native_event = { NULL, WM_KEYDOWN, key_code, 0 };
574 TestKeyEvent keyev(native_event, flags);
575 Dispatch(&keyev);
576 // On Windows, WM_KEYDOWN event is followed by WM_CHAR with a character
577 // if the key event cooresponds to a real character.
578 key_press = WM_CHAR;
579 key_code = static_cast<ui::KeyboardCode>(character);
581 MSG native_event =
582 { NULL, (is_press ? key_press : WM_KEYUP), key_code, 0 };
583 native_event.time = Now().InMicroseconds();
584 TestKeyEvent keyev(native_event, flags);
585 #elif defined(USE_X11)
586 ui::ScopedXI2Event xevent;
587 xevent.InitKeyEvent(is_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED,
588 key_code,
589 flags);
590 static_cast<XEvent*>(xevent)->xkey.time = Now().InMicroseconds();
591 ui::KeyEvent keyev(xevent);
592 #else
593 ui::EventType type = is_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED;
594 ui::KeyEvent keyev(type, key_code, flags);
595 #endif // OS_WIN
596 Dispatch(&keyev);
599 void EventGenerator::UpdateCurrentDispatcher(const gfx::Point& point) {
600 current_target_ = delegate()->GetTargetAt(point);
603 void EventGenerator::PressButton(int flag) {
604 if (!(flags_ & flag)) {
605 flags_ |= flag;
606 grab_ = (flags_ & kAllButtonMask) != 0;
607 gfx::Point location = GetLocationInCurrentRoot();
608 ui::MouseEvent mouseev(ui::ET_MOUSE_PRESSED, location, location,
609 ui::EventTimeForNow(), flags_, flag);
610 Dispatch(&mouseev);
614 void EventGenerator::ReleaseButton(int flag) {
615 if (flags_ & flag) {
616 gfx::Point location = GetLocationInCurrentRoot();
617 ui::MouseEvent mouseev(ui::ET_MOUSE_RELEASED, location, location,
618 ui::EventTimeForNow(), flags_, flag);
619 Dispatch(&mouseev);
620 flags_ ^= flag;
622 grab_ = (flags_ & kAllButtonMask) != 0;
625 gfx::Point EventGenerator::GetLocationInCurrentRoot() const {
626 gfx::Point p(current_location_);
627 delegate()->ConvertPointToTarget(current_target_, &p);
628 return p;
631 gfx::Point EventGenerator::CenterOfWindow(const EventTarget* window) const {
632 return delegate()->CenterOfTarget(window);
635 void EventGenerator::DoDispatchEvent(ui::Event* event, bool async) {
636 if (async) {
637 ui::Event* pending_event;
638 if (event->IsKeyEvent()) {
639 pending_event = new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event));
640 } else if (event->IsMouseEvent()) {
641 pending_event = new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event));
642 } else if (event->IsTouchEvent()) {
643 pending_event = new ui::TouchEvent(*static_cast<ui::TouchEvent*>(event));
644 } else if (event->IsScrollEvent()) {
645 pending_event =
646 new ui::ScrollEvent(*static_cast<ui::ScrollEvent*>(event));
647 } else {
648 NOTREACHED() << "Invalid event type";
649 return;
651 if (pending_events_.empty()) {
652 base::ThreadTaskRunnerHandle::Get()->PostTask(
653 FROM_HERE,
654 base::Bind(&EventGenerator::DispatchNextPendingEvent,
655 base::Unretained(this)));
657 pending_events_.push_back(pending_event);
658 } else {
659 ui::EventSource* event_source = delegate()->GetEventSource(current_target_);
660 ui::EventSourceTestApi event_source_test(event_source);
661 ui::EventDispatchDetails details =
662 event_source_test.SendEventToProcessor(event);
663 CHECK(!details.dispatcher_destroyed);
667 void EventGenerator::DispatchNextPendingEvent() {
668 DCHECK(!pending_events_.empty());
669 ui::Event* event = pending_events_.front();
670 DoDispatchEvent(event, false);
671 pending_events_.pop_front();
672 delete event;
673 if (!pending_events_.empty()) {
674 base::ThreadTaskRunnerHandle::Get()->PostTask(
675 FROM_HERE,
676 base::Bind(&EventGenerator::DispatchNextPendingEvent,
677 base::Unretained(this)));
681 const EventGeneratorDelegate* EventGenerator::delegate() const {
682 if (delegate_)
683 return delegate_.get();
685 DCHECK(default_delegate);
686 return default_delegate;
689 EventGeneratorDelegate* EventGenerator::delegate() {
690 return const_cast<EventGeneratorDelegate*>(
691 const_cast<const EventGenerator*>(this)->delegate());
694 } // namespace test
695 } // namespace ui