Support multiple displays in EventGenerator
- Introduces EventGeneratorDelegates interface that abstracts coordinates
- Added AshEventGeneratorDelegates that uses screen
   coordinates in ash environment.
- Updates several ash tests to use new EventGenerator

I'll convert other tests in separate CL.

BUG=139024
TEST=covered by tests.

Review URL: https://chromiumcodereview.appspot.com/11691010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176392 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index 5517f3c..952b21fc 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -62,13 +62,13 @@
   return Shell::GetInstance()->display_manager();
 }
 
-// An event filter which moves the target window to the secondary root window
+// An event handler which moves the target window to the secondary root window
 // at pre-handle phase of a mouse release event.
-class MoveWindowByClickEventFilter : public ui::EventHandler {
+class MoveWindowByClickEventHandler : public ui::EventHandler {
  public:
-  explicit MoveWindowByClickEventFilter(aura::Window* target)
+  explicit MoveWindowByClickEventHandler(aura::Window* target)
       : target_(target) {}
-  virtual ~MoveWindowByClickEventFilter() {}
+  virtual ~MoveWindowByClickEventHandler() {}
 
  private:
   // ui::EventHandler overrides:
@@ -81,7 +81,43 @@
   }
 
   aura::Window* target_;
-  DISALLOW_COPY_AND_ASSIGN(MoveWindowByClickEventFilter);
+  DISALLOW_COPY_AND_ASSIGN(MoveWindowByClickEventHandler);
+};
+
+// An event handler which records the event's locations.
+class EventLocationRecordingEventHandler : public ui::EventHandler {
+ public:
+  explicit EventLocationRecordingEventHandler() {
+    reset();
+  }
+  virtual ~EventLocationRecordingEventHandler() {}
+
+  std::string GetLocationsAndReset() {
+    std::string result =
+        location_.ToString() + " " + root_location_.ToString();
+    reset();
+    return result;
+  }
+
+ private:
+  // ui::EventHandler overrides:
+  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+    if (event->type() == ui::ET_MOUSE_MOVED ||
+        event->type() == ui::ET_MOUSE_DRAGGED) {
+      location_ = event->location();
+      root_location_ = event->root_location();
+    }
+  }
+
+  void reset() {
+    location_.SetPoint(-999, -999);
+    root_location_.SetPoint(-999, -999);
+  }
+
+  gfx::Point root_location_;
+  gfx::Point location_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventLocationRecordingEventHandler);
 };
 
 }  // namespace
@@ -152,19 +188,17 @@
             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
   EXPECT_TRUE(wm::IsActiveWindow(widget_on_2nd->GetNativeView()));
 
-  aura::test::EventGenerator generator_1st(root_windows[0]);
-  aura::test::EventGenerator generator_2nd(root_windows[1]);
-
+  aura::test::EventGenerator& event_generator(GetEventGenerator());
   // Clicking a window changes the active window and active root window.
-  generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
-  generator_1st.ClickLeftButton();
+  event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
+  event_generator.ClickLeftButton();
 
   EXPECT_EQ(widget_on_1st->GetNativeView(),
             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
   EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
 
-  generator_2nd.MoveMouseToCenterOf(widget_on_2nd->GetNativeView());
-  generator_2nd.ClickLeftButton();
+  event_generator.MoveMouseToCenterOf(widget_on_2nd->GetNativeView());
+  event_generator.ClickLeftButton();
 
   EXPECT_EQ(widget_on_2nd->GetNativeView(),
             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
@@ -190,17 +224,18 @@
   EXPECT_EQ(root_windows[1], modal_widget->GetNativeView()->GetRootWindow());
   EXPECT_EQ(root_windows[1], Shell::GetActiveRootWindow());
 
+  aura::test::EventGenerator& event_generator(GetEventGenerator());
+
   // Clicking a widget on widget_on_1st display should not change activation.
-  aura::test::EventGenerator generator_1st(root_windows[0]);
-  generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
-  generator_1st.ClickLeftButton();
+  event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
+  event_generator.ClickLeftButton();
   EXPECT_TRUE(wm::IsActiveWindow(modal_widget->GetNativeView()));
   EXPECT_EQ(root_windows[1], Shell::GetActiveRootWindow());
 
   // Close system modal and so clicking a widget should work now.
   modal_widget->Close();
-  generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
-  generator_1st.ClickLeftButton();
+  event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
+  event_generator.ClickLeftButton();
   EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
   EXPECT_EQ(root_windows[0], Shell::GetActiveRootWindow());
 }
@@ -357,6 +392,7 @@
 
   EXPECT_EQ(r1_w1.get(),
             aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
+
   aura::test::EventGenerator generator2(root_windows[1]);
   generator2.MoveMouseToCenterOf(r2_w1.get());
   generator2.ClickLeftButton();
@@ -367,7 +403,8 @@
   // no mouse move event on Win.
   EXPECT_EQ("1 1 0", r1_d1.GetMouseMotionCountsAndReset());
   EXPECT_EQ("1 1", r1_d1.GetMouseButtonCountsAndReset());
-  // (15,15) on 1st display is (-985,15) on 2nd display.
+  // Emulate passive grab. (15,15) on 1st display is (-985,15) on 2nd
+  // display.
   generator2.MoveMouseTo(-985, 15);
   EXPECT_EQ("0 1 0", r1_d1.GetMouseMotionCountsAndReset());
 
@@ -381,7 +418,6 @@
   // mouse is already entered.
   EXPECT_EQ("0 1 0", r1_d2.GetMouseMotionCountsAndReset());
   EXPECT_EQ("1 1", r1_d2.GetMouseButtonCountsAndReset());
-
   r1_w2->ReleaseCapture();
   EXPECT_EQ(NULL, aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
   generator2.MoveMouseTo(15, 15);
@@ -434,13 +470,16 @@
   aura::test::EventCountDelegate delegate;
   scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate(
       &delegate, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
-  MoveWindowByClickEventFilter event_filter(window.get());
-  window->AddPreTargetHandler(&event_filter);
-  aura::test::EventGenerator generator(root_windows[0], window.get());
-  generator.ClickLeftButton();
+  MoveWindowByClickEventHandler event_handler(window.get());
+  window->AddPreTargetHandler(&event_handler);
+
+  aura::test::EventGenerator& event_generator(GetEventGenerator());
+
+  event_generator.MoveMouseToCenterOf(window.get());
+  event_generator.ClickLeftButton();
   // Both mouse pressed and released arrive at the window and its delegate.
   EXPECT_EQ("1 1", delegate.GetMouseButtonCountsAndReset());
-  // Also event_filter moves the window to another root at mouse release.
+  // Also event_handler moves the window to another root at mouse release.
   EXPECT_EQ(root_windows[1], window->GetRootWindow());
 }
 
@@ -592,11 +631,11 @@
   SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
   ASSERT_FALSE(tray->HasSystemBubble());
 
+  aura::test::EventGenerator& event_generator(GetEventGenerator());
+
   // Opens the tray by a dummy click event and makes sure that adding/removing
   // displays doesn't break anything.
-  aura::test::EventGenerator event_generator(
-      ash::Shell::GetInstance()->GetPrimaryRootWindow(),
-      tray->GetWidget()->GetNativeWindow());
+  event_generator.MoveMouseToCenterOf(tray->GetWidget()->GetNativeWindow());
   event_generator.ClickLeftButton();
   EXPECT_TRUE(tray->HasSystemBubble());
 
@@ -670,22 +709,24 @@
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
 
   // The lock window should get events on both root windows.
-  aura::test::EventGenerator generator1(root_windows[0]);
-  generator1.PressKey(ui::VKEY_A, 0);
-  generator1.ReleaseKey(ui::VKEY_A, 0);
+  aura::test::EventGenerator& event_generator(GetEventGenerator());
+
+  event_generator.set_current_root_window(root_windows[0]);
+  event_generator.PressKey(ui::VKEY_A, 0);
+  event_generator.ReleaseKey(ui::VKEY_A, 0);
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
   EXPECT_EQ("a", UTF16ToASCII(textfield->text()));
 
-  aura::test::EventGenerator generator2(root_windows[1]);
-  generator2.PressKey(ui::VKEY_B, 0);
-  generator2.ReleaseKey(ui::VKEY_B, 0);
+  event_generator.set_current_root_window(root_windows[1]);
+  event_generator.PressKey(ui::VKEY_B, 0);
+  event_generator.ReleaseKey(ui::VKEY_B, 0);
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
   EXPECT_EQ("ab", UTF16ToASCII(textfield->text()));
 
   // Deleting 2nd display. The lock window still should get the events.
   UpdateDisplay("100x100");
-  generator2.PressKey(ui::VKEY_C, 0);
-  generator2.ReleaseKey(ui::VKEY_C, 0);
+  event_generator.PressKey(ui::VKEY_C, 0);
+  event_generator.ReleaseKey(ui::VKEY_C, 0);
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
   EXPECT_EQ("abc", UTF16ToASCII(textfield->text()));
 
@@ -693,17 +734,46 @@
   // on both root windows.
   UpdateDisplay("100x100,200x200");
   root_windows = Shell::GetAllRootWindows();
-  generator1.PressKey(ui::VKEY_D, 0);
-  generator1.ReleaseKey(ui::VKEY_D, 0);
+  event_generator.set_current_root_window(root_windows[0]);
+  event_generator.PressKey(ui::VKEY_D, 0);
+  event_generator.ReleaseKey(ui::VKEY_D, 0);
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
   EXPECT_EQ("abcd", UTF16ToASCII(textfield->text()));
 
-  aura::test::EventGenerator generator22(root_windows[1]);
-  generator22.PressKey(ui::VKEY_E, 0);
-  generator22.ReleaseKey(ui::VKEY_E, 0);
+  event_generator.set_current_root_window(root_windows[1]);
+  event_generator.PressKey(ui::VKEY_E, 0);
+  event_generator.ReleaseKey(ui::VKEY_E, 0);
   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
   EXPECT_EQ("abcde", UTF16ToASCII(textfield->text()));
 }
 
+TEST_F(ExtendedDesktopTest, PassiveGrab) {
+  EventLocationRecordingEventHandler event_handler;
+  ash::Shell::GetInstance()->AddPreTargetHandler(&event_handler);
+
+  UpdateDisplay("300x300,200x200");
+
+  views::Widget* widget = CreateTestWidget(gfx::Rect(50, 50, 200, 200));
+  widget->Show();
+  ASSERT_EQ("50,50 200x200", widget->GetWindowBoundsInScreen().ToString());
+
+  aura::test::EventGenerator& generator(GetEventGenerator());
+  generator.MoveMouseTo(150, 150);
+  EXPECT_EQ("100,100 150,150", event_handler.GetLocationsAndReset());
+
+  generator.PressLeftButton();
+  generator.MoveMouseTo(400, 150);
+
+  EXPECT_EQ("350,100 400,150", event_handler.GetLocationsAndReset());
+
+  generator.ReleaseLeftButton();
+  EXPECT_EQ("-999,-999 -999,-999", event_handler.GetLocationsAndReset());
+
+  generator.MoveMouseTo(400, 150);
+  EXPECT_EQ("100,150 100,150", event_handler.GetLocationsAndReset());
+
+  ash::Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
+}
+
 }  // namespace internal
 }  // namespace ash