Home | History | Annotate | Download | only in ash
      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 "ash/display/display_controller.h"
      6 #include "ash/display/display_manager.h"
      7 #include "ash/root_window_controller.h"
      8 #include "ash/screen_ash.h"
      9 #include "ash/shell.h"
     10 #include "ash/shell_window_ids.h"
     11 #include "ash/system/tray/system_tray.h"
     12 #include "ash/test/ash_test_base.h"
     13 #include "ash/wm/coordinate_conversion.h"
     14 #include "ash/wm/window_cycle_controller.h"
     15 #include "ash/wm/window_properties.h"
     16 #include "ash/wm/window_util.h"
     17 #include "base/strings/string_util.h"
     18 #include "ui/aura/client/activation_client.h"
     19 #include "ui/aura/client/capture_client.h"
     20 #include "ui/aura/client/focus_client.h"
     21 #include "ui/aura/root_window.h"
     22 #include "ui/aura/test/event_generator.h"
     23 #include "ui/aura/test/test_windows.h"
     24 #include "ui/aura/test/window_test_api.h"
     25 #include "ui/aura/window.h"
     26 #include "ui/base/cursor/cursor.h"
     27 #include "ui/events/event_handler.h"
     28 #include "ui/gfx/display.h"
     29 #include "ui/gfx/screen.h"
     30 #include "ui/views/controls/textfield/textfield.h"
     31 #include "ui/views/widget/widget.h"
     32 #include "ui/views/widget/widget_delegate.h"
     33 
     34 namespace ash {
     35 namespace {
     36 
     37 void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
     38   DisplayLayout layout =
     39       Shell::GetInstance()->display_manager()->GetCurrentDisplayLayout();
     40   layout.position = position;
     41   Shell::GetInstance()->display_manager()->
     42       SetLayoutForCurrentDisplays(layout);
     43 }
     44 
     45 class ModalWidgetDelegate : public views::WidgetDelegateView {
     46  public:
     47   ModalWidgetDelegate() {}
     48   virtual ~ModalWidgetDelegate() {}
     49 
     50   // Overridden from views::WidgetDelegate:
     51   virtual views::View* GetContentsView() OVERRIDE {
     52     return this;
     53   }
     54   virtual ui::ModalType GetModalType() const OVERRIDE {
     55     return ui::MODAL_TYPE_SYSTEM;
     56   }
     57 
     58  private:
     59   DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate);
     60 };
     61 
     62 // An event handler which moves the target window to the secondary root window
     63 // at pre-handle phase of a mouse release event.
     64 class MoveWindowByClickEventHandler : public ui::EventHandler {
     65  public:
     66   explicit MoveWindowByClickEventHandler(aura::Window* target)
     67       : target_(target) {}
     68   virtual ~MoveWindowByClickEventHandler() {}
     69 
     70  private:
     71   // ui::EventHandler overrides:
     72   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
     73     if (event->type() == ui::ET_MOUSE_RELEASED) {
     74       aura::Window::Windows root_windows = Shell::GetAllRootWindows();
     75       DCHECK_LT(1u, root_windows.size());
     76       root_windows[1]->AddChild(target_);
     77     }
     78   }
     79 
     80   aura::Window* target_;
     81   DISALLOW_COPY_AND_ASSIGN(MoveWindowByClickEventHandler);
     82 };
     83 
     84 // An event handler which records the event's locations.
     85 class EventLocationRecordingEventHandler : public ui::EventHandler {
     86  public:
     87   explicit EventLocationRecordingEventHandler() {
     88     reset();
     89   }
     90   virtual ~EventLocationRecordingEventHandler() {}
     91 
     92   std::string GetLocationsAndReset() {
     93     std::string result =
     94         location_.ToString() + " " + root_location_.ToString();
     95     reset();
     96     return result;
     97   }
     98 
     99  private:
    100   // ui::EventHandler overrides:
    101   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
    102     if (event->type() == ui::ET_MOUSE_MOVED ||
    103         event->type() == ui::ET_MOUSE_DRAGGED) {
    104       location_ = event->location();
    105       root_location_ = event->root_location();
    106     }
    107   }
    108 
    109   void reset() {
    110     location_.SetPoint(-999, -999);
    111     root_location_.SetPoint(-999, -999);
    112   }
    113 
    114   gfx::Point root_location_;
    115   gfx::Point location_;
    116 
    117   DISALLOW_COPY_AND_ASSIGN(EventLocationRecordingEventHandler);
    118 };
    119 
    120 }  // namespace
    121 
    122 class ExtendedDesktopTest : public test::AshTestBase {
    123  public:
    124   views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
    125     return CreateTestWidgetWithParentAndContext(
    126         NULL, CurrentContext(), bounds, false);
    127   }
    128 
    129   views::Widget* CreateTestWidgetWithParent(views::Widget* parent,
    130                                             const gfx::Rect& bounds,
    131                                             bool child) {
    132     CHECK(parent);
    133     return CreateTestWidgetWithParentAndContext(parent, NULL, bounds, child);
    134   }
    135 
    136   views::Widget* CreateTestWidgetWithParentAndContext(views::Widget* parent,
    137                                                       gfx::NativeView context,
    138                                                       const gfx::Rect& bounds,
    139                                                       bool child) {
    140     views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    141     if (parent)
    142       params.parent = parent->GetNativeView();
    143     params.context = context;
    144     params.bounds = bounds;
    145     params.child = child;
    146     views::Widget* widget = new views::Widget;
    147     widget->Init(params);
    148     widget->Show();
    149     return widget;
    150   }
    151 };
    152 
    153 // Test conditions that root windows in extended desktop mode
    154 // must satisfy.
    155 TEST_F(ExtendedDesktopTest, Basic) {
    156   if (!SupportsMultipleDisplays())
    157     return;
    158 
    159   UpdateDisplay("1000x600,600x400");
    160   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    161 
    162   // All root windows must have the root window controller.
    163   ASSERT_EQ(2U, root_windows.size());
    164   for (aura::Window::Windows::const_iterator iter = root_windows.begin();
    165        iter != root_windows.end(); ++iter) {
    166     EXPECT_TRUE(internal::GetRootWindowController(*iter) != NULL);
    167   }
    168   // Make sure root windows share the same controllers.
    169   EXPECT_EQ(aura::client::GetFocusClient(root_windows[0]),
    170             aura::client::GetFocusClient(root_windows[1]));
    171   EXPECT_EQ(aura::client::GetActivationClient(root_windows[0]),
    172             aura::client::GetActivationClient(root_windows[1]));
    173   EXPECT_EQ(aura::client::GetCaptureClient(root_windows[0]),
    174             aura::client::GetCaptureClient(root_windows[1]));
    175 }
    176 
    177 TEST_F(ExtendedDesktopTest, Activation) {
    178   if (!SupportsMultipleDisplays())
    179     return;
    180 
    181   UpdateDisplay("1000x600,600x400");
    182   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    183 
    184   views::Widget* widget_on_1st = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
    185   views::Widget* widget_on_2nd =
    186       CreateTestWidget(gfx::Rect(1200, 10, 100, 100));
    187   EXPECT_EQ(root_windows[0], widget_on_1st->GetNativeView()->GetRootWindow());
    188   EXPECT_EQ(root_windows[1], widget_on_2nd->GetNativeView()->GetRootWindow());
    189 
    190   EXPECT_EQ(widget_on_2nd->GetNativeView(),
    191             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
    192   EXPECT_TRUE(wm::IsActiveWindow(widget_on_2nd->GetNativeView()));
    193 
    194   aura::test::EventGenerator& event_generator(GetEventGenerator());
    195   // Clicking a window changes the active window and active root window.
    196   event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
    197   event_generator.ClickLeftButton();
    198 
    199   EXPECT_EQ(widget_on_1st->GetNativeView(),
    200             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
    201   EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
    202 
    203   event_generator.MoveMouseToCenterOf(widget_on_2nd->GetNativeView());
    204   event_generator.ClickLeftButton();
    205 
    206   EXPECT_EQ(widget_on_2nd->GetNativeView(),
    207             aura::client::GetFocusClient(root_windows[0])->GetFocusedWindow());
    208   EXPECT_TRUE(wm::IsActiveWindow(widget_on_2nd->GetNativeView()));
    209 }
    210 
    211 TEST_F(ExtendedDesktopTest, SystemModal) {
    212   if (!SupportsMultipleDisplays())
    213     return;
    214 
    215   UpdateDisplay("1000x600,600x400");
    216   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    217 
    218   views::Widget* widget_on_1st = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
    219   EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
    220   EXPECT_EQ(root_windows[0], widget_on_1st->GetNativeView()->GetRootWindow());
    221   EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow());
    222 
    223   // Open system modal. Make sure it's on 2nd root window and active.
    224   views::Widget* modal_widget = views::Widget::CreateWindowWithContextAndBounds(
    225       new ModalWidgetDelegate(),
    226       CurrentContext(),
    227       gfx::Rect(1200, 100, 100, 100));
    228   modal_widget->Show();
    229   EXPECT_TRUE(wm::IsActiveWindow(modal_widget->GetNativeView()));
    230   EXPECT_EQ(root_windows[1], modal_widget->GetNativeView()->GetRootWindow());
    231   EXPECT_EQ(root_windows[1], Shell::GetTargetRootWindow());
    232 
    233   aura::test::EventGenerator& event_generator(GetEventGenerator());
    234 
    235   // Clicking a widget on widget_on_1st display should not change activation.
    236   event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
    237   event_generator.ClickLeftButton();
    238   EXPECT_TRUE(wm::IsActiveWindow(modal_widget->GetNativeView()));
    239   EXPECT_EQ(root_windows[1], Shell::GetTargetRootWindow());
    240 
    241   // Close system modal and so clicking a widget should work now.
    242   modal_widget->Close();
    243   event_generator.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
    244   event_generator.ClickLeftButton();
    245   EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
    246   EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow());
    247 }
    248 
    249 TEST_F(ExtendedDesktopTest, TestCursor) {
    250   if (!SupportsMultipleDisplays())
    251     return;
    252 
    253   UpdateDisplay("1000x600,600x400");
    254   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    255   aura::WindowEventDispatcher* dispatcher0 = root_windows[0]->GetDispatcher();
    256   aura::WindowEventDispatcher* dispatcher1 = root_windows[1]->GetDispatcher();
    257   EXPECT_EQ(ui::kCursorPointer, dispatcher0->last_cursor().native_type());
    258   EXPECT_EQ(ui::kCursorPointer, dispatcher1->last_cursor().native_type());
    259   Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorCopy);
    260   EXPECT_EQ(ui::kCursorCopy, dispatcher0->last_cursor().native_type());
    261   EXPECT_EQ(ui::kCursorCopy, dispatcher1->last_cursor().native_type());
    262 }
    263 
    264 TEST_F(ExtendedDesktopTest, TestCursorLocation) {
    265   if (!SupportsMultipleDisplays())
    266     return;
    267 
    268   UpdateDisplay("1000x600,600x400");
    269   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    270   aura::test::WindowTestApi root_window0_test_api(root_windows[0]);
    271   aura::test::WindowTestApi root_window1_test_api(root_windows[1]);
    272 
    273   root_windows[0]->MoveCursorTo(gfx::Point(10, 10));
    274   EXPECT_EQ("10,10", Shell::GetScreen()->GetCursorScreenPoint().ToString());
    275   EXPECT_TRUE(root_window0_test_api.ContainsMouse());
    276   EXPECT_FALSE(root_window1_test_api.ContainsMouse());
    277   root_windows[1]->MoveCursorTo(gfx::Point(10, 20));
    278   EXPECT_EQ("1010,20", Shell::GetScreen()->GetCursorScreenPoint().ToString());
    279   EXPECT_FALSE(root_window0_test_api.ContainsMouse());
    280   EXPECT_TRUE(root_window1_test_api.ContainsMouse());
    281   root_windows[0]->MoveCursorTo(gfx::Point(20, 10));
    282   EXPECT_EQ("20,10", Shell::GetScreen()->GetCursorScreenPoint().ToString());
    283   EXPECT_TRUE(root_window0_test_api.ContainsMouse());
    284   EXPECT_FALSE(root_window1_test_api.ContainsMouse());
    285 }
    286 
    287 TEST_F(ExtendedDesktopTest, CycleWindows) {
    288   if (!SupportsMultipleDisplays())
    289     return;
    290 
    291   UpdateDisplay("700x500,500x500");
    292   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    293 
    294   WindowCycleController* controller =
    295       Shell::GetInstance()->window_cycle_controller();
    296 
    297   views::Widget* d1_w1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
    298   EXPECT_EQ(root_windows[0], d1_w1->GetNativeView()->GetRootWindow());
    299   views::Widget* d2_w1 = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
    300   EXPECT_EQ(root_windows[1], d2_w1->GetNativeView()->GetRootWindow());
    301   EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
    302 
    303   controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
    304   EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
    305   controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
    306   EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
    307   controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
    308   EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
    309   controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
    310   EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
    311 
    312   // Cycle through all windows across root windows.
    313   views::Widget* d1_w2 = CreateTestWidget(gfx::Rect(10, 200, 100, 100));
    314   EXPECT_EQ(root_windows[0], d1_w2->GetNativeView()->GetRootWindow());
    315   views::Widget* d2_w2 = CreateTestWidget(gfx::Rect(800, 200, 100, 100));
    316   EXPECT_EQ(root_windows[1], d2_w2->GetNativeView()->GetRootWindow());
    317 
    318   controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
    319   EXPECT_TRUE(wm::IsActiveWindow(d1_w2->GetNativeView()));
    320   controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
    321   EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
    322   controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
    323   EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
    324   controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
    325   EXPECT_TRUE(wm::IsActiveWindow(d2_w2->GetNativeView()));
    326 
    327   // Backwards
    328   controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
    329   EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
    330   controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
    331   EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
    332   controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
    333   EXPECT_TRUE(wm::IsActiveWindow(d1_w2->GetNativeView()));
    334   controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
    335   EXPECT_TRUE(wm::IsActiveWindow(d2_w2->GetNativeView()));
    336 }
    337 
    338 TEST_F(ExtendedDesktopTest, GetRootWindowAt) {
    339   if (!SupportsMultipleDisplays())
    340     return;
    341 
    342   UpdateDisplay("700x500,500x500");
    343   SetSecondaryDisplayLayout(DisplayLayout::LEFT);
    344   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    345 
    346   EXPECT_EQ(root_windows[1], wm::GetRootWindowAt(gfx::Point(-400, 100)));
    347   EXPECT_EQ(root_windows[1], wm::GetRootWindowAt(gfx::Point(-1, 100)));
    348   EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(0, 300)));
    349   EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(700,300)));
    350 
    351   // Zero origin.
    352   EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(0, 0)));
    353 
    354   // Out of range point should return the primary root window
    355   EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(-600, 0)));
    356   EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(701, 100)));
    357 }
    358 
    359 TEST_F(ExtendedDesktopTest, GetRootWindowMatching) {
    360   if (!SupportsMultipleDisplays())
    361     return;
    362 
    363   UpdateDisplay("700x500,500x500");
    364   SetSecondaryDisplayLayout(DisplayLayout::LEFT);
    365 
    366   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    367 
    368   // Containing rect.
    369   EXPECT_EQ(root_windows[1],
    370             wm::GetRootWindowMatching(gfx::Rect(-300, 10, 50, 50)));
    371   EXPECT_EQ(root_windows[0],
    372             wm::GetRootWindowMatching(gfx::Rect(100, 10, 50, 50)));
    373 
    374   // Intersecting rect.
    375   EXPECT_EQ(root_windows[1],
    376             wm::GetRootWindowMatching(gfx::Rect(-200, 0, 300, 300)));
    377   EXPECT_EQ(root_windows[0],
    378             wm::GetRootWindowMatching(gfx::Rect(-100, 0, 300, 300)));
    379 
    380   // Zero origin.
    381   EXPECT_EQ(root_windows[0],
    382             wm::GetRootWindowMatching(gfx::Rect(0, 0, 0, 0)));
    383   EXPECT_EQ(root_windows[0],
    384             wm::GetRootWindowMatching(gfx::Rect(0, 0, 1, 1)));
    385 
    386   // Empty rect.
    387   EXPECT_EQ(root_windows[1],
    388             wm::GetRootWindowMatching(gfx::Rect(-400, 100, 0, 0)));
    389   EXPECT_EQ(root_windows[0],
    390             wm::GetRootWindowMatching(gfx::Rect(100, 100, 0, 0)));
    391 
    392   // Out of range rect should return the primary root window.
    393   EXPECT_EQ(root_windows[0],
    394             wm::GetRootWindowMatching(gfx::Rect(-600, -300, 50, 50)));
    395   EXPECT_EQ(root_windows[0],
    396             wm::GetRootWindowMatching(gfx::Rect(0, 1000, 50, 50)));
    397 }
    398 
    399 TEST_F(ExtendedDesktopTest, Capture) {
    400   if (!SupportsMultipleDisplays())
    401     return;
    402 
    403   UpdateDisplay("1000x600,600x400");
    404   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    405 
    406   aura::test::EventCountDelegate r1_d1;
    407   aura::test::EventCountDelegate r1_d2;
    408   aura::test::EventCountDelegate r2_d1;
    409 
    410   scoped_ptr<aura::Window> r1_w1(aura::test::CreateTestWindowWithDelegate(
    411       &r1_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
    412   scoped_ptr<aura::Window> r1_w2(aura::test::CreateTestWindowWithDelegate(
    413       &r1_d2, 0, gfx::Rect(10, 100, 100, 100), root_windows[0]));
    414   scoped_ptr<aura::Window> r2_w1(aura::test::CreateTestWindowWithDelegate(
    415       &r2_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[1]));
    416 
    417   r1_w1->SetCapture();
    418 
    419   EXPECT_EQ(r1_w1.get(),
    420             aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
    421 
    422   aura::test::EventGenerator generator2(root_windows[1]);
    423   generator2.MoveMouseToCenterOf(r2_w1.get());
    424   generator2.ClickLeftButton();
    425   EXPECT_EQ("0 0 0", r2_d1.GetMouseMotionCountsAndReset());
    426   EXPECT_EQ("0 0", r2_d1.GetMouseButtonCountsAndReset());
    427   // The mouse is outside. On chromeos, the mouse is warped to the
    428   // dest root window, but it's not implemented on Win yet, so
    429   // no mouse move event on Win.
    430   EXPECT_EQ("1 1 0", r1_d1.GetMouseMotionCountsAndReset());
    431   EXPECT_EQ("1 1", r1_d1.GetMouseButtonCountsAndReset());
    432   // Emulate passive grab. (15,15) on 1st display is (-985,15) on 2nd
    433   // display.
    434   generator2.MoveMouseTo(-985, 15);
    435   EXPECT_EQ("0 1 0", r1_d1.GetMouseMotionCountsAndReset());
    436 
    437   r1_w2->SetCapture();
    438   EXPECT_EQ(r1_w2.get(),
    439             aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
    440   generator2.MoveMouseBy(10, 10);
    441   generator2.ClickLeftButton();
    442   EXPECT_EQ("0 0 0", r2_d1.GetMouseMotionCountsAndReset());
    443   EXPECT_EQ("0 0", r2_d1.GetMouseButtonCountsAndReset());
    444   // mouse is already entered.
    445   EXPECT_EQ("0 1 0", r1_d2.GetMouseMotionCountsAndReset());
    446   EXPECT_EQ("1 1", r1_d2.GetMouseButtonCountsAndReset());
    447   r1_w2->ReleaseCapture();
    448   EXPECT_EQ(NULL, aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
    449   generator2.MoveMouseTo(15, 15);
    450   generator2.ClickLeftButton();
    451   EXPECT_EQ("1 1 0", r2_d1.GetMouseMotionCountsAndReset());
    452   EXPECT_EQ("1 1", r2_d1.GetMouseButtonCountsAndReset());
    453   // Make sure the mouse_moved_handler_ is properly reset.
    454   EXPECT_EQ("0 0 0", r1_d2.GetMouseMotionCountsAndReset());
    455   EXPECT_EQ("0 0", r1_d2.GetMouseButtonCountsAndReset());
    456 }
    457 
    458 TEST_F(ExtendedDesktopTest, MoveWindow) {
    459   if (!SupportsMultipleDisplays())
    460     return;
    461 
    462   UpdateDisplay("1000x600,600x400");
    463   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    464   views::Widget* d1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
    465 
    466   EXPECT_EQ(root_windows[0], d1->GetNativeView()->GetRootWindow());
    467 
    468   d1->SetBounds(gfx::Rect(1010, 10, 100, 100));
    469   EXPECT_EQ("1010,10 100x100",
    470             d1->GetWindowBoundsInScreen().ToString());
    471 
    472   EXPECT_EQ(root_windows[1], d1->GetNativeView()->GetRootWindow());
    473 
    474   d1->SetBounds(gfx::Rect(10, 10, 100, 100));
    475   EXPECT_EQ("10,10 100x100",
    476             d1->GetWindowBoundsInScreen().ToString());
    477 
    478   EXPECT_EQ(root_windows[0], d1->GetNativeView()->GetRootWindow());
    479 
    480   // Make sure the bounds which doesn't fit to the root window
    481   // works correctly.
    482   d1->SetBounds(gfx::Rect(1560, 30, 100, 100));
    483   EXPECT_EQ(root_windows[1], d1->GetNativeView()->GetRootWindow());
    484   EXPECT_EQ("1560,30 100x100",
    485             d1->GetWindowBoundsInScreen().ToString());
    486 
    487   // Setting outside of root windows will be moved to primary root window.
    488   // TODO(oshima): This one probably should pick the closest root window.
    489   d1->SetBounds(gfx::Rect(200, 10, 100, 100));
    490   EXPECT_EQ(root_windows[0], d1->GetNativeView()->GetRootWindow());
    491 }
    492 
    493 // Verifies if the mouse event arrives to the window even when the window
    494 // moves to another root in a pre-target handler.  See: crbug.com/157583
    495 TEST_F(ExtendedDesktopTest, MoveWindowByMouseClick) {
    496   if (!SupportsMultipleDisplays())
    497     return;
    498 
    499   UpdateDisplay("1000x600,600x400");
    500 
    501   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    502   aura::test::EventCountDelegate delegate;
    503   scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate(
    504       &delegate, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
    505   MoveWindowByClickEventHandler event_handler(window.get());
    506   window->AddPreTargetHandler(&event_handler);
    507 
    508   aura::test::EventGenerator& event_generator(GetEventGenerator());
    509 
    510   event_generator.MoveMouseToCenterOf(window.get());
    511   event_generator.ClickLeftButton();
    512   // Both mouse pressed and released arrive at the window and its delegate.
    513   EXPECT_EQ("1 1", delegate.GetMouseButtonCountsAndReset());
    514   // Also event_handler moves the window to another root at mouse release.
    515   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    516 }
    517 
    518 TEST_F(ExtendedDesktopTest, MoveWindowToDisplay) {
    519   if (!SupportsMultipleDisplays())
    520     return;
    521 
    522   UpdateDisplay("1000x1000,1000x1000");
    523   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    524 
    525   gfx::Display display0 = Shell::GetScreen()->GetDisplayMatching(
    526       root_windows[0]->GetBoundsInScreen());
    527   gfx::Display display1 = Shell::GetScreen()->GetDisplayMatching(
    528       root_windows[1]->GetBoundsInScreen());
    529   EXPECT_NE(display0.id(), display1.id());
    530 
    531   views::Widget* d1 = CreateTestWidget(gfx::Rect(10, 10, 1000, 100));
    532   EXPECT_EQ(root_windows[0], d1->GetNativeView()->GetRootWindow());
    533 
    534   // Move the window where the window spans both root windows. Since the second
    535   // parameter is |display1|, the window should be shown on the secondary root.
    536   d1->GetNativeWindow()->SetBoundsInScreen(gfx::Rect(500, 10, 1000, 100),
    537                                            display1);
    538   EXPECT_EQ("500,10 1000x100",
    539             d1->GetWindowBoundsInScreen().ToString());
    540   EXPECT_EQ(root_windows[1], d1->GetNativeView()->GetRootWindow());
    541 
    542   // Move to the primary root.
    543   d1->GetNativeWindow()->SetBoundsInScreen(gfx::Rect(500, 10, 1000, 100),
    544                                            display0);
    545   EXPECT_EQ("500,10 1000x100",
    546             d1->GetWindowBoundsInScreen().ToString());
    547   EXPECT_EQ(root_windows[0], d1->GetNativeView()->GetRootWindow());
    548 }
    549 
    550 TEST_F(ExtendedDesktopTest, MoveWindowWithTransient) {
    551   if (!SupportsMultipleDisplays())
    552     return;
    553 
    554   UpdateDisplay("1000x600,600x400");
    555   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    556   views::Widget* w1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
    557   views::Widget* w1_t1 = CreateTestWidgetWithParent(
    558       w1, gfx::Rect(50, 50, 50, 50), false /* transient */);
    559   // Transient child of the transient child.
    560   views::Widget* w1_t11 = CreateTestWidgetWithParent(
    561       w1_t1, gfx::Rect(1200, 70, 30, 30), false /* transient */);
    562 
    563   views::Widget* w11 = CreateTestWidgetWithParent(
    564       w1, gfx::Rect(10, 10, 40, 40), true /* child */);
    565   views::Widget* w11_t1 = CreateTestWidgetWithParent(
    566       w1, gfx::Rect(1300, 100, 80, 80), false /* transient */);
    567 
    568   EXPECT_EQ(root_windows[0], w1->GetNativeView()->GetRootWindow());
    569   EXPECT_EQ(root_windows[0], w11->GetNativeView()->GetRootWindow());
    570   EXPECT_EQ(root_windows[0], w1_t1->GetNativeView()->GetRootWindow());
    571   EXPECT_EQ(root_windows[0], w1_t11->GetNativeView()->GetRootWindow());
    572   EXPECT_EQ(root_windows[0], w11_t1->GetNativeView()->GetRootWindow());
    573   EXPECT_EQ("50,50 50x50",
    574             w1_t1->GetWindowBoundsInScreen().ToString());
    575   EXPECT_EQ("1200,70 30x30",
    576             w1_t11->GetWindowBoundsInScreen().ToString());
    577   EXPECT_EQ("20,20 40x40",
    578             w11->GetWindowBoundsInScreen().ToString());
    579   EXPECT_EQ("1300,100 80x80",
    580             w11_t1->GetWindowBoundsInScreen().ToString());
    581 
    582   w1->SetBounds(gfx::Rect(1100,10,100,100));
    583 
    584   EXPECT_EQ(root_windows[1], w1_t1->GetNativeView()->GetRootWindow());
    585   EXPECT_EQ(root_windows[1], w1_t1->GetNativeView()->GetRootWindow());
    586   EXPECT_EQ(root_windows[1], w1_t11->GetNativeView()->GetRootWindow());
    587   EXPECT_EQ(root_windows[1], w11->GetNativeView()->GetRootWindow());
    588   EXPECT_EQ(root_windows[1], w11_t1->GetNativeView()->GetRootWindow());
    589 
    590   EXPECT_EQ("1110,20 40x40",
    591             w11->GetWindowBoundsInScreen().ToString());
    592   // Transient window's screen bounds stays the same.
    593   EXPECT_EQ("50,50 50x50",
    594             w1_t1->GetWindowBoundsInScreen().ToString());
    595   EXPECT_EQ("1200,70 30x30",
    596             w1_t11->GetWindowBoundsInScreen().ToString());
    597   EXPECT_EQ("1300,100 80x80",
    598             w11_t1->GetWindowBoundsInScreen().ToString());
    599 
    600   // Transient window doesn't move between root window unless
    601   // its transient parent moves.
    602   w1_t1->SetBounds(gfx::Rect(10, 50, 50, 50));
    603   EXPECT_EQ(root_windows[1], w1_t1->GetNativeView()->GetRootWindow());
    604   EXPECT_EQ("10,50 50x50",
    605             w1_t1->GetWindowBoundsInScreen().ToString());
    606 }
    607 
    608 // Test if the Window::ConvertPointToTarget works across root windows.
    609 // TODO(oshima): Move multiple display suport and this test to aura.
    610 TEST_F(ExtendedDesktopTest, ConvertPoint) {
    611   if (!SupportsMultipleDisplays())
    612     return;
    613   gfx::Screen* screen = Shell::GetInstance()->screen();
    614   UpdateDisplay("1000x600,600x400");
    615   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    616   gfx::Display display_1 = screen->GetDisplayNearestWindow(root_windows[0]);
    617   EXPECT_EQ("0,0", display_1.bounds().origin().ToString());
    618   gfx::Display display_2 = screen->GetDisplayNearestWindow(root_windows[1]);
    619   EXPECT_EQ("1000,0", display_2.bounds().origin().ToString());
    620 
    621   aura::Window* d1 =
    622       CreateTestWidget(gfx::Rect(10, 10, 100, 100))->GetNativeView();
    623   aura::Window* d2 =
    624       CreateTestWidget(gfx::Rect(1020, 20, 100, 100))->GetNativeView();
    625   EXPECT_EQ(root_windows[0], d1->GetRootWindow());
    626   EXPECT_EQ(root_windows[1], d2->GetRootWindow());
    627 
    628   // Convert point in the Root2's window to the Root1's window Coord.
    629   gfx::Point p(0, 0);
    630   aura::Window::ConvertPointToTarget(root_windows[1], root_windows[0], &p);
    631   EXPECT_EQ("1000,0", p.ToString());
    632   p.SetPoint(0, 0);
    633   aura::Window::ConvertPointToTarget(d2, d1, &p);
    634   EXPECT_EQ("1010,10", p.ToString());
    635 
    636   // Convert point in the Root1's window to the Root2's window Coord.
    637   p.SetPoint(0, 0);
    638   aura::Window::ConvertPointToTarget(root_windows[0], root_windows[1], &p);
    639   EXPECT_EQ("-1000,0", p.ToString());
    640   p.SetPoint(0, 0);
    641   aura::Window::ConvertPointToTarget(d1, d2, &p);
    642   EXPECT_EQ("-1010,-10", p.ToString());
    643 
    644   // Move the 2nd display to the bottom and test again.
    645   SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
    646 
    647   display_2 = screen->GetDisplayNearestWindow(root_windows[1]);
    648   EXPECT_EQ("0,600", display_2.bounds().origin().ToString());
    649 
    650   // Convert point in Root2's window to Root1's window Coord.
    651   p.SetPoint(0, 0);
    652   aura::Window::ConvertPointToTarget(root_windows[1], root_windows[0], &p);
    653   EXPECT_EQ("0,600", p.ToString());
    654   p.SetPoint(0, 0);
    655   aura::Window::ConvertPointToTarget(d2, d1, &p);
    656   EXPECT_EQ("10,610", p.ToString());
    657 
    658   // Convert point in Root1's window to Root2's window Coord.
    659   p.SetPoint(0, 0);
    660   aura::Window::ConvertPointToTarget(root_windows[0], root_windows[1], &p);
    661   EXPECT_EQ("0,-600", p.ToString());
    662   p.SetPoint(0, 0);
    663   aura::Window::ConvertPointToTarget(d1, d2, &p);
    664   EXPECT_EQ("-10,-610", p.ToString());
    665 }
    666 
    667 TEST_F(ExtendedDesktopTest, OpenSystemTray) {
    668   if (!SupportsMultipleDisplays())
    669     return;
    670 
    671   UpdateDisplay("500x600,600x400");
    672   SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
    673   ASSERT_FALSE(tray->HasSystemBubble());
    674 
    675   aura::test::EventGenerator& event_generator(GetEventGenerator());
    676 
    677   // Opens the tray by a dummy click event and makes sure that adding/removing
    678   // displays doesn't break anything.
    679   event_generator.MoveMouseToCenterOf(tray->GetWidget()->GetNativeWindow());
    680   event_generator.ClickLeftButton();
    681   EXPECT_TRUE(tray->HasSystemBubble());
    682 
    683   UpdateDisplay("500x600");
    684   EXPECT_TRUE(tray->HasSystemBubble());
    685   UpdateDisplay("500x600,600x400");
    686   EXPECT_TRUE(tray->HasSystemBubble());
    687 
    688   // Closes the tray and again makes sure that adding/removing displays doesn't
    689   // break anything.
    690   event_generator.ClickLeftButton();
    691   RunAllPendingInMessageLoop();
    692 
    693   EXPECT_FALSE(tray->HasSystemBubble());
    694 
    695   UpdateDisplay("500x600");
    696   EXPECT_FALSE(tray->HasSystemBubble());
    697   UpdateDisplay("500x600,600x400");
    698   EXPECT_FALSE(tray->HasSystemBubble());
    699 }
    700 
    701 TEST_F(ExtendedDesktopTest, StayInSameRootWindow) {
    702   if (!SupportsMultipleDisplays())
    703     return;
    704 
    705   UpdateDisplay("100x100,200x200");
    706   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    707   views::Widget* w1 = CreateTestWidget(gfx::Rect(10, 10, 50, 50));
    708   EXPECT_EQ(root_windows[0], w1->GetNativeView()->GetRootWindow());
    709   w1->SetBounds(gfx::Rect(150, 10, 50, 50));
    710   EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
    711 
    712   // The widget stays in the same root if kStayInSameRootWindowKey is set to
    713   // true.
    714   w1->GetNativeView()->SetProperty(internal::kStayInSameRootWindowKey, true);
    715   w1->SetBounds(gfx::Rect(10, 10, 50, 50));
    716   EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
    717 
    718   // The widget should now move to the 1st root window without the property.
    719   w1->GetNativeView()->ClearProperty(internal::kStayInSameRootWindowKey);
    720   w1->SetBounds(gfx::Rect(10, 10, 50, 50));
    721   EXPECT_EQ(root_windows[0], w1->GetNativeView()->GetRootWindow());
    722 
    723   // a window in SettingsBubbleContainer and StatusContainer should
    724   // not move to another root window regardles of the bounds specified.
    725   aura::Window* settings_bubble_container =
    726       Shell::GetPrimaryRootWindowController()->GetContainer(
    727           internal::kShellWindowId_SettingBubbleContainer);
    728   aura::Window* window = aura::test::CreateTestWindowWithId(
    729       100, settings_bubble_container);
    730   window->SetBoundsInScreen(gfx::Rect(150, 10, 50, 50),
    731                             ScreenAsh::GetSecondaryDisplay());
    732   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    733 
    734   aura::Window* status_container =
    735       Shell::GetPrimaryRootWindowController()->GetContainer(
    736           internal::kShellWindowId_StatusContainer);
    737   window = aura::test::CreateTestWindowWithId(100, status_container);
    738   window->SetBoundsInScreen(gfx::Rect(150, 10, 50, 50),
    739                             ScreenAsh::GetSecondaryDisplay());
    740   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    741 }
    742 
    743 TEST_F(ExtendedDesktopTest, KeyEventsOnLockScreen) {
    744   if (!SupportsMultipleDisplays())
    745     return;
    746 
    747   UpdateDisplay("100x100,200x200");
    748   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    749 
    750   // Create normal windows on both displays.
    751   views::Widget* widget1 = CreateTestWidget(
    752       Shell::GetScreen()->GetPrimaryDisplay().bounds());
    753   widget1->Show();
    754   EXPECT_EQ(root_windows[0], widget1->GetNativeView()->GetRootWindow());
    755   views::Widget* widget2 = CreateTestWidget(
    756       ScreenAsh::GetSecondaryDisplay().bounds());
    757   widget2->Show();
    758   EXPECT_EQ(root_windows[1], widget2->GetNativeView()->GetRootWindow());
    759 
    760   // Create a LockScreen window.
    761   views::Widget* lock_widget = CreateTestWidget(
    762       Shell::GetScreen()->GetPrimaryDisplay().bounds());
    763   views::Textfield* textfield = new views::Textfield;
    764   lock_widget->client_view()->AddChildView(textfield);
    765 
    766   ash::Shell::GetContainer(
    767       Shell::GetPrimaryRootWindow(),
    768       ash::internal::kShellWindowId_LockScreenContainer)->
    769       AddChild(lock_widget->GetNativeView());
    770   lock_widget->Show();
    771   textfield->RequestFocus();
    772 
    773   aura::client::FocusClient* focus_client =
    774       aura::client::GetFocusClient(root_windows[0]);
    775   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    776 
    777   // The lock window should get events on both root windows.
    778   aura::test::EventGenerator& event_generator(GetEventGenerator());
    779 
    780   event_generator.set_current_root_window(root_windows[0]->GetDispatcher());
    781   event_generator.PressKey(ui::VKEY_A, 0);
    782   event_generator.ReleaseKey(ui::VKEY_A, 0);
    783   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    784   EXPECT_EQ("a", UTF16ToASCII(textfield->text()));
    785 
    786   event_generator.set_current_root_window(root_windows[1]->GetDispatcher());
    787   event_generator.PressKey(ui::VKEY_B, 0);
    788   event_generator.ReleaseKey(ui::VKEY_B, 0);
    789   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    790   EXPECT_EQ("ab", UTF16ToASCII(textfield->text()));
    791 
    792   // Deleting 2nd display. The lock window still should get the events.
    793   UpdateDisplay("100x100");
    794   event_generator.PressKey(ui::VKEY_C, 0);
    795   event_generator.ReleaseKey(ui::VKEY_C, 0);
    796   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    797   EXPECT_EQ("abc", UTF16ToASCII(textfield->text()));
    798 
    799   // Creating 2nd display again, and lock window still should get events
    800   // on both root windows.
    801   UpdateDisplay("100x100,200x200");
    802   root_windows = Shell::GetAllRootWindows();
    803   event_generator.set_current_root_window(root_windows[0]->GetDispatcher());
    804   event_generator.PressKey(ui::VKEY_D, 0);
    805   event_generator.ReleaseKey(ui::VKEY_D, 0);
    806   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    807   EXPECT_EQ("abcd", UTF16ToASCII(textfield->text()));
    808 
    809   event_generator.set_current_root_window(root_windows[1]->GetDispatcher());
    810   event_generator.PressKey(ui::VKEY_E, 0);
    811   event_generator.ReleaseKey(ui::VKEY_E, 0);
    812   EXPECT_EQ(lock_widget->GetNativeView(), focus_client->GetFocusedWindow());
    813   EXPECT_EQ("abcde", UTF16ToASCII(textfield->text()));
    814 }
    815 
    816 TEST_F(ExtendedDesktopTest, PassiveGrab) {
    817   if (!SupportsMultipleDisplays())
    818     return;
    819 
    820   EventLocationRecordingEventHandler event_handler;
    821   ash::Shell::GetInstance()->AddPreTargetHandler(&event_handler);
    822 
    823   UpdateDisplay("300x300,200x200");
    824 
    825   views::Widget* widget = CreateTestWidget(gfx::Rect(50, 50, 200, 200));
    826   widget->Show();
    827   ASSERT_EQ("50,50 200x200", widget->GetWindowBoundsInScreen().ToString());
    828 
    829   aura::test::EventGenerator& generator(GetEventGenerator());
    830   generator.MoveMouseTo(150, 150);
    831   EXPECT_EQ("100,100 150,150", event_handler.GetLocationsAndReset());
    832 
    833   generator.PressLeftButton();
    834   generator.MoveMouseTo(400, 150);
    835 
    836   EXPECT_EQ("350,100 400,150", event_handler.GetLocationsAndReset());
    837 
    838   generator.ReleaseLeftButton();
    839   EXPECT_EQ("-999,-999 -999,-999", event_handler.GetLocationsAndReset());
    840 
    841   generator.MoveMouseTo(400, 150);
    842   EXPECT_EQ("100,150 100,150", event_handler.GetLocationsAndReset());
    843 
    844   ash::Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
    845 }
    846 
    847 }  // namespace ash
    848