Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / aura / window_event_dispatcher_unittest.cc
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/window_event_dispatcher.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/run_loop.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/aura/client/capture_client.h"
13 #include "ui/aura/client/event_client.h"
14 #include "ui/aura/client/focus_client.h"
15 #include "ui/aura/env.h"
16 #include "ui/aura/test/aura_test_base.h"
17 #include "ui/aura/test/env_test_helper.h"
18 #include "ui/aura/test/test_cursor_client.h"
19 #include "ui/aura/test/test_screen.h"
20 #include "ui/aura/test/test_window_delegate.h"
21 #include "ui/aura/test/test_windows.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_tracker.h"
24 #include "ui/base/hit_test.h"
25 #include "ui/events/event.h"
26 #include "ui/events/event_handler.h"
27 #include "ui/events/event_utils.h"
28 #include "ui/events/gestures/gesture_configuration.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
30 #include "ui/events/test/event_generator.h"
31 #include "ui/events/test/test_event_handler.h"
32 #include "ui/gfx/point.h"
33 #include "ui/gfx/rect.h"
34 #include "ui/gfx/screen.h"
35 #include "ui/gfx/transform.h"
36
37 namespace aura {
38 namespace {
39
40 // A delegate that always returns a non-client component for hit tests.
41 class NonClientDelegate : public test::TestWindowDelegate {
42  public:
43   NonClientDelegate()
44       : non_client_count_(0),
45         mouse_event_count_(0),
46         mouse_event_flags_(0x0) {
47   }
48   virtual ~NonClientDelegate() {}
49
50   int non_client_count() const { return non_client_count_; }
51   gfx::Point non_client_location() const { return non_client_location_; }
52   int mouse_event_count() const { return mouse_event_count_; }
53   gfx::Point mouse_event_location() const { return mouse_event_location_; }
54   int mouse_event_flags() const { return mouse_event_flags_; }
55
56   virtual int GetNonClientComponent(const gfx::Point& location) const OVERRIDE {
57     NonClientDelegate* self = const_cast<NonClientDelegate*>(this);
58     self->non_client_count_++;
59     self->non_client_location_ = location;
60     return HTTOPLEFT;
61   }
62   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
63     mouse_event_count_++;
64     mouse_event_location_ = event->location();
65     mouse_event_flags_ = event->flags();
66     event->SetHandled();
67   }
68
69  private:
70   int non_client_count_;
71   gfx::Point non_client_location_;
72   int mouse_event_count_;
73   gfx::Point mouse_event_location_;
74   int mouse_event_flags_;
75
76   DISALLOW_COPY_AND_ASSIGN(NonClientDelegate);
77 };
78
79 // A simple event handler that consumes key events.
80 class ConsumeKeyHandler : public ui::test::TestEventHandler {
81  public:
82   ConsumeKeyHandler() {}
83   virtual ~ConsumeKeyHandler() {}
84
85   // Overridden from ui::EventHandler:
86   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
87     ui::test::TestEventHandler::OnKeyEvent(event);
88     event->StopPropagation();
89   }
90
91  private:
92   DISALLOW_COPY_AND_ASSIGN(ConsumeKeyHandler);
93 };
94
95 bool IsFocusedWindow(aura::Window* window) {
96   return client::GetFocusClient(window)->GetFocusedWindow() == window;
97 }
98
99 }  // namespace
100
101 typedef test::AuraTestBase WindowEventDispatcherTest;
102
103 TEST_F(WindowEventDispatcherTest, OnHostMouseEvent) {
104   // Create two non-overlapping windows so we don't have to worry about which
105   // is on top.
106   scoped_ptr<NonClientDelegate> delegate1(new NonClientDelegate());
107   scoped_ptr<NonClientDelegate> delegate2(new NonClientDelegate());
108   const int kWindowWidth = 123;
109   const int kWindowHeight = 45;
110   gfx::Rect bounds1(100, 200, kWindowWidth, kWindowHeight);
111   gfx::Rect bounds2(300, 400, kWindowWidth, kWindowHeight);
112   scoped_ptr<aura::Window> window1(CreateTestWindowWithDelegate(
113       delegate1.get(), -1234, bounds1, root_window()));
114   scoped_ptr<aura::Window> window2(CreateTestWindowWithDelegate(
115       delegate2.get(), -5678, bounds2, root_window()));
116
117   // Send a mouse event to window1.
118   gfx::Point point(101, 201);
119   ui::MouseEvent event1(
120       ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON,
121       ui::EF_LEFT_MOUSE_BUTTON);
122   DispatchEventUsingWindowDispatcher(&event1);
123
124   // Event was tested for non-client area for the target window.
125   EXPECT_EQ(1, delegate1->non_client_count());
126   EXPECT_EQ(0, delegate2->non_client_count());
127   // The non-client component test was in local coordinates.
128   EXPECT_EQ(gfx::Point(1, 1), delegate1->non_client_location());
129   // Mouse event was received by target window.
130   EXPECT_EQ(1, delegate1->mouse_event_count());
131   EXPECT_EQ(0, delegate2->mouse_event_count());
132   // Event was in local coordinates.
133   EXPECT_EQ(gfx::Point(1, 1), delegate1->mouse_event_location());
134   // Non-client flag was set.
135   EXPECT_TRUE(delegate1->mouse_event_flags() & ui::EF_IS_NON_CLIENT);
136 }
137
138 TEST_F(WindowEventDispatcherTest, RepostEvent) {
139   // Test RepostEvent in RootWindow. It only works for Mouse Press.
140   EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
141   gfx::Point point(10, 10);
142   ui::MouseEvent event(
143       ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON,
144       ui::EF_LEFT_MOUSE_BUTTON);
145   host()->dispatcher()->RepostEvent(event);
146   RunAllPendingInMessageLoop();
147   EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
148 }
149
150 // Check that we correctly track the state of the mouse buttons in response to
151 // button press and release events.
152 TEST_F(WindowEventDispatcherTest, MouseButtonState) {
153   EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
154
155   gfx::Point location;
156   scoped_ptr<ui::MouseEvent> event;
157
158   // Press the left button.
159   event.reset(new ui::MouseEvent(
160       ui::ET_MOUSE_PRESSED,
161       location,
162       location,
163       ui::EF_LEFT_MOUSE_BUTTON,
164       ui::EF_LEFT_MOUSE_BUTTON));
165   DispatchEventUsingWindowDispatcher(event.get());
166   EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
167
168   // Additionally press the right.
169   event.reset(new ui::MouseEvent(
170       ui::ET_MOUSE_PRESSED,
171       location,
172       location,
173       ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
174       ui::EF_RIGHT_MOUSE_BUTTON));
175   DispatchEventUsingWindowDispatcher(event.get());
176   EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
177
178   // Release the left button.
179   event.reset(new ui::MouseEvent(
180       ui::ET_MOUSE_RELEASED,
181       location,
182       location,
183       ui::EF_RIGHT_MOUSE_BUTTON,
184       ui::EF_LEFT_MOUSE_BUTTON));
185   DispatchEventUsingWindowDispatcher(event.get());
186   EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
187
188   // Release the right button.  We should ignore the Shift-is-down flag.
189   event.reset(new ui::MouseEvent(
190       ui::ET_MOUSE_RELEASED,
191       location,
192       location,
193       ui::EF_SHIFT_DOWN,
194       ui::EF_RIGHT_MOUSE_BUTTON));
195   DispatchEventUsingWindowDispatcher(event.get());
196   EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
197
198   // Press the middle button.
199   event.reset(new ui::MouseEvent(
200       ui::ET_MOUSE_PRESSED,
201       location,
202       location,
203       ui::EF_MIDDLE_MOUSE_BUTTON,
204       ui::EF_MIDDLE_MOUSE_BUTTON));
205   DispatchEventUsingWindowDispatcher(event.get());
206   EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
207 }
208
209 TEST_F(WindowEventDispatcherTest, TranslatedEvent) {
210   scoped_ptr<Window> w1(test::CreateTestWindowWithDelegate(NULL, 1,
211       gfx::Rect(50, 50, 100, 100), root_window()));
212
213   gfx::Point origin(100, 100);
214   ui::MouseEvent root(ui::ET_MOUSE_PRESSED, origin, origin, 0, 0);
215
216   EXPECT_EQ("100,100", root.location().ToString());
217   EXPECT_EQ("100,100", root.root_location().ToString());
218
219   ui::MouseEvent translated_event(
220       root, static_cast<Window*>(root_window()), w1.get(),
221       ui::ET_MOUSE_ENTERED, root.flags());
222   EXPECT_EQ("50,50", translated_event.location().ToString());
223   EXPECT_EQ("100,100", translated_event.root_location().ToString());
224 }
225
226 namespace {
227
228 class TestEventClient : public client::EventClient {
229  public:
230   static const int kNonLockWindowId = 100;
231   static const int kLockWindowId = 200;
232
233   explicit TestEventClient(Window* root_window)
234       : root_window_(root_window),
235         lock_(false) {
236     client::SetEventClient(root_window_, this);
237     Window* lock_window =
238         test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
239     lock_window->set_id(kLockWindowId);
240     Window* non_lock_window =
241         test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
242     non_lock_window->set_id(kNonLockWindowId);
243   }
244   virtual ~TestEventClient() {
245     client::SetEventClient(root_window_, NULL);
246   }
247
248   // Starts/stops locking. Locking prevents windows other than those inside
249   // the lock container from receiving events, getting focus etc.
250   void Lock() {
251     lock_ = true;
252   }
253   void Unlock() {
254     lock_ = false;
255   }
256
257   Window* GetLockWindow() {
258     return const_cast<Window*>(
259         static_cast<const TestEventClient*>(this)->GetLockWindow());
260   }
261   const Window* GetLockWindow() const {
262     return root_window_->GetChildById(kLockWindowId);
263   }
264   Window* GetNonLockWindow() {
265     return root_window_->GetChildById(kNonLockWindowId);
266   }
267
268  private:
269   // Overridden from client::EventClient:
270   virtual bool CanProcessEventsWithinSubtree(
271       const Window* window) const OVERRIDE {
272     return lock_ ?
273         window->Contains(GetLockWindow()) || GetLockWindow()->Contains(window) :
274         true;
275   }
276
277   virtual ui::EventTarget* GetToplevelEventTarget() OVERRIDE {
278     return NULL;
279   }
280
281   Window* root_window_;
282   bool lock_;
283
284   DISALLOW_COPY_AND_ASSIGN(TestEventClient);
285 };
286
287 }  // namespace
288
289 TEST_F(WindowEventDispatcherTest, CanProcessEventsWithinSubtree) {
290   TestEventClient client(root_window());
291   test::TestWindowDelegate d;
292
293   ui::test::TestEventHandler nonlock_ef;
294   ui::test::TestEventHandler lock_ef;
295   client.GetNonLockWindow()->AddPreTargetHandler(&nonlock_ef);
296   client.GetLockWindow()->AddPreTargetHandler(&lock_ef);
297
298   Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20),
299                                                 client.GetNonLockWindow());
300   w1->set_id(1);
301   Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20),
302                                                 client.GetNonLockWindow());
303   w2->set_id(2);
304   scoped_ptr<Window> w3(
305       test::CreateTestWindowWithDelegate(&d, 3, gfx::Rect(30, 30, 20, 20),
306                                          client.GetLockWindow()));
307
308   w1->Focus();
309   EXPECT_TRUE(IsFocusedWindow(w1));
310
311   client.Lock();
312
313   // Since we're locked, the attempt to focus w2 will be ignored.
314   w2->Focus();
315   EXPECT_TRUE(IsFocusedWindow(w1));
316   EXPECT_FALSE(IsFocusedWindow(w2));
317
318   {
319     // Attempting to send a key event to w1 (not in the lock container) should
320     // cause focus to be reset.
321     ui::test::EventGenerator generator(root_window());
322     generator.PressKey(ui::VKEY_SPACE, 0);
323     EXPECT_EQ(NULL, client::GetFocusClient(w1)->GetFocusedWindow());
324     EXPECT_FALSE(IsFocusedWindow(w1));
325   }
326
327   {
328     // Events sent to a window not in the lock container will not be processed.
329     // i.e. never sent to the non-lock container's event filter.
330     ui::test::EventGenerator generator(root_window(), w1);
331     generator.ClickLeftButton();
332     EXPECT_EQ(0, nonlock_ef.num_mouse_events());
333
334     // Events sent to a window in the lock container will be processed.
335     ui::test::EventGenerator generator3(root_window(), w3.get());
336     generator3.PressLeftButton();
337     EXPECT_EQ(1, lock_ef.num_mouse_events());
338   }
339
340   // Prevent w3 from being deleted by the hierarchy since its delegate is owned
341   // by this scope.
342   w3->parent()->RemoveChild(w3.get());
343 }
344
345 TEST_F(WindowEventDispatcherTest, IgnoreUnknownKeys) {
346   ConsumeKeyHandler handler;
347   root_window()->AddPreTargetHandler(&handler);
348
349   ui::KeyEvent unknown_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_NONE);
350   DispatchEventUsingWindowDispatcher(&unknown_event);
351   EXPECT_FALSE(unknown_event.handled());
352   EXPECT_EQ(0, handler.num_key_events());
353
354   handler.Reset();
355   ui::KeyEvent known_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
356   DispatchEventUsingWindowDispatcher(&known_event);
357   EXPECT_TRUE(known_event.handled());
358   EXPECT_EQ(1, handler.num_key_events());
359
360   handler.Reset();
361   ui::KeyEvent ime_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
362                          ui::EF_IME_FABRICATED_KEY);
363   DispatchEventUsingWindowDispatcher(&ime_event);
364   EXPECT_TRUE(ime_event.handled());
365   EXPECT_EQ(1, handler.num_key_events());
366
367   handler.Reset();
368   ui::KeyEvent unknown_key_with_char_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
369                                            ui::EF_NONE);
370   unknown_key_with_char_event.set_character(0x00e4 /* "ä" */);
371   DispatchEventUsingWindowDispatcher(&unknown_key_with_char_event);
372   EXPECT_TRUE(unknown_key_with_char_event.handled());
373   EXPECT_EQ(1, handler.num_key_events());
374 }
375
376 TEST_F(WindowEventDispatcherTest, NoDelegateWindowReceivesKeyEvents) {
377   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
378   w1->Show();
379   w1->Focus();
380
381   ui::test::TestEventHandler handler;
382   w1->AddPreTargetHandler(&handler);
383   ui::KeyEvent key_press(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
384   DispatchEventUsingWindowDispatcher(&key_press);
385   EXPECT_TRUE(key_press.handled());
386   EXPECT_EQ(1, handler.num_key_events());
387
388   w1->RemovePreTargetHandler(&handler);
389 }
390
391 // Tests that touch-events that are beyond the bounds of the root-window do get
392 // propagated to the event filters correctly with the root as the target.
393 TEST_F(WindowEventDispatcherTest, TouchEventsOutsideBounds) {
394   ui::test::TestEventHandler handler;
395   root_window()->AddPreTargetHandler(&handler);
396
397   gfx::Point position = root_window()->bounds().origin();
398   position.Offset(-10, -10);
399   ui::TouchEvent press(
400       ui::ET_TOUCH_PRESSED, position, 0, ui::EventTimeForNow());
401   DispatchEventUsingWindowDispatcher(&press);
402   EXPECT_EQ(1, handler.num_touch_events());
403
404   position = root_window()->bounds().origin();
405   position.Offset(root_window()->bounds().width() + 10,
406                   root_window()->bounds().height() + 10);
407   ui::TouchEvent release(
408       ui::ET_TOUCH_RELEASED, position, 0, ui::EventTimeForNow());
409   DispatchEventUsingWindowDispatcher(&release);
410   EXPECT_EQ(2, handler.num_touch_events());
411 }
412
413 // Tests that scroll events are dispatched correctly.
414 TEST_F(WindowEventDispatcherTest, ScrollEventDispatch) {
415   base::TimeDelta now = ui::EventTimeForNow();
416   ui::test::TestEventHandler handler;
417   root_window()->AddPreTargetHandler(&handler);
418
419   test::TestWindowDelegate delegate;
420   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
421   w1->SetBounds(gfx::Rect(20, 20, 40, 40));
422
423   // A scroll event on the root-window itself is dispatched.
424   ui::ScrollEvent scroll1(ui::ET_SCROLL,
425                           gfx::Point(10, 10),
426                           now,
427                           0,
428                           0, -10,
429                           0, -10,
430                           2);
431   DispatchEventUsingWindowDispatcher(&scroll1);
432   EXPECT_EQ(1, handler.num_scroll_events());
433
434   // Scroll event on a window should be dispatched properly.
435   ui::ScrollEvent scroll2(ui::ET_SCROLL,
436                           gfx::Point(25, 30),
437                           now,
438                           0,
439                           -10, 0,
440                           -10, 0,
441                           2);
442   DispatchEventUsingWindowDispatcher(&scroll2);
443   EXPECT_EQ(2, handler.num_scroll_events());
444   root_window()->RemovePreTargetHandler(&handler);
445 }
446
447 namespace {
448
449 // FilterFilter that tracks the types of events it's seen.
450 class EventFilterRecorder : public ui::EventHandler {
451  public:
452   typedef std::vector<ui::EventType> Events;
453   typedef std::vector<gfx::Point> EventLocations;
454   typedef std::vector<int> EventFlags;
455
456   EventFilterRecorder()
457       : wait_until_event_(ui::ET_UNKNOWN) {
458   }
459
460   const Events& events() const { return events_; }
461
462   const EventLocations& mouse_locations() const { return mouse_locations_; }
463   gfx::Point mouse_location(int i) const { return mouse_locations_[i]; }
464   const EventLocations& touch_locations() const { return touch_locations_; }
465   const EventFlags& mouse_event_flags() const { return mouse_event_flags_; }
466
467   void WaitUntilReceivedEvent(ui::EventType type) {
468     wait_until_event_ = type;
469     run_loop_.reset(new base::RunLoop());
470     run_loop_->Run();
471   }
472
473   Events GetAndResetEvents() {
474     Events events = events_;
475     Reset();
476     return events;
477   }
478
479   void Reset() {
480     events_.clear();
481     mouse_locations_.clear();
482     touch_locations_.clear();
483     mouse_event_flags_.clear();
484   }
485
486   // ui::EventHandler overrides:
487   virtual void OnEvent(ui::Event* event) OVERRIDE {
488     ui::EventHandler::OnEvent(event);
489     events_.push_back(event->type());
490     if (wait_until_event_ == event->type() && run_loop_) {
491       run_loop_->Quit();
492       wait_until_event_ = ui::ET_UNKNOWN;
493     }
494   }
495
496   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
497     mouse_locations_.push_back(event->location());
498     mouse_event_flags_.push_back(event->flags());
499   }
500
501   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
502     touch_locations_.push_back(event->location());
503   }
504
505   bool HasReceivedEvent(ui::EventType type) {
506     return std::find(events_.begin(), events_.end(), type) != events_.end();
507   }
508
509  private:
510   scoped_ptr<base::RunLoop> run_loop_;
511   ui::EventType wait_until_event_;
512
513   Events events_;
514   EventLocations mouse_locations_;
515   EventLocations touch_locations_;
516   EventFlags mouse_event_flags_;
517
518   DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder);
519 };
520
521 // Converts an EventType to a string.
522 std::string EventTypeToString(ui::EventType type) {
523   switch (type) {
524     case ui::ET_TOUCH_RELEASED:
525       return "TOUCH_RELEASED";
526
527     case ui::ET_TOUCH_CANCELLED:
528       return "TOUCH_CANCELLED";
529
530     case ui::ET_TOUCH_PRESSED:
531       return "TOUCH_PRESSED";
532
533     case ui::ET_TOUCH_MOVED:
534       return "TOUCH_MOVED";
535
536     case ui::ET_MOUSE_PRESSED:
537       return "MOUSE_PRESSED";
538
539     case ui::ET_MOUSE_DRAGGED:
540       return "MOUSE_DRAGGED";
541
542     case ui::ET_MOUSE_RELEASED:
543       return "MOUSE_RELEASED";
544
545     case ui::ET_MOUSE_MOVED:
546       return "MOUSE_MOVED";
547
548     case ui::ET_MOUSE_ENTERED:
549       return "MOUSE_ENTERED";
550
551     case ui::ET_MOUSE_EXITED:
552       return "MOUSE_EXITED";
553
554     case ui::ET_GESTURE_SCROLL_BEGIN:
555       return "GESTURE_SCROLL_BEGIN";
556
557     case ui::ET_GESTURE_SCROLL_END:
558       return "GESTURE_SCROLL_END";
559
560     case ui::ET_GESTURE_SCROLL_UPDATE:
561       return "GESTURE_SCROLL_UPDATE";
562
563     case ui::ET_GESTURE_PINCH_BEGIN:
564       return "GESTURE_PINCH_BEGIN";
565
566     case ui::ET_GESTURE_PINCH_END:
567       return "GESTURE_PINCH_END";
568
569     case ui::ET_GESTURE_PINCH_UPDATE:
570       return "GESTURE_PINCH_UPDATE";
571
572     case ui::ET_GESTURE_TAP:
573       return "GESTURE_TAP";
574
575     case ui::ET_GESTURE_TAP_DOWN:
576       return "GESTURE_TAP_DOWN";
577
578     case ui::ET_GESTURE_TAP_CANCEL:
579       return "GESTURE_TAP_CANCEL";
580
581     case ui::ET_GESTURE_SHOW_PRESS:
582       return "GESTURE_SHOW_PRESS";
583
584     case ui::ET_GESTURE_BEGIN:
585       return "GESTURE_BEGIN";
586
587     case ui::ET_GESTURE_END:
588       return "GESTURE_END";
589
590     default:
591       // We should explicitly require each event type.
592       NOTREACHED() << "Received unexpected event: " << type;
593       break;
594   }
595   return "";
596 }
597
598 std::string EventTypesToString(const EventFilterRecorder::Events& events) {
599   std::string result;
600   for (size_t i = 0; i < events.size(); ++i) {
601     if (i != 0)
602       result += " ";
603     result += EventTypeToString(events[i]);
604   }
605   return result;
606 }
607
608 }  // namespace
609
610 #if defined(OS_WIN) && defined(ARCH_CPU_X86)
611 #define MAYBE(x) DISABLED_##x
612 #else
613 #define MAYBE(x) x
614 #endif
615
616 // Verifies a repost mouse event targets the window with capture (if there is
617 // one).
618 // Flaky on 32-bit Windows bots.  http://crbug.com/388290
619 TEST_F(WindowEventDispatcherTest, MAYBE(RepostTargetsCaptureWindow)) {
620   // Set capture on |window| generate a mouse event (that is reposted) and not
621   // over |window| and verify |window| gets it (|window| gets it because it has
622   // capture).
623   EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
624   EventFilterRecorder recorder;
625   scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
626   window->SetBounds(gfx::Rect(20, 20, 40, 30));
627   window->AddPreTargetHandler(&recorder);
628   window->SetCapture();
629   const ui::MouseEvent press_event(
630       ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
631       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
632   host()->dispatcher()->RepostEvent(press_event);
633   RunAllPendingInMessageLoop();  // Necessitated by RepostEvent().
634   // Mouse moves/enters may be generated. We only care about a pressed.
635   EXPECT_TRUE(EventTypesToString(recorder.events()).find("MOUSE_PRESSED") !=
636               std::string::npos) << EventTypesToString(recorder.events());
637 }
638
639 TEST_F(WindowEventDispatcherTest, MouseMovesHeld) {
640   EventFilterRecorder recorder;
641   root_window()->AddPreTargetHandler(&recorder);
642
643   test::TestWindowDelegate delegate;
644   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
645       &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
646
647   ui::MouseEvent mouse_move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
648                                   gfx::Point(0, 0), 0, 0);
649   DispatchEventUsingWindowDispatcher(&mouse_move_event);
650   // Discard MOUSE_ENTER.
651   recorder.Reset();
652
653   host()->dispatcher()->HoldPointerMoves();
654
655   // Check that we don't immediately dispatch the MOUSE_DRAGGED event.
656   ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0),
657                                      gfx::Point(0, 0), 0, 0);
658   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
659   EXPECT_TRUE(recorder.events().empty());
660
661   // Check that we do dispatch the held MOUSE_DRAGGED event before another type
662   // of event.
663   ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
664                                      gfx::Point(0, 0), 0, 0);
665   DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
666   EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
667             EventTypesToString(recorder.events()));
668   recorder.Reset();
669
670   // Check that we coalesce held MOUSE_DRAGGED events.
671   ui::MouseEvent mouse_dragged_event2(ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10),
672                                       gfx::Point(10, 10), 0, 0);
673   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
674   DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
675   EXPECT_TRUE(recorder.events().empty());
676   DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
677   EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
678             EventTypesToString(recorder.events()));
679   recorder.Reset();
680
681   // Check that on ReleasePointerMoves, held events are not dispatched
682   // immediately, but posted instead.
683   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
684   host()->dispatcher()->ReleasePointerMoves();
685   EXPECT_TRUE(recorder.events().empty());
686   RunAllPendingInMessageLoop();
687   EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
688   recorder.Reset();
689
690   // However if another message comes in before the dispatch of the posted
691   // event, check that the posted event is dispatched before this new event.
692   host()->dispatcher()->HoldPointerMoves();
693   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
694   host()->dispatcher()->ReleasePointerMoves();
695   DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
696   EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
697             EventTypesToString(recorder.events()));
698   recorder.Reset();
699   RunAllPendingInMessageLoop();
700   EXPECT_TRUE(recorder.events().empty());
701
702   // Check that if the other message is another MOUSE_DRAGGED, we still coalesce
703   // them.
704   host()->dispatcher()->HoldPointerMoves();
705   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
706   host()->dispatcher()->ReleasePointerMoves();
707   DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
708   EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
709   recorder.Reset();
710   RunAllPendingInMessageLoop();
711   EXPECT_TRUE(recorder.events().empty());
712
713   // Check that synthetic mouse move event has a right location when issued
714   // while holding pointer moves.
715   ui::MouseEvent mouse_dragged_event3(ui::ET_MOUSE_DRAGGED, gfx::Point(28, 28),
716                                       gfx::Point(28, 28), 0, 0);
717   host()->dispatcher()->HoldPointerMoves();
718   DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
719   DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
720   window->SetBounds(gfx::Rect(15, 15, 80, 80));
721   DispatchEventUsingWindowDispatcher(&mouse_dragged_event3);
722   RunAllPendingInMessageLoop();
723   EXPECT_TRUE(recorder.events().empty());
724   host()->dispatcher()->ReleasePointerMoves();
725   RunAllPendingInMessageLoop();
726   EXPECT_EQ("MOUSE_MOVED", EventTypesToString(recorder.events()));
727   EXPECT_EQ(gfx::Point(13, 13), recorder.mouse_location(0));
728   recorder.Reset();
729   root_window()->RemovePreTargetHandler(&recorder);
730 }
731
732 TEST_F(WindowEventDispatcherTest, TouchMovesHeld) {
733   EventFilterRecorder recorder;
734   root_window()->AddPreTargetHandler(&recorder);
735
736   test::TestWindowDelegate delegate;
737   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
738       &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
739
740   // Starting the touch and throwing out the first few events, since the system
741   // is going to generate synthetic mouse events that are not relevant to the
742   // test.
743   ui::TouchEvent touch_pressed_event(
744       ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, ui::EventTimeForNow());
745   DispatchEventUsingWindowDispatcher(&touch_pressed_event);
746   recorder.WaitUntilReceivedEvent(ui::ET_GESTURE_SHOW_PRESS);
747   recorder.Reset();
748
749   host()->dispatcher()->HoldPointerMoves();
750
751   // Check that we don't immediately dispatch the TOUCH_MOVED event.
752   ui::TouchEvent touch_moved_event(
753       ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 0, ui::EventTimeForNow());
754   ui::TouchEvent touch_moved_event2(
755       ui::ET_TOUCH_MOVED, gfx::Point(11, 10), 0, ui::EventTimeForNow());
756   ui::TouchEvent touch_moved_event3(
757       ui::ET_TOUCH_MOVED, gfx::Point(12, 10), 0, ui::EventTimeForNow());
758
759   DispatchEventUsingWindowDispatcher(&touch_moved_event);
760   EXPECT_TRUE(recorder.events().empty());
761
762   // Check that on ReleasePointerMoves, held events are not dispatched
763   // immediately, but posted instead.
764   DispatchEventUsingWindowDispatcher(&touch_moved_event2);
765   host()->dispatcher()->ReleasePointerMoves();
766   EXPECT_TRUE(recorder.events().empty());
767
768   RunAllPendingInMessageLoop();
769   EXPECT_EQ("TOUCH_MOVED", EventTypesToString(recorder.events()));
770   recorder.Reset();
771
772   // If another touch event occurs then the held touch should be dispatched
773   // immediately before it.
774   ui::TouchEvent touch_released_event(
775       ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 0, ui::EventTimeForNow());
776   recorder.Reset();
777   host()->dispatcher()->HoldPointerMoves();
778   DispatchEventUsingWindowDispatcher(&touch_moved_event3);
779   DispatchEventUsingWindowDispatcher(&touch_released_event);
780   EXPECT_EQ("TOUCH_MOVED TOUCH_RELEASED GESTURE_TAP GESTURE_END",
781             EventTypesToString(recorder.events()));
782   recorder.Reset();
783   host()->dispatcher()->ReleasePointerMoves();
784   RunAllPendingInMessageLoop();
785   EXPECT_TRUE(recorder.events().empty());
786 }
787
788 // Verifies that a direct call to ProcessedTouchEvent() with a
789 // TOUCH_PRESSED event does not cause a crash.
790 TEST_F(WindowEventDispatcherTest, CallToProcessedTouchEvent) {
791   test::TestWindowDelegate delegate;
792   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
793       &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
794
795   ui::TouchEvent touch(
796       ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 1, ui::EventTimeForNow());
797   host()->dispatcher()->ProcessedTouchEvent(
798       &touch, window.get(), ui::ER_UNHANDLED);
799 }
800
801 // This event handler requests the dispatcher to start holding pointer-move
802 // events when it receives the first scroll-update gesture.
803 class HoldPointerOnScrollHandler : public ui::test::TestEventHandler {
804  public:
805   HoldPointerOnScrollHandler(WindowEventDispatcher* dispatcher,
806                              EventFilterRecorder* filter)
807       : dispatcher_(dispatcher),
808         filter_(filter),
809         holding_moves_(false) {}
810   virtual ~HoldPointerOnScrollHandler() {}
811
812  private:
813   // ui::test::TestEventHandler:
814   virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
815     if (!holding_moves_ && gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
816       holding_moves_ = true;
817       dispatcher_->HoldPointerMoves();
818       filter_->Reset();
819     } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
820       dispatcher_->ReleasePointerMoves();
821       holding_moves_ = false;
822     }
823   }
824
825   WindowEventDispatcher* dispatcher_;
826   EventFilterRecorder* filter_;
827   bool holding_moves_;
828
829   DISALLOW_COPY_AND_ASSIGN(HoldPointerOnScrollHandler);
830 };
831
832 // Tests that touch-move events don't contribute to an in-progress scroll
833 // gesture if touch-move events are being held by the dispatcher.
834 TEST_F(WindowEventDispatcherTest, TouchMovesHeldOnScroll) {
835   EventFilterRecorder recorder;
836   root_window()->AddPreTargetHandler(&recorder);
837   test::TestWindowDelegate delegate;
838   HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
839   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
840       &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
841   window->AddPreTargetHandler(&handler);
842
843   ui::test::EventGenerator generator(root_window());
844   generator.GestureScrollSequence(
845       gfx::Point(60, 60), gfx::Point(10, 60),
846       base::TimeDelta::FromMilliseconds(100), 25);
847
848   // |handler| will have reset |filter| and started holding the touch-move
849   // events when scrolling started. At the end of the scroll (i.e. upon
850   // touch-release), the held touch-move event will have been dispatched first,
851   // along with the subsequent events (i.e. touch-release, scroll-end, and
852   // gesture-end).
853   const EventFilterRecorder::Events& events = recorder.events();
854   EXPECT_EQ(
855       "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
856       "GESTURE_SCROLL_END GESTURE_END",
857       EventTypesToString(events));
858   ASSERT_EQ(2u, recorder.touch_locations().size());
859   EXPECT_EQ(gfx::Point(-40, 10).ToString(),
860             recorder.touch_locations()[0].ToString());
861   EXPECT_EQ(gfx::Point(-40, 10).ToString(),
862             recorder.touch_locations()[1].ToString());
863 }
864
865 // Tests that a 'held' touch-event does contribute to gesture event when it is
866 // dispatched.
867 TEST_F(WindowEventDispatcherTest, HeldTouchMoveContributesToGesture) {
868   EventFilterRecorder recorder;
869   root_window()->AddPreTargetHandler(&recorder);
870
871   const gfx::Point location(20, 20);
872   ui::TouchEvent press(
873       ui::ET_TOUCH_PRESSED, location, 0, ui::EventTimeForNow());
874   DispatchEventUsingWindowDispatcher(&press);
875   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_PRESSED));
876   recorder.Reset();
877
878   host()->dispatcher()->HoldPointerMoves();
879
880   ui::TouchEvent move(ui::ET_TOUCH_MOVED,
881                       location + gfx::Vector2d(100, 100),
882                       0,
883                       ui::EventTimeForNow());
884   DispatchEventUsingWindowDispatcher(&move);
885   EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
886   EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
887   recorder.Reset();
888
889   host()->dispatcher()->ReleasePointerMoves();
890   EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
891   RunAllPendingInMessageLoop();
892   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
893   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
894   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_UPDATE));
895
896   root_window()->RemovePreTargetHandler(&recorder);
897 }
898
899 // Tests that synthetic mouse events are ignored when mouse
900 // events are disabled.
901 TEST_F(WindowEventDispatcherTest, DispatchSyntheticMouseEvents) {
902   EventFilterRecorder recorder;
903   root_window()->AddPreTargetHandler(&recorder);
904
905   test::TestWindowDelegate delegate;
906   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
907       &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
908   window->Show();
909   window->SetCapture();
910
911   test::TestCursorClient cursor_client(root_window());
912
913   // Dispatch a non-synthetic mouse event when mouse events are enabled.
914   ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
915                         gfx::Point(10, 10), 0, 0);
916   DispatchEventUsingWindowDispatcher(&mouse1);
917   EXPECT_FALSE(recorder.events().empty());
918   recorder.Reset();
919
920   // Dispatch a synthetic mouse event when mouse events are enabled.
921   ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
922                         gfx::Point(10, 10), ui::EF_IS_SYNTHESIZED, 0);
923   DispatchEventUsingWindowDispatcher(&mouse2);
924   EXPECT_FALSE(recorder.events().empty());
925   recorder.Reset();
926
927   // Dispatch a synthetic mouse event when mouse events are disabled.
928   cursor_client.DisableMouseEvents();
929   DispatchEventUsingWindowDispatcher(&mouse2);
930   EXPECT_TRUE(recorder.events().empty());
931   root_window()->RemovePreTargetHandler(&recorder);
932 }
933
934 // Tests that a mouse-move event is not synthesized when a mouse-button is down.
935 TEST_F(WindowEventDispatcherTest, DoNotSynthesizeWhileButtonDown) {
936   EventFilterRecorder recorder;
937   test::TestWindowDelegate delegate;
938   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
939       &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
940   window->Show();
941
942   window->AddPreTargetHandler(&recorder);
943   // Dispatch a non-synthetic mouse event when mouse events are enabled.
944   ui::MouseEvent mouse1(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
945                         gfx::Point(10, 10), ui::EF_LEFT_MOUSE_BUTTON,
946                         ui::EF_LEFT_MOUSE_BUTTON);
947   DispatchEventUsingWindowDispatcher(&mouse1);
948   ASSERT_EQ(1u, recorder.events().size());
949   EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder.events()[0]);
950   window->RemovePreTargetHandler(&recorder);
951   recorder.Reset();
952
953   // Move |window| away from underneath the cursor.
954   root_window()->AddPreTargetHandler(&recorder);
955   window->SetBounds(gfx::Rect(30, 30, 100, 100));
956   EXPECT_TRUE(recorder.events().empty());
957   RunAllPendingInMessageLoop();
958   EXPECT_TRUE(recorder.events().empty());
959   root_window()->RemovePreTargetHandler(&recorder);
960 }
961
962 #if defined(OS_WIN) && defined(ARCH_CPU_X86)
963 #define MAYBE(x) DISABLED_##x
964 #else
965 #define MAYBE(x) x
966 #endif
967
968 // Tests synthetic mouse events generated when window bounds changes such that
969 // the cursor previously outside the window becomes inside, or vice versa.
970 // Do not synthesize events if the window ignores events or is invisible.
971 // Flaky on 32-bit Windows bots.  http://crbug.com/388272
972 TEST_F(WindowEventDispatcherTest,
973        MAYBE(SynthesizeMouseEventsOnWindowBoundsChanged)) {
974   test::TestWindowDelegate delegate;
975   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
976       &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
977   window->Show();
978   window->SetCapture();
979
980   EventFilterRecorder recorder;
981   window->AddPreTargetHandler(&recorder);
982
983   // Dispatch a non-synthetic mouse event to place cursor inside window bounds.
984   ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
985                        gfx::Point(10, 10), 0, 0);
986   DispatchEventUsingWindowDispatcher(&mouse);
987   EXPECT_FALSE(recorder.events().empty());
988   recorder.Reset();
989
990   // Update the window bounds so that cursor is now outside the window.
991   // This should trigger a synthetic MOVED event.
992   gfx::Rect bounds1(20, 20, 100, 100);
993   window->SetBounds(bounds1);
994   RunAllPendingInMessageLoop();
995   ASSERT_FALSE(recorder.events().empty());
996   ASSERT_FALSE(recorder.mouse_event_flags().empty());
997   EXPECT_EQ(ui::ET_MOUSE_MOVED, recorder.events().back());
998   EXPECT_EQ(ui::EF_IS_SYNTHESIZED, recorder.mouse_event_flags().back());
999   recorder.Reset();
1000
1001   // Set window to ignore events.
1002   window->set_ignore_events(true);
1003
1004   // Update the window bounds so that cursor is back inside the window.
1005   // This should not trigger a synthetic event.
1006   gfx::Rect bounds2(5, 5, 100, 100);
1007   window->SetBounds(bounds2);
1008   RunAllPendingInMessageLoop();
1009   EXPECT_TRUE(recorder.events().empty());
1010   recorder.Reset();
1011
1012   // Set window to accept events but invisible.
1013   window->set_ignore_events(false);
1014   window->Hide();
1015   recorder.Reset();
1016
1017   // Update the window bounds so that cursor is outside the window.
1018   // This should not trigger a synthetic event.
1019   window->SetBounds(bounds1);
1020   RunAllPendingInMessageLoop();
1021   EXPECT_TRUE(recorder.events().empty());
1022 }
1023
1024 // Tests that a mouse exit is dispatched to the last known cursor location
1025 // when the cursor becomes invisible.
1026 TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenCursorHidden) {
1027   EventFilterRecorder recorder;
1028   root_window()->AddPreTargetHandler(&recorder);
1029
1030   test::TestWindowDelegate delegate;
1031   gfx::Point window_origin(7, 18);
1032   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1033       &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
1034       root_window()));
1035   window->Show();
1036
1037   // Dispatch a mouse move event into the window.
1038   gfx::Point mouse_location(gfx::Point(15, 25));
1039   ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location,
1040                         mouse_location, 0, 0);
1041   EXPECT_TRUE(recorder.events().empty());
1042   DispatchEventUsingWindowDispatcher(&mouse1);
1043   EXPECT_FALSE(recorder.events().empty());
1044   recorder.Reset();
1045
1046   // Hide the cursor and verify a mouse exit was dispatched.
1047   host()->OnCursorVisibilityChanged(false);
1048   EXPECT_FALSE(recorder.events().empty());
1049   EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events()));
1050
1051   // Verify the mouse exit was dispatched at the correct location
1052   // (in the correct coordinate space).
1053   int translated_x = mouse_location.x() - window_origin.x();
1054   int translated_y = mouse_location.y() - window_origin.y();
1055   gfx::Point translated_point(translated_x, translated_y);
1056   EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());
1057   root_window()->RemovePreTargetHandler(&recorder);
1058 }
1059
1060 // Tests that a synthetic mouse exit is dispatched to the last known cursor
1061 // location after mouse events are disabled on the cursor client.
1062 TEST_F(WindowEventDispatcherTest,
1063        DispatchSyntheticMouseExitAfterMouseEventsDisabled) {
1064   EventFilterRecorder recorder;
1065   root_window()->AddPreTargetHandler(&recorder);
1066
1067   test::TestWindowDelegate delegate;
1068   gfx::Point window_origin(7, 18);
1069   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1070       &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
1071       root_window()));
1072   window->Show();
1073
1074   // Dispatch a mouse move event into the window.
1075   gfx::Point mouse_location(gfx::Point(15, 25));
1076   ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location,
1077                         mouse_location, 0, 0);
1078   EXPECT_TRUE(recorder.events().empty());
1079   DispatchEventUsingWindowDispatcher(&mouse1);
1080   EXPECT_FALSE(recorder.events().empty());
1081   recorder.Reset();
1082
1083   test::TestCursorClient cursor_client(root_window());
1084   cursor_client.DisableMouseEvents();
1085
1086   gfx::Point mouse_exit_location(gfx::Point(150, 150));
1087   ui::MouseEvent mouse2(ui::ET_MOUSE_EXITED, gfx::Point(150, 150),
1088                         gfx::Point(150, 150), ui::EF_IS_SYNTHESIZED, 0);
1089   DispatchEventUsingWindowDispatcher(&mouse2);
1090
1091   EXPECT_FALSE(recorder.events().empty());
1092   // We get the mouse exited event twice in our filter. Once during the
1093   // predispatch phase and during the actual dispatch.
1094   EXPECT_EQ("MOUSE_EXITED MOUSE_EXITED", EventTypesToString(recorder.events()));
1095
1096   // Verify the mouse exit was dispatched at the correct location
1097   // (in the correct coordinate space).
1098   int translated_x = mouse_exit_location.x() - window_origin.x();
1099   int translated_y = mouse_exit_location.y() - window_origin.y();
1100   gfx::Point translated_point(translated_x, translated_y);
1101   EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());
1102   root_window()->RemovePreTargetHandler(&recorder);
1103 }
1104
1105 class DeletingEventFilter : public ui::EventHandler {
1106  public:
1107   DeletingEventFilter()
1108       : delete_during_pre_handle_(false) {}
1109   virtual ~DeletingEventFilter() {}
1110
1111   void Reset(bool delete_during_pre_handle) {
1112     delete_during_pre_handle_ = delete_during_pre_handle;
1113   }
1114
1115  private:
1116   // Overridden from ui::EventHandler:
1117   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
1118     if (delete_during_pre_handle_)
1119       delete event->target();
1120   }
1121
1122   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1123     if (delete_during_pre_handle_)
1124       delete event->target();
1125   }
1126
1127   bool delete_during_pre_handle_;
1128
1129   DISALLOW_COPY_AND_ASSIGN(DeletingEventFilter);
1130 };
1131
1132 class DeletingWindowDelegate : public test::TestWindowDelegate {
1133  public:
1134   DeletingWindowDelegate()
1135       : window_(NULL),
1136         delete_during_handle_(false),
1137         got_event_(false) {}
1138   virtual ~DeletingWindowDelegate() {}
1139
1140   void Reset(Window* window, bool delete_during_handle) {
1141     window_ = window;
1142     delete_during_handle_ = delete_during_handle;
1143     got_event_ = false;
1144   }
1145   bool got_event() const { return got_event_; }
1146
1147  private:
1148   // Overridden from WindowDelegate:
1149   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
1150     if (delete_during_handle_)
1151       delete window_;
1152     got_event_ = true;
1153   }
1154
1155   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1156     if (delete_during_handle_)
1157       delete window_;
1158     got_event_ = true;
1159   }
1160
1161   Window* window_;
1162   bool delete_during_handle_;
1163   bool got_event_;
1164
1165   DISALLOW_COPY_AND_ASSIGN(DeletingWindowDelegate);
1166 };
1167
1168 TEST_F(WindowEventDispatcherTest, DeleteWindowDuringDispatch) {
1169   // Verifies that we can delete a window during each phase of event handling.
1170   // Deleting the window should not cause a crash, only prevent further
1171   // processing from occurring.
1172   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
1173   DeletingWindowDelegate d11;
1174   Window* w11 = CreateNormalWindow(11, w1.get(), &d11);
1175   WindowTracker tracker;
1176   DeletingEventFilter w1_filter;
1177   w1->AddPreTargetHandler(&w1_filter);
1178   client::GetFocusClient(w1.get())->FocusWindow(w11);
1179
1180   ui::test::EventGenerator generator(root_window(), w11);
1181
1182   // First up, no one deletes anything.
1183   tracker.Add(w11);
1184   d11.Reset(w11, false);
1185
1186   generator.PressLeftButton();
1187   EXPECT_TRUE(tracker.Contains(w11));
1188   EXPECT_TRUE(d11.got_event());
1189   generator.ReleaseLeftButton();
1190
1191   // Delegate deletes w11. This will prevent the post-handle step from applying.
1192   w1_filter.Reset(false);
1193   d11.Reset(w11, true);
1194   generator.PressKey(ui::VKEY_A, 0);
1195   EXPECT_FALSE(tracker.Contains(w11));
1196   EXPECT_TRUE(d11.got_event());
1197
1198   // Pre-handle step deletes w11. This will prevent the delegate and the post-
1199   // handle steps from applying.
1200   w11 = CreateNormalWindow(11, w1.get(), &d11);
1201   w1_filter.Reset(true);
1202   d11.Reset(w11, false);
1203   generator.PressLeftButton();
1204   EXPECT_FALSE(tracker.Contains(w11));
1205   EXPECT_FALSE(d11.got_event());
1206 }
1207
1208 namespace {
1209
1210 // A window delegate that detaches the parent of the target's parent window when
1211 // it receives a tap event.
1212 class DetachesParentOnTapDelegate : public test::TestWindowDelegate {
1213  public:
1214   DetachesParentOnTapDelegate() {}
1215   virtual ~DetachesParentOnTapDelegate() {}
1216
1217  private:
1218   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1219     if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
1220       event->SetHandled();
1221       return;
1222     }
1223
1224     if (event->type() == ui::ET_GESTURE_TAP) {
1225       Window* parent = static_cast<Window*>(event->target())->parent();
1226       parent->parent()->RemoveChild(parent);
1227       event->SetHandled();
1228     }
1229   }
1230
1231   DISALLOW_COPY_AND_ASSIGN(DetachesParentOnTapDelegate);
1232 };
1233
1234 }  // namespace
1235
1236 // Tests that the gesture recognizer is reset for all child windows when a
1237 // window hides. No expectations, just checks that the test does not crash.
1238 TEST_F(WindowEventDispatcherTest,
1239        GestureRecognizerResetsTargetWhenParentHides) {
1240   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
1241   DetachesParentOnTapDelegate delegate;
1242   scoped_ptr<Window> parent(CreateNormalWindow(22, w1.get(), NULL));
1243   Window* child = CreateNormalWindow(11, parent.get(), &delegate);
1244   ui::test::EventGenerator generator(root_window(), child);
1245   generator.GestureTapAt(gfx::Point(40, 40));
1246 }
1247
1248 namespace {
1249
1250 // A window delegate that processes nested gestures on tap.
1251 class NestedGestureDelegate : public test::TestWindowDelegate {
1252  public:
1253   NestedGestureDelegate(ui::test::EventGenerator* generator,
1254                         const gfx::Point tap_location)
1255       : generator_(generator),
1256         tap_location_(tap_location),
1257         gesture_end_count_(0) {}
1258   virtual ~NestedGestureDelegate() {}
1259
1260   int gesture_end_count() const { return gesture_end_count_; }
1261
1262  private:
1263   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1264     switch (event->type()) {
1265       case ui::ET_GESTURE_TAP_DOWN:
1266         event->SetHandled();
1267         break;
1268       case ui::ET_GESTURE_TAP:
1269         if (generator_)
1270           generator_->GestureTapAt(tap_location_);
1271         event->SetHandled();
1272         break;
1273       case ui::ET_GESTURE_END:
1274         ++gesture_end_count_;
1275         break;
1276       default:
1277         break;
1278     }
1279   }
1280
1281   ui::test::EventGenerator* generator_;
1282   const gfx::Point tap_location_;
1283   int gesture_end_count_;
1284   DISALLOW_COPY_AND_ASSIGN(NestedGestureDelegate);
1285 };
1286
1287 }  // namespace
1288
1289 // Tests that gesture end is delivered after nested gesture processing.
1290 TEST_F(WindowEventDispatcherTest, GestureEndDeliveredAfterNestedGestures) {
1291   NestedGestureDelegate d1(NULL, gfx::Point());
1292   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &d1));
1293   w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1294
1295   ui::test::EventGenerator nested_generator(root_window(), w1.get());
1296   NestedGestureDelegate d2(&nested_generator, w1->bounds().CenterPoint());
1297   scoped_ptr<Window> w2(CreateNormalWindow(1, root_window(), &d2));
1298   w2->SetBounds(gfx::Rect(100, 0, 100, 100));
1299
1300   // Tap on w2 which triggers nested gestures for w1.
1301   ui::test::EventGenerator generator(root_window(), w2.get());
1302   generator.GestureTapAt(w2->bounds().CenterPoint());
1303
1304   // Both windows should get their gesture end events.
1305   EXPECT_EQ(1, d1.gesture_end_count());
1306   EXPECT_EQ(1, d2.gesture_end_count());
1307 }
1308
1309 // Tests whether we can repost the Tap down gesture event.
1310 TEST_F(WindowEventDispatcherTest, RepostTapdownGestureTest) {
1311   EventFilterRecorder recorder;
1312   root_window()->AddPreTargetHandler(&recorder);
1313
1314   test::TestWindowDelegate delegate;
1315   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1316       &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
1317
1318   ui::GestureEventDetails details(ui::ET_GESTURE_TAP_DOWN, 0.0f, 0.0f);
1319   gfx::Point point(10, 10);
1320   ui::GestureEvent event(point.x(),
1321                          point.y(),
1322                          0,
1323                          ui::EventTimeForNow(),
1324                          details);
1325   host()->dispatcher()->RepostEvent(event);
1326   RunAllPendingInMessageLoop();
1327   // TODO(rbyers): Currently disabled - crbug.com/170987
1328   EXPECT_FALSE(EventTypesToString(recorder.events()).find("GESTURE_TAP_DOWN") !=
1329               std::string::npos);
1330   recorder.Reset();
1331   root_window()->RemovePreTargetHandler(&recorder);
1332 }
1333
1334 // This class inherits from the EventFilterRecorder class which provides a
1335 // facility to record events. This class additionally provides a facility to
1336 // repost the ET_GESTURE_TAP_DOWN gesture to the target window and records
1337 // events after that.
1338 class RepostGestureEventRecorder : public EventFilterRecorder {
1339  public:
1340   RepostGestureEventRecorder(aura::Window* repost_source,
1341                              aura::Window* repost_target)
1342       : repost_source_(repost_source),
1343         repost_target_(repost_target),
1344         reposted_(false),
1345         done_cleanup_(false) {}
1346
1347   virtual ~RepostGestureEventRecorder() {}
1348
1349   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
1350     if (reposted_ && event->type() == ui::ET_TOUCH_PRESSED) {
1351       done_cleanup_ = true;
1352       Reset();
1353     }
1354     EventFilterRecorder::OnTouchEvent(event);
1355   }
1356
1357   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1358     EXPECT_EQ(done_cleanup_ ? repost_target_ : repost_source_, event->target());
1359     if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
1360       if (!reposted_) {
1361         EXPECT_NE(repost_target_, event->target());
1362         reposted_ = true;
1363         repost_target_->GetHost()->dispatcher()->RepostEvent(*event);
1364         // Ensure that the reposted gesture event above goes to the
1365         // repost_target_;
1366         repost_source_->GetRootWindow()->RemoveChild(repost_source_);
1367         return;
1368       }
1369     }
1370     EventFilterRecorder::OnGestureEvent(event);
1371   }
1372
1373   // Ignore mouse events as they don't fire at all times. This causes
1374   // the GestureRepostEventOrder test to fail randomly.
1375   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {}
1376
1377  private:
1378   aura::Window* repost_source_;
1379   aura::Window* repost_target_;
1380   // set to true if we reposted the ET_GESTURE_TAP_DOWN event.
1381   bool reposted_;
1382   // set true if we're done cleaning up after hiding repost_source_;
1383   bool done_cleanup_;
1384   DISALLOW_COPY_AND_ASSIGN(RepostGestureEventRecorder);
1385 };
1386
1387 // Tests whether events which are generated after the reposted gesture event
1388 // are received after that. In this case the scroll sequence events should
1389 // be received after the reposted gesture event.
1390 TEST_F(WindowEventDispatcherTest, GestureRepostEventOrder) {
1391   // Expected events at the end for the repost_target window defined below.
1392   const char kExpectedTargetEvents[] =
1393     // TODO)(rbyers): Gesture event reposting is disabled - crbug.com/279039.
1394     // "GESTURE_BEGIN GESTURE_TAP_DOWN "
1395     "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
1396     "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE TOUCH_MOVED "
1397     "GESTURE_SCROLL_UPDATE TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
1398     "GESTURE_SCROLL_END GESTURE_END";
1399   // We create two windows.
1400   // The first window (repost_source) is the one to which the initial tap
1401   // gesture is sent. It reposts this event to the second window
1402   // (repost_target).
1403   // We then generate the scroll sequence for repost_target and look for two
1404   // ET_GESTURE_TAP_DOWN events in the event list at the end.
1405   test::TestWindowDelegate delegate;
1406   scoped_ptr<aura::Window> repost_target(CreateTestWindowWithDelegate(
1407       &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
1408
1409   scoped_ptr<aura::Window> repost_source(CreateTestWindowWithDelegate(
1410       &delegate, 1, gfx::Rect(0, 0, 50, 50), root_window()));
1411
1412   RepostGestureEventRecorder repost_event_recorder(repost_source.get(),
1413                                                    repost_target.get());
1414   root_window()->AddPreTargetHandler(&repost_event_recorder);
1415
1416   // Generate a tap down gesture for the repost_source. This will be reposted
1417   // to repost_target.
1418   ui::test::EventGenerator repost_generator(root_window(), repost_source.get());
1419   repost_generator.GestureTapAt(gfx::Point(40, 40));
1420   RunAllPendingInMessageLoop();
1421
1422   ui::test::EventGenerator scroll_generator(root_window(), repost_target.get());
1423   scroll_generator.GestureScrollSequence(
1424       gfx::Point(80, 80),
1425       gfx::Point(100, 100),
1426       base::TimeDelta::FromMilliseconds(100),
1427       3);
1428   RunAllPendingInMessageLoop();
1429
1430   int tap_down_count = 0;
1431   for (size_t i = 0; i < repost_event_recorder.events().size(); ++i) {
1432     if (repost_event_recorder.events()[i] == ui::ET_GESTURE_TAP_DOWN)
1433       ++tap_down_count;
1434   }
1435
1436   // We expect two tap down events. One from the repost and the other one from
1437   // the scroll sequence posted above.
1438   // TODO(rbyers): Currently disabled - crbug.com/170987
1439   EXPECT_EQ(1, tap_down_count);
1440
1441   EXPECT_EQ(kExpectedTargetEvents,
1442             EventTypesToString(repost_event_recorder.events()));
1443   root_window()->RemovePreTargetHandler(&repost_event_recorder);
1444 }
1445
1446 class OnMouseExitDeletingEventFilter : public EventFilterRecorder {
1447  public:
1448   OnMouseExitDeletingEventFilter() : window_to_delete_(NULL) {}
1449   virtual ~OnMouseExitDeletingEventFilter() {}
1450
1451   void set_window_to_delete(Window* window_to_delete) {
1452     window_to_delete_ = window_to_delete;
1453   }
1454
1455  private:
1456   // Overridden from ui::EventHandler:
1457   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1458     EventFilterRecorder::OnMouseEvent(event);
1459     if (window_to_delete_) {
1460       delete window_to_delete_;
1461       window_to_delete_ = NULL;
1462     }
1463   }
1464
1465   Window* window_to_delete_;
1466
1467   DISALLOW_COPY_AND_ASSIGN(OnMouseExitDeletingEventFilter);
1468 };
1469
1470 // Tests that RootWindow drops mouse-moved event that is supposed to be sent to
1471 // a child, but the child is destroyed because of the synthesized mouse-exit
1472 // event generated on the previous mouse_moved_handler_.
1473 TEST_F(WindowEventDispatcherTest, DeleteWindowDuringMouseMovedDispatch) {
1474   // Create window 1 and set its event filter. Window 1 will take ownership of
1475   // the event filter.
1476   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
1477   OnMouseExitDeletingEventFilter w1_filter;
1478   w1->AddPreTargetHandler(&w1_filter);
1479   w1->SetBounds(gfx::Rect(20, 20, 60, 60));
1480   EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());
1481
1482   ui::test::EventGenerator generator(root_window(), w1.get());
1483
1484   // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the
1485   // root window.
1486   generator.MoveMouseTo(51, 51);
1487   EXPECT_EQ(w1.get(), host()->dispatcher()->mouse_moved_handler());
1488
1489   // Create window 2 under the mouse cursor and stack it above window 1.
1490   Window* w2 = CreateNormalWindow(2, root_window(), NULL);
1491   w2->SetBounds(gfx::Rect(30, 30, 40, 40));
1492   root_window()->StackChildAbove(w2, w1.get());
1493
1494   // Set window 2 as the window that is to be deleted when a mouse-exited event
1495   // happens on window 1.
1496   w1_filter.set_window_to_delete(w2);
1497
1498   // Move mosue over window 2. This should generate a mouse-exited event for
1499   // window 1 resulting in deletion of window 2. The original mouse-moved event
1500   // that was targeted to window 2 should be dropped since window 2 is
1501   // destroyed. This test passes if no crash happens.
1502   generator.MoveMouseTo(52, 52);
1503   EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());
1504
1505   // Check events received by window 1.
1506   EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED MOUSE_EXITED",
1507             EventTypesToString(w1_filter.events()));
1508 }
1509
1510 namespace {
1511
1512 // Used to track if OnWindowDestroying() is invoked and if there is a valid
1513 // RootWindow at such time.
1514 class ValidRootDuringDestructionWindowObserver : public aura::WindowObserver {
1515  public:
1516   ValidRootDuringDestructionWindowObserver(bool* got_destroying,
1517                                            bool* has_valid_root)
1518       : got_destroying_(got_destroying),
1519         has_valid_root_(has_valid_root) {
1520   }
1521
1522   // WindowObserver:
1523   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
1524     *got_destroying_ = true;
1525     *has_valid_root_ = (window->GetRootWindow() != NULL);
1526   }
1527
1528  private:
1529   bool* got_destroying_;
1530   bool* has_valid_root_;
1531
1532   DISALLOW_COPY_AND_ASSIGN(ValidRootDuringDestructionWindowObserver);
1533 };
1534
1535 }  // namespace
1536
1537 // Verifies GetRootWindow() from ~Window returns a valid root.
1538 TEST_F(WindowEventDispatcherTest, ValidRootDuringDestruction) {
1539   bool got_destroying = false;
1540   bool has_valid_root = false;
1541   ValidRootDuringDestructionWindowObserver observer(&got_destroying,
1542                                                     &has_valid_root);
1543   {
1544     scoped_ptr<WindowTreeHost> host(
1545         WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100)));
1546     host->InitHost();
1547     // Owned by WindowEventDispatcher.
1548     Window* w1 = CreateNormalWindow(1, host->window(), NULL);
1549     w1->AddObserver(&observer);
1550   }
1551   EXPECT_TRUE(got_destroying);
1552   EXPECT_TRUE(has_valid_root);
1553 }
1554
1555 namespace {
1556
1557 // See description above DontResetHeldEvent for details.
1558 class DontResetHeldEventWindowDelegate : public test::TestWindowDelegate {
1559  public:
1560   explicit DontResetHeldEventWindowDelegate(aura::Window* root)
1561       : root_(root),
1562         mouse_event_count_(0) {}
1563   virtual ~DontResetHeldEventWindowDelegate() {}
1564
1565   int mouse_event_count() const { return mouse_event_count_; }
1566
1567   // TestWindowDelegate:
1568   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1569     if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 &&
1570         mouse_event_count_++ == 0) {
1571       ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED,
1572                                  gfx::Point(10, 10), gfx::Point(10, 10),
1573                                  ui::EF_SHIFT_DOWN, 0);
1574       root_->GetHost()->dispatcher()->RepostEvent(mouse_event);
1575     }
1576   }
1577
1578  private:
1579   Window* root_;
1580   int mouse_event_count_;
1581
1582   DISALLOW_COPY_AND_ASSIGN(DontResetHeldEventWindowDelegate);
1583 };
1584
1585 }  // namespace
1586
1587 // Verifies RootWindow doesn't reset |RootWindow::held_repostable_event_| after
1588 // dispatching. This is done by using DontResetHeldEventWindowDelegate, which
1589 // tracks the number of events with ui::EF_SHIFT_DOWN set (all reposted events
1590 // have EF_SHIFT_DOWN). When the first event is seen RepostEvent() is used to
1591 // schedule another reposted event.
1592 TEST_F(WindowEventDispatcherTest, DontResetHeldEvent) {
1593   DontResetHeldEventWindowDelegate delegate(root_window());
1594   scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
1595   w1->SetBounds(gfx::Rect(0, 0, 40, 40));
1596   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
1597                          gfx::Point(10, 10), gfx::Point(10, 10),
1598                          ui::EF_SHIFT_DOWN, 0);
1599   root_window()->GetHost()->dispatcher()->RepostEvent(pressed);
1600   ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED,
1601                           gfx::Point(10, 10), gfx::Point(10, 10), 0, 0);
1602   // Dispatch an event to flush event scheduled by way of RepostEvent().
1603   DispatchEventUsingWindowDispatcher(&pressed2);
1604   // Delegate should have seen reposted event (identified by way of
1605   // EF_SHIFT_DOWN). Dispatch another event to flush the second
1606   // RepostedEvent().
1607   EXPECT_EQ(1, delegate.mouse_event_count());
1608   DispatchEventUsingWindowDispatcher(&pressed2);
1609   EXPECT_EQ(2, delegate.mouse_event_count());
1610 }
1611
1612 namespace {
1613
1614 // See description above DeleteHostFromHeldMouseEvent for details.
1615 class DeleteHostFromHeldMouseEventDelegate
1616     : public test::TestWindowDelegate {
1617  public:
1618   explicit DeleteHostFromHeldMouseEventDelegate(WindowTreeHost* host)
1619       : host_(host),
1620         got_mouse_event_(false),
1621         got_destroy_(false) {
1622   }
1623   virtual ~DeleteHostFromHeldMouseEventDelegate() {}
1624
1625   bool got_mouse_event() const { return got_mouse_event_; }
1626   bool got_destroy() const { return got_destroy_; }
1627
1628   // TestWindowDelegate:
1629   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1630     if ((event->flags() & ui::EF_SHIFT_DOWN) != 0) {
1631       got_mouse_event_ = true;
1632       delete host_;
1633     }
1634   }
1635   virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1636     got_destroy_ = true;
1637   }
1638
1639  private:
1640   WindowTreeHost* host_;
1641   bool got_mouse_event_;
1642   bool got_destroy_;
1643
1644   DISALLOW_COPY_AND_ASSIGN(DeleteHostFromHeldMouseEventDelegate);
1645 };
1646
1647 }  // namespace
1648
1649 // Verifies if a WindowTreeHost is deleted from dispatching a held mouse event
1650 // we don't crash.
1651 TEST_F(WindowEventDispatcherTest, DeleteHostFromHeldMouseEvent) {
1652   // Should be deleted by |delegate|.
1653   WindowTreeHost* h2 = WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100));
1654   h2->InitHost();
1655   DeleteHostFromHeldMouseEventDelegate delegate(h2);
1656   // Owned by |h2|.
1657   Window* w1 = CreateNormalWindow(1, h2->window(), &delegate);
1658   w1->SetBounds(gfx::Rect(0, 0, 40, 40));
1659   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
1660                          gfx::Point(10, 10), gfx::Point(10, 10),
1661                          ui::EF_SHIFT_DOWN, 0);
1662   h2->dispatcher()->RepostEvent(pressed);
1663   // RunAllPendingInMessageLoop() to make sure the |pressed| is run.
1664   RunAllPendingInMessageLoop();
1665   EXPECT_TRUE(delegate.got_mouse_event());
1666   EXPECT_TRUE(delegate.got_destroy());
1667 }
1668
1669 TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveTouches) {
1670   EventFilterRecorder recorder;
1671   root_window()->AddPreTargetHandler(&recorder);
1672
1673   test::TestWindowDelegate delegate;
1674   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1675       &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
1676
1677   gfx::Point position1 = root_window()->bounds().origin();
1678   ui::TouchEvent press(
1679       ui::ET_TOUCH_PRESSED, position1, 0, ui::EventTimeForNow());
1680   DispatchEventUsingWindowDispatcher(&press);
1681
1682   EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN",
1683             EventTypesToString(recorder.GetAndResetEvents()));
1684
1685   window->Hide();
1686
1687   EXPECT_EQ(ui::ET_TOUCH_CANCELLED, recorder.events()[0]);
1688   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_TAP_CANCEL));
1689   EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_END));
1690   EXPECT_EQ(3U, recorder.events().size());
1691   root_window()->RemovePreTargetHandler(&recorder);
1692 }
1693
1694 TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveGestures) {
1695   EventFilterRecorder recorder;
1696   root_window()->AddPreTargetHandler(&recorder);
1697
1698   test::TestWindowDelegate delegate;
1699   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1700       &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
1701
1702   gfx::Point position1 = root_window()->bounds().origin();
1703   gfx::Point position2 = root_window()->bounds().CenterPoint();
1704   ui::TouchEvent press(
1705       ui::ET_TOUCH_PRESSED, position1, 0, ui::EventTimeForNow());
1706   DispatchEventUsingWindowDispatcher(&press);
1707
1708   ui::TouchEvent move(
1709       ui::ET_TOUCH_MOVED, position2, 0, ui::EventTimeForNow());
1710   DispatchEventUsingWindowDispatcher(&move);
1711
1712   ui::TouchEvent press2(
1713       ui::ET_TOUCH_PRESSED, position1, 1, ui::EventTimeForNow());
1714   DispatchEventUsingWindowDispatcher(&press2);
1715
1716   // TODO(tdresser): once the unified Gesture Recognizer has stuck, remove the
1717   // special casing here. See crbug.com/332418 for details.
1718   std::string expected =
1719       "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
1720       "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
1721       "TOUCH_PRESSED GESTURE_BEGIN GESTURE_PINCH_BEGIN";
1722
1723   std::string expected_ugr =
1724       "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
1725       "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
1726       "TOUCH_PRESSED GESTURE_BEGIN";
1727
1728   std::string events_string = EventTypesToString(recorder.GetAndResetEvents());
1729   EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));
1730
1731   window->Hide();
1732
1733   expected =
1734       "TOUCH_CANCELLED GESTURE_PINCH_END GESTURE_END TOUCH_CANCELLED "
1735       "GESTURE_SCROLL_END GESTURE_END";
1736   expected_ugr =
1737       "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END TOUCH_CANCELLED "
1738       "GESTURE_END";
1739
1740   events_string = EventTypesToString(recorder.GetAndResetEvents());
1741   EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));
1742
1743   root_window()->RemovePreTargetHandler(&recorder);
1744 }
1745
1746 // Places two windows side by side. Presses down on one window, and starts a
1747 // scroll. Sets capture on the other window and ensures that the "ending" events
1748 // aren't sent to the window which gained capture.
1749 TEST_F(WindowEventDispatcherTest, EndingEventDoesntRetarget) {
1750   EventFilterRecorder recorder1;
1751   EventFilterRecorder recorder2;
1752   scoped_ptr<Window> window1(CreateNormalWindow(1, root_window(), NULL));
1753   window1->SetBounds(gfx::Rect(0, 0, 40, 40));
1754
1755   scoped_ptr<Window> window2(CreateNormalWindow(2, root_window(), NULL));
1756   window2->SetBounds(gfx::Rect(40, 0, 40, 40));
1757
1758   window1->AddPreTargetHandler(&recorder1);
1759   window2->AddPreTargetHandler(&recorder2);
1760
1761   gfx::Point position = window1->bounds().origin();
1762   ui::TouchEvent press(
1763       ui::ET_TOUCH_PRESSED, position, 0, ui::EventTimeForNow());
1764   DispatchEventUsingWindowDispatcher(&press);
1765
1766   gfx::Point position2 = window1->bounds().CenterPoint();
1767   ui::TouchEvent move(
1768       ui::ET_TOUCH_MOVED, position2, 0, ui::EventTimeForNow());
1769   DispatchEventUsingWindowDispatcher(&move);
1770
1771   window2->SetCapture();
1772
1773   EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
1774             "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
1775             "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END",
1776             EventTypesToString(recorder1.events()));
1777
1778   EXPECT_TRUE(recorder2.events().empty());
1779 }
1780
1781 namespace {
1782
1783 // This class creates and manages a window which is destroyed as soon as
1784 // capture is lost. This is the case for the drag and drop capture window.
1785 class CaptureWindowTracker : public test::TestWindowDelegate {
1786  public:
1787   CaptureWindowTracker() {}
1788   virtual ~CaptureWindowTracker() {}
1789
1790   void CreateCaptureWindow(aura::Window* root_window) {
1791     capture_window_.reset(test::CreateTestWindowWithDelegate(
1792         this, -1234, gfx::Rect(20, 20, 20, 20), root_window));
1793     capture_window_->SetCapture();
1794   }
1795
1796   void reset() {
1797     capture_window_.reset();
1798   }
1799
1800   virtual void OnCaptureLost() OVERRIDE {
1801     capture_window_.reset();
1802   }
1803
1804   virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1805     TestWindowDelegate::OnWindowDestroyed(window);
1806     capture_window_.reset();
1807   }
1808
1809   aura::Window* capture_window() { return capture_window_.get(); }
1810
1811  private:
1812   scoped_ptr<aura::Window> capture_window_;
1813
1814   DISALLOW_COPY_AND_ASSIGN(CaptureWindowTracker);
1815 };
1816
1817 }
1818
1819 // Verifies handling loss of capture by the capture window being hidden.
1820 TEST_F(WindowEventDispatcherTest, CaptureWindowHidden) {
1821   CaptureWindowTracker capture_window_tracker;
1822   capture_window_tracker.CreateCaptureWindow(root_window());
1823   capture_window_tracker.capture_window()->Hide();
1824   EXPECT_EQ(NULL, capture_window_tracker.capture_window());
1825 }
1826
1827 // Verifies handling loss of capture by the capture window being destroyed.
1828 TEST_F(WindowEventDispatcherTest, CaptureWindowDestroyed) {
1829   CaptureWindowTracker capture_window_tracker;
1830   capture_window_tracker.CreateCaptureWindow(root_window());
1831   capture_window_tracker.reset();
1832   EXPECT_EQ(NULL, capture_window_tracker.capture_window());
1833 }
1834
1835 class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler {
1836  public:
1837   ExitMessageLoopOnMousePress() {}
1838   virtual ~ExitMessageLoopOnMousePress() {}
1839
1840  protected:
1841   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1842     ui::test::TestEventHandler::OnMouseEvent(event);
1843     if (event->type() == ui::ET_MOUSE_PRESSED)
1844       base::MessageLoopForUI::current()->Quit();
1845   }
1846
1847  private:
1848   DISALLOW_COPY_AND_ASSIGN(ExitMessageLoopOnMousePress);
1849 };
1850
1851 class WindowEventDispatcherTestWithMessageLoop
1852     : public WindowEventDispatcherTest {
1853  public:
1854   WindowEventDispatcherTestWithMessageLoop() {}
1855   virtual ~WindowEventDispatcherTestWithMessageLoop() {}
1856
1857   void RunTest() {
1858     // Reset any event the window may have received when bringing up the window
1859     // (e.g. mouse-move events if the mouse cursor is over the window).
1860     handler_.Reset();
1861
1862     // Start a nested message-loop, post an event to be dispatched, and then
1863     // terminate the message-loop. When the message-loop unwinds and gets back,
1864     // the reposted event should not have fired.
1865     scoped_ptr<ui::MouseEvent> mouse(new ui::MouseEvent(ui::ET_MOUSE_PRESSED,
1866                                                         gfx::Point(10, 10),
1867                                                         gfx::Point(10, 10),
1868                                                         ui::EF_NONE,
1869                                                         ui::EF_NONE));
1870     message_loop()->PostTask(
1871         FROM_HERE,
1872         base::Bind(&WindowEventDispatcherTestWithMessageLoop::RepostEventHelper,
1873                    host()->dispatcher(),
1874                    base::Passed(&mouse)));
1875     message_loop()->PostTask(FROM_HERE, message_loop()->QuitClosure());
1876
1877     base::MessageLoop::ScopedNestableTaskAllower allow(message_loop());
1878     base::RunLoop loop;
1879     loop.Run();
1880     EXPECT_EQ(0, handler_.num_mouse_events());
1881
1882     // Let the current message-loop run. The event-handler will terminate the
1883     // message-loop when it receives the reposted event.
1884   }
1885
1886   base::MessageLoop* message_loop() {
1887     return base::MessageLoopForUI::current();
1888   }
1889
1890  protected:
1891   virtual void SetUp() OVERRIDE {
1892     WindowEventDispatcherTest::SetUp();
1893     window_.reset(CreateNormalWindow(1, root_window(), NULL));
1894     window_->AddPreTargetHandler(&handler_);
1895   }
1896
1897   virtual void TearDown() OVERRIDE {
1898     window_.reset();
1899     WindowEventDispatcherTest::TearDown();
1900   }
1901
1902  private:
1903   // Used to avoid a copying |event| when binding to a closure.
1904   static void RepostEventHelper(WindowEventDispatcher* dispatcher,
1905                                 scoped_ptr<ui::MouseEvent> event) {
1906     dispatcher->RepostEvent(*event);
1907   }
1908
1909   scoped_ptr<Window> window_;
1910   ExitMessageLoopOnMousePress handler_;
1911
1912   DISALLOW_COPY_AND_ASSIGN(WindowEventDispatcherTestWithMessageLoop);
1913 };
1914
1915 TEST_F(WindowEventDispatcherTestWithMessageLoop, EventRepostedInNonNestedLoop) {
1916   CHECK(!message_loop()->is_running());
1917   // Perform the test in a callback, so that it runs after the message-loop
1918   // starts.
1919   message_loop()->PostTask(
1920       FROM_HERE, base::Bind(
1921           &WindowEventDispatcherTestWithMessageLoop::RunTest,
1922           base::Unretained(this)));
1923   message_loop()->Run();
1924 }
1925
1926 class WindowEventDispatcherTestInHighDPI : public WindowEventDispatcherTest {
1927  public:
1928   WindowEventDispatcherTestInHighDPI() {}
1929   virtual ~WindowEventDispatcherTestInHighDPI() {}
1930
1931  protected:
1932   virtual void SetUp() OVERRIDE {
1933     WindowEventDispatcherTest::SetUp();
1934     test_screen()->SetDeviceScaleFactor(2.f);
1935   }
1936 };
1937
1938 TEST_F(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
1939   test::TestWindowDelegate delegate;
1940   scoped_ptr<aura::Window> child(test::CreateTestWindowWithDelegate(&delegate,
1941       1234, gfx::Rect(20, 20, 100, 100), root_window()));
1942   child->Show();
1943
1944   ui::test::TestEventHandler handler_child;
1945   ui::test::TestEventHandler handler_root;
1946   root_window()->AddPreTargetHandler(&handler_root);
1947   child->AddPreTargetHandler(&handler_child);
1948
1949   {
1950     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
1951                         gfx::Point(30, 30), gfx::Point(30, 30),
1952                         ui::EF_NONE, ui::EF_NONE);
1953     DispatchEventUsingWindowDispatcher(&move);
1954     EXPECT_EQ(0, handler_child.num_mouse_events());
1955     EXPECT_EQ(1, handler_root.num_mouse_events());
1956   }
1957
1958   {
1959     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
1960                         gfx::Point(50, 50), gfx::Point(50, 50),
1961                         ui::EF_NONE, ui::EF_NONE);
1962     DispatchEventUsingWindowDispatcher(&move);
1963     // The child receives an ENTER, and a MOVED event.
1964     EXPECT_EQ(2, handler_child.num_mouse_events());
1965     // The root receives both the ENTER and the MOVED events dispatched to
1966     // |child|, as well as an EXIT event.
1967     EXPECT_EQ(3, handler_root.num_mouse_events());
1968   }
1969
1970   child->RemovePreTargetHandler(&handler_child);
1971   root_window()->RemovePreTargetHandler(&handler_root);
1972 }
1973
1974 TEST_F(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
1975   EventFilterRecorder recorder;
1976   root_window()->AddPreTargetHandler(&recorder);
1977   test::TestWindowDelegate delegate;
1978   HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
1979   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
1980       &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
1981   window->AddPreTargetHandler(&handler);
1982
1983   ui::test::EventGenerator generator(root_window());
1984   generator.GestureScrollSequence(
1985       gfx::Point(120, 120), gfx::Point(20, 120),
1986       base::TimeDelta::FromMilliseconds(100), 25);
1987
1988   // |handler| will have reset |filter| and started holding the touch-move
1989   // events when scrolling started. At the end of the scroll (i.e. upon
1990   // touch-release), the held touch-move event will have been dispatched first,
1991   // along with the subsequent events (i.e. touch-release, scroll-end, and
1992   // gesture-end).
1993   const EventFilterRecorder::Events& events = recorder.events();
1994   EXPECT_EQ(
1995       "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
1996       "GESTURE_SCROLL_END GESTURE_END",
1997       EventTypesToString(events));
1998   ASSERT_EQ(2u, recorder.touch_locations().size());
1999   EXPECT_EQ(gfx::Point(-40, 10).ToString(),
2000             recorder.touch_locations()[0].ToString());
2001   EXPECT_EQ(gfx::Point(-40, 10).ToString(),
2002             recorder.touch_locations()[1].ToString());
2003 }
2004
2005 class SelfDestructDelegate : public test::TestWindowDelegate {
2006  public:
2007   SelfDestructDelegate() {}
2008   virtual ~SelfDestructDelegate() {}
2009
2010   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
2011     window_.reset();
2012   }
2013
2014   void set_window(scoped_ptr<aura::Window> window) {
2015     window_ = window.Pass();
2016   }
2017   bool has_window() const { return !!window_.get(); }
2018
2019  private:
2020   scoped_ptr<aura::Window> window_;
2021   DISALLOW_COPY_AND_ASSIGN(SelfDestructDelegate);
2022 };
2023
2024 TEST_F(WindowEventDispatcherTest, SynthesizedLocatedEvent) {
2025   ui::test::EventGenerator generator(root_window());
2026   generator.MoveMouseTo(10, 10);
2027   EXPECT_EQ("10,10",
2028             Env::GetInstance()->last_mouse_location().ToString());
2029
2030   // Synthesized event should not update the mouse location.
2031   ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
2032                          ui::EF_IS_SYNTHESIZED, 0);
2033   generator.Dispatch(&mouseev);
2034   EXPECT_EQ("10,10",
2035             Env::GetInstance()->last_mouse_location().ToString());
2036
2037   generator.MoveMouseTo(0, 0);
2038   EXPECT_EQ("0,0",
2039             Env::GetInstance()->last_mouse_location().ToString());
2040
2041   // Make sure the location gets updated when a syntheiszed enter
2042   // event destroyed the window.
2043   SelfDestructDelegate delegate;
2044   scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
2045       &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
2046   delegate.set_window(window.Pass());
2047   EXPECT_TRUE(delegate.has_window());
2048
2049   generator.MoveMouseTo(100, 100);
2050   EXPECT_FALSE(delegate.has_window());
2051   EXPECT_EQ("100,100",
2052             Env::GetInstance()->last_mouse_location().ToString());
2053 }
2054
2055 class StaticFocusClient : public client::FocusClient {
2056  public:
2057   explicit StaticFocusClient(Window* focused)
2058       : focused_(focused) {}
2059   virtual ~StaticFocusClient() {}
2060
2061  private:
2062   // client::FocusClient:
2063   virtual void AddObserver(client::FocusChangeObserver* observer) OVERRIDE {}
2064   virtual void RemoveObserver(client::FocusChangeObserver* observer) OVERRIDE {}
2065   virtual void FocusWindow(Window* window) OVERRIDE {}
2066   virtual void ResetFocusWithinActiveWindow(Window* window) OVERRIDE {}
2067   virtual Window* GetFocusedWindow() OVERRIDE { return focused_; }
2068
2069   Window* focused_;
2070
2071   DISALLOW_COPY_AND_ASSIGN(StaticFocusClient);
2072 };
2073
2074 // Tests that host-cancel-mode event can be dispatched to a dispatcher safely
2075 // when the focused window does not live in the dispatcher's tree.
2076 TEST_F(WindowEventDispatcherTest, HostCancelModeWithFocusedWindowOutside) {
2077   test::TestWindowDelegate delegate;
2078   scoped_ptr<Window> focused(CreateTestWindowWithDelegate(&delegate, 123,
2079       gfx::Rect(20, 30, 100, 50), NULL));
2080   StaticFocusClient focus_client(focused.get());
2081   client::SetFocusClient(root_window(), &focus_client);
2082   EXPECT_FALSE(root_window()->Contains(focused.get()));
2083   EXPECT_EQ(focused.get(),
2084             client::GetFocusClient(root_window())->GetFocusedWindow());
2085   host()->dispatcher()->DispatchCancelModeEvent();
2086   EXPECT_EQ(focused.get(),
2087             client::GetFocusClient(root_window())->GetFocusedWindow());
2088 }
2089
2090 // Dispatches a mouse-move event to |target| when it receives a mouse-move
2091 // event.
2092 class DispatchEventHandler : public ui::EventHandler {
2093  public:
2094   explicit DispatchEventHandler(Window* target)
2095       : target_(target),
2096         dispatched_(false) {}
2097   virtual ~DispatchEventHandler() {}
2098
2099   bool dispatched() const { return dispatched_; }
2100  private:
2101   // ui::EventHandler:
2102   virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
2103     if (mouse->type() == ui::ET_MOUSE_MOVED) {
2104       ui::MouseEvent move(ui::ET_MOUSE_MOVED, target_->bounds().CenterPoint(),
2105           target_->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE);
2106       ui::EventDispatchDetails details =
2107           target_->GetHost()->dispatcher()->OnEventFromSource(&move);
2108       ASSERT_FALSE(details.dispatcher_destroyed);
2109       EXPECT_FALSE(details.target_destroyed);
2110       EXPECT_EQ(target_, move.target());
2111       dispatched_ = true;
2112     }
2113     ui::EventHandler::OnMouseEvent(mouse);
2114   }
2115
2116   Window* target_;
2117   bool dispatched_;
2118
2119   DISALLOW_COPY_AND_ASSIGN(DispatchEventHandler);
2120 };
2121
2122 // Moves |window| to |root_window| when it receives a mouse-move event.
2123 class MoveWindowHandler : public ui::EventHandler {
2124  public:
2125   MoveWindowHandler(Window* window, Window* root_window)
2126       : window_to_move_(window),
2127         root_window_to_move_to_(root_window) {}
2128   virtual ~MoveWindowHandler() {}
2129
2130  private:
2131   // ui::EventHandler:
2132   virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
2133     if (mouse->type() == ui::ET_MOUSE_MOVED) {
2134       root_window_to_move_to_->AddChild(window_to_move_);
2135     }
2136     ui::EventHandler::OnMouseEvent(mouse);
2137   }
2138
2139   Window* window_to_move_;
2140   Window* root_window_to_move_to_;
2141
2142   DISALLOW_COPY_AND_ASSIGN(MoveWindowHandler);
2143 };
2144
2145 // Tests that nested event dispatch works correctly if the target of the older
2146 // event being dispatched is moved to a different dispatcher in response to an
2147 // event in the inner loop.
2148 TEST_F(WindowEventDispatcherTest, NestedEventDispatchTargetMoved) {
2149   scoped_ptr<WindowTreeHost> second_host(
2150       WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
2151   second_host->InitHost();
2152   Window* second_root = second_host->window();
2153
2154   // Create two windows parented to |root_window()|.
2155   test::TestWindowDelegate delegate;
2156   scoped_ptr<Window> first(CreateTestWindowWithDelegate(&delegate, 123,
2157       gfx::Rect(20, 10, 10, 20), root_window()));
2158   scoped_ptr<Window> second(CreateTestWindowWithDelegate(&delegate, 234,
2159       gfx::Rect(40, 10, 50, 20), root_window()));
2160
2161   // Setup a handler on |first| so that it dispatches an event to |second| when
2162   // |first| receives an event.
2163   DispatchEventHandler dispatch_event(second.get());
2164   first->AddPreTargetHandler(&dispatch_event);
2165
2166   // Setup a handler on |second| so that it moves |first| into |second_root|
2167   // when |second| receives an event.
2168   MoveWindowHandler move_window(first.get(), second_root);
2169   second->AddPreTargetHandler(&move_window);
2170
2171   // Some sanity checks: |first| is inside |root_window()|'s tree.
2172   EXPECT_EQ(root_window(), first->GetRootWindow());
2173   // The two root windows are different.
2174   EXPECT_NE(root_window(), second_root);
2175
2176   // Dispatch an event to |first|.
2177   ui::MouseEvent move(ui::ET_MOUSE_MOVED, first->bounds().CenterPoint(),
2178                       first->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE);
2179   ui::EventDispatchDetails details =
2180       host()->dispatcher()->OnEventFromSource(&move);
2181   ASSERT_FALSE(details.dispatcher_destroyed);
2182   EXPECT_TRUE(details.target_destroyed);
2183   EXPECT_EQ(first.get(), move.target());
2184   EXPECT_TRUE(dispatch_event.dispatched());
2185   EXPECT_EQ(second_root, first->GetRootWindow());
2186
2187   first->RemovePreTargetHandler(&dispatch_event);
2188   second->RemovePreTargetHandler(&move_window);
2189 }
2190
2191 class AlwaysMouseDownInputStateLookup : public InputStateLookup {
2192  public:
2193   AlwaysMouseDownInputStateLookup() {}
2194   virtual ~AlwaysMouseDownInputStateLookup() {}
2195
2196  private:
2197   // InputStateLookup:
2198   virtual bool IsMouseButtonDown() const OVERRIDE { return true; }
2199
2200   DISALLOW_COPY_AND_ASSIGN(AlwaysMouseDownInputStateLookup);
2201 };
2202
2203 TEST_F(WindowEventDispatcherTest,
2204        CursorVisibilityChangedWhileCaptureWindowInAnotherDispatcher) {
2205   test::EventCountDelegate delegate;
2206   scoped_ptr<Window> window(CreateTestWindowWithDelegate(&delegate, 123,
2207       gfx::Rect(20, 10, 10, 20), root_window()));
2208   window->Show();
2209
2210   scoped_ptr<WindowTreeHost> second_host(
2211       WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
2212   second_host->InitHost();
2213   WindowEventDispatcher* second_dispatcher = second_host->dispatcher();
2214
2215   // Install an InputStateLookup on the Env that always claims that a
2216   // mouse-button is down.
2217   test::EnvTestHelper(Env::GetInstance()).SetInputStateLookup(
2218       scoped_ptr<InputStateLookup>(new AlwaysMouseDownInputStateLookup()));
2219
2220   window->SetCapture();
2221
2222   // Because the mouse button is down, setting the capture on |window| will set
2223   // it as the mouse-move handler for |root_window()|.
2224   EXPECT_EQ(window.get(), host()->dispatcher()->mouse_moved_handler());
2225
2226   // This does not set |window| as the mouse-move handler for the second
2227   // dispatcher.
2228   EXPECT_EQ(NULL, second_dispatcher->mouse_moved_handler());
2229
2230   // However, some capture-client updates the capture in each root-window on a
2231   // capture. Emulate that here. Because of this, the second dispatcher also has
2232   // |window| as the mouse-move handler.
2233   client::CaptureDelegate* second_capture_delegate = second_dispatcher;
2234   second_capture_delegate->UpdateCapture(NULL, window.get());
2235   EXPECT_EQ(window.get(), second_dispatcher->mouse_moved_handler());
2236
2237   // Reset the mouse-event counts for |window|.
2238   delegate.GetMouseMotionCountsAndReset();
2239
2240   // Notify both hosts that the cursor is now hidden. This should send a single
2241   // mouse-exit event to |window|.
2242   host()->OnCursorVisibilityChanged(false);
2243   second_host->OnCursorVisibilityChanged(false);
2244   EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset());
2245 }
2246
2247 TEST_F(WindowEventDispatcherTest,
2248        RedirectedEventToDifferentDispatcherLocation) {
2249   scoped_ptr<WindowTreeHost> second_host(
2250       WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
2251   second_host->InitHost();
2252   client::SetCaptureClient(second_host->window(),
2253                            client::GetCaptureClient(root_window()));
2254
2255   test::EventCountDelegate delegate;
2256   scoped_ptr<Window> window_first(CreateTestWindowWithDelegate(&delegate, 123,
2257       gfx::Rect(20, 10, 10, 20), root_window()));
2258   window_first->Show();
2259
2260   scoped_ptr<Window> window_second(CreateTestWindowWithDelegate(&delegate, 12,
2261       gfx::Rect(10, 10, 20, 30), second_host->window()));
2262   window_second->Show();
2263
2264   window_second->SetCapture();
2265   EXPECT_EQ(window_second.get(),
2266             client::GetCaptureWindow(root_window()));
2267
2268   // Send an event to the first host. Make sure it goes to |window_second| in
2269   // |second_host| instead (since it has capture).
2270   EventFilterRecorder recorder_first;
2271   window_first->AddPreTargetHandler(&recorder_first);
2272   EventFilterRecorder recorder_second;
2273   window_second->AddPreTargetHandler(&recorder_second);
2274   const gfx::Point event_location(25, 15);
2275   ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, event_location,
2276                        event_location, ui::EF_LEFT_MOUSE_BUTTON,
2277                        ui::EF_LEFT_MOUSE_BUTTON);
2278   DispatchEventUsingWindowDispatcher(&mouse);
2279   EXPECT_TRUE(recorder_first.events().empty());
2280   ASSERT_EQ(1u, recorder_second.events().size());
2281   EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder_second.events()[0]);
2282   EXPECT_EQ(event_location.ToString(),
2283             recorder_second.mouse_locations()[0].ToString());
2284 }
2285
2286 }  // namespace aura