Home | History | Annotate | Download | only in panels
      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/wm/panels/panel_layout_manager.h"
      6 
      7 #include "ash/ash_switches.h"
      8 #include "ash/launcher/launcher.h"
      9 #include "ash/root_window_controller.h"
     10 #include "ash/screen_ash.h"
     11 #include "ash/shelf/shelf_button.h"
     12 #include "ash/shelf/shelf_layout_manager.h"
     13 #include "ash/shelf/shelf_model.h"
     14 #include "ash/shelf/shelf_types.h"
     15 #include "ash/shelf/shelf_util.h"
     16 #include "ash/shelf/shelf_view.h"
     17 #include "ash/shelf/shelf_widget.h"
     18 #include "ash/shell.h"
     19 #include "ash/shell_window_ids.h"
     20 #include "ash/test/ash_test_base.h"
     21 #include "ash/test/launcher_test_api.h"
     22 #include "ash/test/shelf_view_test_api.h"
     23 #include "ash/test/shell_test_api.h"
     24 #include "ash/test/test_shelf_delegate.h"
     25 #include "ash/wm/mru_window_tracker.h"
     26 #include "ash/wm/window_util.h"
     27 #include "base/basictypes.h"
     28 #include "base/command_line.h"
     29 #include "base/compiler_specific.h"
     30 #include "base/i18n/rtl.h"
     31 #include "base/run_loop.h"
     32 #include "ui/aura/client/aura_constants.h"
     33 #include "ui/aura/root_window.h"
     34 #include "ui/aura/test/event_generator.h"
     35 #include "ui/aura/test/test_windows.h"
     36 #include "ui/aura/window.h"
     37 #include "ui/base/l10n/l10n_util.h"
     38 #include "ui/views/corewm/corewm_switches.h"
     39 #include "ui/views/widget/widget.h"
     40 
     41 namespace ash {
     42 namespace internal {
     43 
     44 using aura::test::WindowIsAbove;
     45 
     46 class PanelLayoutManagerTest : public test::AshTestBase {
     47  public:
     48   PanelLayoutManagerTest() {}
     49   virtual ~PanelLayoutManagerTest() {}
     50 
     51   virtual void SetUp() OVERRIDE {
     52     test::AshTestBase::SetUp();
     53     ASSERT_TRUE(test::TestShelfDelegate::instance());
     54 
     55     shelf_view_test_.reset(new test::ShelfViewTestAPI(
     56         GetShelfView(Launcher::ForPrimaryDisplay())));
     57     shelf_view_test_->SetAnimationDuration(1);
     58   }
     59 
     60   aura::Window* CreateNormalWindow(const gfx::Rect& bounds) {
     61     return CreateTestWindowInShellWithBounds(bounds);
     62   }
     63 
     64   aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
     65     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
     66         NULL,
     67         aura::client::WINDOW_TYPE_PANEL,
     68         0,
     69         bounds);
     70     test::TestShelfDelegate* shelf_delegate =
     71         test::TestShelfDelegate::instance();
     72     shelf_delegate->AddLauncherItem(window);
     73     PanelLayoutManager* manager = static_cast<PanelLayoutManager*>(
     74         GetPanelContainer(window)->layout_manager());
     75     manager->Relayout();
     76     shelf_view_test()->RunMessageLoopUntilAnimationsDone();
     77     return window;
     78   }
     79 
     80   aura::Window* GetPanelContainer(aura::Window* panel) {
     81     return Shell::GetContainer(panel->GetRootWindow(),
     82                                internal::kShellWindowId_PanelContainer);
     83   }
     84 
     85   views::Widget* GetCalloutWidgetForPanel(aura::Window* panel) {
     86     PanelLayoutManager* manager =
     87         static_cast<PanelLayoutManager*>(GetPanelContainer(panel)->
     88                                          layout_manager());
     89     DCHECK(manager);
     90     PanelLayoutManager::PanelList::iterator found = std::find(
     91         manager->panel_windows_.begin(), manager->panel_windows_.end(),
     92         panel);
     93     DCHECK(found != manager->panel_windows_.end());
     94     DCHECK(found->callout_widget);
     95     return reinterpret_cast<views::Widget*>(found->callout_widget);
     96   }
     97 
     98   void PanelInScreen(aura::Window* panel) {
     99     gfx::Rect panel_bounds = panel->GetBoundsInRootWindow();
    100     gfx::Point root_point = gfx::Point(panel_bounds.x(), panel_bounds.y());
    101     gfx::Display display = ScreenAsh::FindDisplayContainingPoint(root_point);
    102 
    103     gfx::Rect panel_bounds_in_screen = panel->GetBoundsInScreen();
    104     gfx::Point screen_bottom_right = gfx::Point(
    105         panel_bounds_in_screen.right(),
    106         panel_bounds_in_screen.bottom());
    107     gfx::Rect display_bounds = display.bounds();
    108     EXPECT_TRUE(screen_bottom_right.x() < display_bounds.width() &&
    109                 screen_bottom_right.y() < display_bounds.height());
    110   }
    111 
    112   void PanelsNotOverlapping(aura::Window* panel1, aura::Window* panel2) {
    113     // Waits until all shelf view animations are done.
    114     shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    115     gfx::Rect window1_bounds = panel1->GetBoundsInRootWindow();
    116     gfx::Rect window2_bounds = panel2->GetBoundsInRootWindow();
    117 
    118     EXPECT_FALSE(window1_bounds.Intersects(window2_bounds));
    119   }
    120 
    121   // TODO(dcheng): This should be const, but GetScreenBoundsOfItemIconForWindow
    122   // takes a non-const Window. We can probably fix that.
    123   void IsPanelAboveLauncherIcon(aura::Window* panel) {
    124     // Waits until all shelf view animations are done.
    125     shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    126 
    127     Launcher* launcher =
    128         RootWindowController::ForLauncher(panel)->shelf()->launcher();
    129     gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel);
    130     ASSERT_FALSE(icon_bounds.width() == 0 && icon_bounds.height() == 0);
    131 
    132     gfx::Rect window_bounds = panel->GetBoundsInScreen();
    133     ASSERT_LT(icon_bounds.width(), window_bounds.width());
    134     ASSERT_LT(icon_bounds.height(), window_bounds.height());
    135     gfx::Rect launcher_bounds = launcher->shelf_widget()->
    136         GetWindowBoundsInScreen();
    137     ShelfAlignment alignment = GetAlignment(panel->GetRootWindow());
    138 
    139     if (IsHorizontal(alignment)) {
    140       // The horizontal bounds of the panel window should contain the bounds of
    141       // the launcher icon.
    142       EXPECT_LE(window_bounds.x(), icon_bounds.x());
    143       EXPECT_GE(window_bounds.right(), icon_bounds.right());
    144     } else {
    145       // The vertical bounds of the panel window should contain the bounds of
    146       // the launcher icon.
    147       EXPECT_LE(window_bounds.y(), icon_bounds.y());
    148       EXPECT_GE(window_bounds.bottom(), icon_bounds.bottom());
    149     }
    150 
    151     switch (alignment) {
    152       case SHELF_ALIGNMENT_BOTTOM:
    153         EXPECT_EQ(launcher_bounds.y(), window_bounds.bottom());
    154         break;
    155       case SHELF_ALIGNMENT_LEFT:
    156         EXPECT_EQ(launcher_bounds.right(), window_bounds.x());
    157         break;
    158       case SHELF_ALIGNMENT_RIGHT:
    159         EXPECT_EQ(launcher_bounds.x(), window_bounds.right());
    160         break;
    161       case SHELF_ALIGNMENT_TOP:
    162         EXPECT_EQ(launcher_bounds.bottom(), window_bounds.y());
    163         break;
    164     }
    165   }
    166 
    167   void IsCalloutAboveLauncherIcon(aura::Window* panel) {
    168     // Flush the message loop, since callout updates use a delayed task.
    169     base::RunLoop().RunUntilIdle();
    170     views::Widget* widget = GetCalloutWidgetForPanel(panel);
    171 
    172     Launcher* launcher =
    173         RootWindowController::ForLauncher(panel)->shelf()->launcher();
    174     gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel);
    175     ASSERT_FALSE(icon_bounds.IsEmpty());
    176 
    177     gfx::Rect panel_bounds = panel->GetBoundsInScreen();
    178     gfx::Rect callout_bounds = widget->GetWindowBoundsInScreen();
    179     ASSERT_FALSE(icon_bounds.IsEmpty());
    180 
    181     EXPECT_TRUE(widget->IsVisible());
    182 
    183     ShelfAlignment alignment = GetAlignment(panel->GetRootWindow());
    184     switch (alignment) {
    185       case SHELF_ALIGNMENT_BOTTOM:
    186         EXPECT_EQ(panel_bounds.bottom(), callout_bounds.y());
    187         break;
    188       case SHELF_ALIGNMENT_LEFT:
    189         EXPECT_EQ(panel_bounds.x(), callout_bounds.right());
    190         break;
    191       case SHELF_ALIGNMENT_RIGHT:
    192         EXPECT_EQ(panel_bounds.right(), callout_bounds.x());
    193         break;
    194       case SHELF_ALIGNMENT_TOP:
    195         EXPECT_EQ(panel_bounds.y(), callout_bounds.bottom());
    196         break;
    197     }
    198 
    199     if (IsHorizontal(alignment)) {
    200       EXPECT_NEAR(icon_bounds.CenterPoint().x(),
    201                   widget->GetWindowBoundsInScreen().CenterPoint().x(),
    202                   1);
    203     } else {
    204       EXPECT_NEAR(icon_bounds.CenterPoint().y(),
    205                   widget->GetWindowBoundsInScreen().CenterPoint().y(),
    206                   1);
    207     }
    208   }
    209 
    210   bool IsPanelCalloutVisible(aura::Window* panel) {
    211     views::Widget* widget = GetCalloutWidgetForPanel(panel);
    212     return widget->IsVisible();
    213   }
    214 
    215   test::ShelfViewTestAPI* shelf_view_test() {
    216     return shelf_view_test_.get();
    217   }
    218 
    219   // Clicks the launcher items on |shelf_view| that is
    220   /// associated with given |window|.
    221   void ClickLauncherItemForWindow(ShelfView* shelf_view,
    222                                   aura::Window* window) {
    223     test::ShelfViewTestAPI test_api(shelf_view);
    224     test_api.SetAnimationDuration(1);
    225     test_api.RunMessageLoopUntilAnimationsDone();
    226     ShelfModel* model = test::ShellTestApi(Shell::GetInstance()).shelf_model();
    227     int index = model->ItemIndexByID(GetLauncherIDForWindow(window));
    228     gfx::Rect bounds = test_api.GetButton(index)->GetBoundsInScreen();
    229 
    230     aura::test::EventGenerator& event_generator = GetEventGenerator();
    231     event_generator.MoveMouseTo(bounds.CenterPoint());
    232     event_generator.ClickLeftButton();
    233 
    234     test_api.RunMessageLoopUntilAnimationsDone();
    235   }
    236 
    237   void SetAlignment(aura::Window* root_window, ShelfAlignment alignment) {
    238     ash::Shell* shell = ash::Shell::GetInstance();
    239     shell->SetShelfAlignment(alignment, root_window);
    240   }
    241 
    242   ShelfAlignment GetAlignment(aura::Window* root_window) {
    243     ash::Shell* shell = ash::Shell::GetInstance();
    244     return shell->GetShelfAlignment(root_window);
    245   }
    246 
    247   void SetShelfAutoHideBehavior(aura::Window* window,
    248                                 ShelfAutoHideBehavior behavior) {
    249     internal::ShelfLayoutManager* shelf =
    250         RootWindowController::ForWindow(window)->shelf()->
    251         shelf_layout_manager();
    252     shelf->SetAutoHideBehavior(behavior);
    253     ShelfView* shelf_view = GetShelfView(Launcher::ForWindow(window));
    254     test::ShelfViewTestAPI test_api(shelf_view);
    255     test_api.RunMessageLoopUntilAnimationsDone();
    256   }
    257 
    258   void SetShelfVisibilityState(aura::Window* window,
    259                                ShelfVisibilityState visibility_state) {
    260     internal::ShelfLayoutManager* shelf =
    261         RootWindowController::ForWindow(window)->shelf()->
    262         shelf_layout_manager();
    263     shelf->SetState(visibility_state);
    264   }
    265 
    266   internal::ShelfView* GetShelfView(Launcher* launcher) {
    267     return test::LauncherTestAPI(launcher).shelf_view();
    268   }
    269 
    270  private:
    271   scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
    272 
    273   bool IsHorizontal(ShelfAlignment alignment) {
    274     return alignment == SHELF_ALIGNMENT_BOTTOM ||
    275            alignment == SHELF_ALIGNMENT_TOP;
    276   }
    277 
    278   DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTest);
    279 };
    280 
    281 class PanelLayoutManagerTextDirectionTest
    282     : public PanelLayoutManagerTest,
    283       public testing::WithParamInterface<bool> {
    284  public:
    285   PanelLayoutManagerTextDirectionTest() : is_rtl_(GetParam()) {}
    286   virtual ~PanelLayoutManagerTextDirectionTest() {}
    287 
    288   virtual void SetUp() OVERRIDE {
    289     original_locale = l10n_util::GetApplicationLocale(std::string());
    290     if (is_rtl_)
    291       base::i18n::SetICUDefaultLocale("he");
    292     PanelLayoutManagerTest::SetUp();
    293     ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
    294   }
    295 
    296   virtual void TearDown() OVERRIDE {
    297     if (is_rtl_)
    298       base::i18n::SetICUDefaultLocale(original_locale);
    299     PanelLayoutManagerTest::TearDown();
    300   }
    301 
    302  private:
    303   bool is_rtl_;
    304   std::string original_locale;
    305 
    306   DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTextDirectionTest);
    307 };
    308 
    309 // Tests that a created panel window is above the launcher icon in LTR and RTL.
    310 TEST_P(PanelLayoutManagerTextDirectionTest, AddOnePanel) {
    311   gfx::Rect bounds(0, 0, 201, 201);
    312   scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
    313   EXPECT_EQ(GetPanelContainer(window.get()), window->parent());
    314   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get()));
    315   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(window.get()));
    316 }
    317 
    318 // Tests that a created panel window is successfully aligned over a hidden
    319 // launcher icon.
    320 TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIcon) {
    321   gfx::Rect bounds(0, 0, 201, 201);
    322   SetShelfAutoHideBehavior(Shell::GetPrimaryRootWindow(),
    323                            SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    324   scoped_ptr<aura::Window> normal_window(CreateNormalWindow(bounds));
    325   scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
    326   EXPECT_EQ(GetPanelContainer(window.get()), window->parent());
    327   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get()));
    328 }
    329 
    330 TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIconSecondDisplay) {
    331   if (!SupportsMultipleDisplays())
    332     return;
    333 
    334   // Keep the displays wide so that launchers have enough
    335   // space for launcher buttons.
    336   UpdateDisplay("400x400,600x400");
    337   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    338 
    339   scoped_ptr<aura::Window> normal_window(
    340       CreateNormalWindow(gfx::Rect(450, 0, 100, 100)));
    341   scoped_ptr<aura::Window> panel(CreatePanelWindow(gfx::Rect(400, 0, 50, 50)));
    342   EXPECT_EQ(root_windows[1], panel->GetRootWindow());
    343   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get()));
    344   gfx::Rect shelf_visible_position = panel->GetBoundsInScreen();
    345 
    346   SetShelfAutoHideBehavior(root_windows[1],
    347                            SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    348   // Expect the panel X position to remain the same after the shelf is hidden
    349   // but the Y to move down.
    350   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get()));
    351   EXPECT_EQ(shelf_visible_position.x(), panel->GetBoundsInScreen().x());
    352   EXPECT_GT(panel->GetBoundsInScreen().y(), shelf_visible_position.y());
    353 }
    354 
    355 // Tests interactions between multiple panels
    356 TEST_F(PanelLayoutManagerTest, MultiplePanelsAreAboveIcons) {
    357   gfx::Rect odd_bounds(0, 0, 201, 201);
    358   gfx::Rect even_bounds(0, 0, 200, 200);
    359 
    360   scoped_ptr<aura::Window> w1(CreatePanelWindow(odd_bounds));
    361   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
    362 
    363   scoped_ptr<aura::Window> w2(CreatePanelWindow(even_bounds));
    364   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
    365   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
    366 
    367   scoped_ptr<aura::Window> w3(CreatePanelWindow(odd_bounds));
    368   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
    369   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
    370   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
    371 }
    372 
    373 TEST_F(PanelLayoutManagerTest, MultiplePanelStacking) {
    374   gfx::Rect bounds(0, 0, 201, 201);
    375   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    376   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    377   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    378 
    379   // Default stacking order.
    380   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
    381   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    382 
    383   // Changing the active window should update the stacking order.
    384   wm::ActivateWindow(w1.get());
    385   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    386   EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get()));
    387   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    388 
    389   wm::ActivateWindow(w2.get());
    390   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    391   EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get()));
    392   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    393   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    394 
    395   wm::ActivateWindow(w3.get());
    396   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
    397   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    398 }
    399 
    400 TEST_F(PanelLayoutManagerTest, MultiplePanelStackingVertical) {
    401   // set launcher shelf to be aligned on the right
    402   SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
    403 
    404   // Size panels in such a way that ordering them by X coordinate would cause
    405   // stacking order to be incorrect. Test that stacking order is based on Y.
    406   scoped_ptr<aura::Window> w1(CreatePanelWindow(gfx::Rect(0, 0, 210, 201)));
    407   scoped_ptr<aura::Window> w2(CreatePanelWindow(gfx::Rect(0, 0, 220, 201)));
    408   scoped_ptr<aura::Window> w3(CreatePanelWindow(gfx::Rect(0, 0, 200, 201)));
    409 
    410   // Default stacking order.
    411   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
    412   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    413 
    414   // Changing the active window should update the stacking order.
    415   wm::ActivateWindow(w1.get());
    416   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    417   EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get()));
    418   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    419 
    420   wm::ActivateWindow(w2.get());
    421   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    422   EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get()));
    423   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    424   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    425 
    426   wm::ActivateWindow(w3.get());
    427   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
    428   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    429 }
    430 
    431 TEST_F(PanelLayoutManagerTest, MultiplePanelCallout) {
    432   gfx::Rect bounds(0, 0, 200, 200);
    433   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    434   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    435   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    436   scoped_ptr<aura::Window> w4(CreateNormalWindow(gfx::Rect()));
    437   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    438   EXPECT_TRUE(IsPanelCalloutVisible(w1.get()));
    439   EXPECT_TRUE(IsPanelCalloutVisible(w2.get()));
    440   EXPECT_TRUE(IsPanelCalloutVisible(w3.get()));
    441   wm::ActivateWindow(w1.get());
    442   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w1.get()));
    443   wm::ActivateWindow(w2.get());
    444   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get()));
    445   wm::ActivateWindow(w3.get());
    446   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
    447   wm::ActivateWindow(w4.get());
    448   wm::ActivateWindow(w3.get());
    449   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
    450   w3.reset();
    451   EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get()));
    452 }
    453 
    454 // Tests removing panels.
    455 TEST_F(PanelLayoutManagerTest, RemoveLeftPanel) {
    456   gfx::Rect bounds(0, 0, 201, 201);
    457   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    458   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    459   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    460 
    461   // At this point, windows should be stacked with 1 < 2 < 3
    462   wm::ActivateWindow(w1.get());
    463   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    464   // Now, windows should be stacked 1 > 2 > 3
    465   w1.reset();
    466   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
    467   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
    468   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    469 }
    470 
    471 TEST_F(PanelLayoutManagerTest, RemoveMiddlePanel) {
    472   gfx::Rect bounds(0, 0, 201, 201);
    473   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    474   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    475   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    476 
    477   // At this point, windows should be stacked with 1 < 2 < 3
    478   wm::ActivateWindow(w2.get());
    479   // Windows should be stacked 1 < 2 > 3
    480   w2.reset();
    481   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
    482   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
    483   EXPECT_TRUE(WindowIsAbove(w3.get(), w1.get()));
    484 }
    485 
    486 TEST_F(PanelLayoutManagerTest, RemoveRightPanel) {
    487   gfx::Rect bounds(0, 0, 201, 201);
    488   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    489   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    490   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    491 
    492   // At this point, windows should be stacked with 1 < 2 < 3
    493   wm::ActivateWindow(w3.get());
    494   // Order shouldn't change.
    495   w3.reset();
    496   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
    497   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
    498   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
    499 }
    500 
    501 TEST_F(PanelLayoutManagerTest, RemoveNonActivePanel) {
    502   gfx::Rect bounds(0, 0, 201, 201);
    503   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    504   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    505   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    506 
    507   // At this point, windows should be stacked with 1 < 2 < 3
    508   wm::ActivateWindow(w2.get());
    509   // Windows should be stacked 1 < 2 > 3
    510   w1.reset();
    511   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
    512   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
    513   EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
    514 }
    515 
    516 TEST_F(PanelLayoutManagerTest, SplitView) {
    517   gfx::Rect bounds(0, 0, 90, 201);
    518   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    519   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    520 
    521   EXPECT_NO_FATAL_FAILURE(PanelsNotOverlapping(w1.get(), w2.get()));
    522 }
    523 
    524 #if defined(OS_WIN)
    525 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
    526 #define MAYBE_SplitViewOverlapWhenLarge DISABLED_SplitViewOverlapWhenLarge
    527 #else
    528 #define MAYBE_SplitViewOverlapWhenLarge SplitViewOverlapWhenLarge
    529 #endif
    530 
    531 TEST_F(PanelLayoutManagerTest, MAYBE_SplitViewOverlapWhenLarge) {
    532   gfx::Rect bounds(0, 0, 600, 201);
    533   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    534   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    535 
    536   EXPECT_NO_FATAL_FAILURE(PanelInScreen(w1.get()));
    537   EXPECT_NO_FATAL_FAILURE(PanelInScreen(w2.get()));
    538 }
    539 
    540 TEST_F(PanelLayoutManagerTest, FanWindows) {
    541   gfx::Rect bounds(0, 0, 201, 201);
    542   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    543   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    544   scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
    545 
    546   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    547   int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x();
    548   int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x();
    549   int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x();
    550   Launcher* launcher = Launcher::ForPrimaryDisplay();
    551   int icon_x1 = launcher->GetScreenBoundsOfItemIconForWindow(w1.get()).x();
    552   int icon_x2 = launcher->GetScreenBoundsOfItemIconForWindow(w2.get()).x();
    553   EXPECT_EQ(window_x2 - window_x1, window_x3 - window_x2);
    554   int spacing = window_x2 - window_x1;
    555   EXPECT_GT(spacing, icon_x2 - icon_x1);
    556 }
    557 
    558 TEST_F(PanelLayoutManagerTest, FanLargeWindow) {
    559   gfx::Rect small_bounds(0, 0, 201, 201);
    560   gfx::Rect large_bounds(0, 0, 501, 201);
    561   scoped_ptr<aura::Window> w1(CreatePanelWindow(small_bounds));
    562   scoped_ptr<aura::Window> w2(CreatePanelWindow(large_bounds));
    563   scoped_ptr<aura::Window> w3(CreatePanelWindow(small_bounds));
    564 
    565   shelf_view_test()->RunMessageLoopUntilAnimationsDone();
    566   int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x();
    567   int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x();
    568   int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x();
    569   // The distances may not be equidistant with a large panel but the panels
    570   // should be in the correct order with respect to their midpoints.
    571   EXPECT_GT(window_x2, window_x1);
    572   EXPECT_GT(window_x3, window_x2);
    573 }
    574 
    575 TEST_F(PanelLayoutManagerTest, MinimizeRestorePanel) {
    576   gfx::Rect bounds(0, 0, 201, 201);
    577   scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
    578   // Activate the window, ensure callout is visible.
    579   wm::ActivateWindow(window.get());
    580   RunAllPendingInMessageLoop();
    581   EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
    582   // Minimize the panel, callout should be hidden.
    583   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
    584   RunAllPendingInMessageLoop();
    585   EXPECT_FALSE(IsPanelCalloutVisible(window.get()));
    586   // Restore the pantel; panel should not be activated by default but callout
    587   // should be visible.
    588   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    589   RunAllPendingInMessageLoop();
    590   EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
    591   // Activate the window, ensure callout is visible.
    592   wm::ActivateWindow(window.get());
    593   RunAllPendingInMessageLoop();
    594   EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
    595 }
    596 
    597 TEST_F(PanelLayoutManagerTest, PanelMoveBetweenMultipleDisplays) {
    598   if (!SupportsMultipleDisplays())
    599     return;
    600 
    601   // Keep the displays wide so that launchers have enough
    602   // space for launcher buttons.
    603   UpdateDisplay("600x400,600x400");
    604   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    605 
    606   scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
    607   scoped_ptr<aura::Window> p2_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
    608   scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
    609   scoped_ptr<aura::Window> p2_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
    610 
    611   ShelfView* shelf_view_1st = GetShelfView(Launcher::ForPrimaryDisplay());
    612   ShelfView* shelf_view_2nd =
    613       GetShelfView(Launcher::ForWindow(root_windows[1]));
    614 
    615   EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
    616   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    617   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    618   EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
    619 
    620   EXPECT_EQ(internal::kShellWindowId_PanelContainer, p1_d1->parent()->id());
    621   EXPECT_EQ(internal::kShellWindowId_PanelContainer, p2_d1->parent()->id());
    622   EXPECT_EQ(internal::kShellWindowId_PanelContainer, p1_d2->parent()->id());
    623   EXPECT_EQ(internal::kShellWindowId_PanelContainer, p2_d2->parent()->id());
    624 
    625   // Test a panel on 1st display.
    626   // Clicking on the same display has no effect.
    627   ClickLauncherItemForWindow(shelf_view_1st, p1_d1.get());
    628   EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
    629   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    630   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    631   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    632   EXPECT_FALSE(root_windows[1]->GetBoundsInScreen().Contains(
    633       p1_d1->GetBoundsInScreen()));
    634 
    635   // Test if clicking on another display moves the panel to
    636   // that display.
    637   ClickLauncherItemForWindow(shelf_view_2nd, p1_d1.get());
    638   EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
    639   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    640   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    641   EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
    642   EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
    643       p1_d1->GetBoundsInScreen()));
    644 
    645   // Test a panel on 2nd display.
    646   // Clicking on the same display has no effect.
    647   ClickLauncherItemForWindow(shelf_view_2nd, p1_d2.get());
    648   EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
    649   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    650   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    651   EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
    652   EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
    653       p1_d2->GetBoundsInScreen()));
    654 
    655   // Test if clicking on another display moves the panel to
    656   // that display.
    657   ClickLauncherItemForWindow(shelf_view_1st, p1_d2.get());
    658   EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
    659   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    660   EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow());
    661   EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
    662   EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
    663       p1_d2->GetBoundsInScreen()));
    664 
    665   // Test if clicking on a previously moved window moves the
    666   // panel back to the original display.
    667   ClickLauncherItemForWindow(shelf_view_1st, p1_d1.get());
    668   EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
    669   EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
    670   EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow());
    671   EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
    672   EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
    673       p1_d1->GetBoundsInScreen()));
    674 }
    675 
    676 TEST_F(PanelLayoutManagerTest, PanelAttachPositionMultipleDisplays) {
    677   if (!SupportsMultipleDisplays())
    678     return;
    679 
    680   // Keep the displays wide so that launchers have enough space for launcher
    681   // buttons. Use differently sized displays so the launcher is in a different
    682   // position on second display.
    683   UpdateDisplay("600x400,600x600");
    684   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    685 
    686   scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
    687   scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
    688 
    689   EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
    690   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    691 
    692   IsPanelAboveLauncherIcon(p1_d1.get());
    693   IsCalloutAboveLauncherIcon(p1_d1.get());
    694   IsPanelAboveLauncherIcon(p1_d2.get());
    695   IsCalloutAboveLauncherIcon(p1_d2.get());
    696 }
    697 
    698 TEST_F(PanelLayoutManagerTest, PanelAlignmentSecondDisplay) {
    699   if (!SupportsMultipleDisplays())
    700     return;
    701 
    702   UpdateDisplay("600x400,600x400");
    703   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    704 
    705   scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
    706   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
    707 
    708   IsPanelAboveLauncherIcon(p1_d2.get());
    709   IsCalloutAboveLauncherIcon(p1_d2.get());
    710 
    711   SetAlignment(root_windows[1], SHELF_ALIGNMENT_RIGHT);
    712   IsPanelAboveLauncherIcon(p1_d2.get());
    713   IsCalloutAboveLauncherIcon(p1_d2.get());
    714   SetAlignment(root_windows[1], SHELF_ALIGNMENT_LEFT);
    715   IsPanelAboveLauncherIcon(p1_d2.get());
    716   IsCalloutAboveLauncherIcon(p1_d2.get());
    717   SetAlignment(root_windows[1], SHELF_ALIGNMENT_TOP);
    718   IsPanelAboveLauncherIcon(p1_d2.get());
    719   IsCalloutAboveLauncherIcon(p1_d2.get());
    720 }
    721 
    722 TEST_F(PanelLayoutManagerTest, AlignmentLeft) {
    723   gfx::Rect bounds(0, 0, 201, 201);
    724   scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
    725   SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_LEFT);
    726   IsPanelAboveLauncherIcon(w.get());
    727   IsCalloutAboveLauncherIcon(w.get());
    728 }
    729 
    730 TEST_F(PanelLayoutManagerTest, AlignmentRight) {
    731   gfx::Rect bounds(0, 0, 201, 201);
    732   scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
    733   SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
    734   IsPanelAboveLauncherIcon(w.get());
    735   IsCalloutAboveLauncherIcon(w.get());
    736 }
    737 
    738 TEST_F(PanelLayoutManagerTest, AlignmentTop) {
    739   gfx::Rect bounds(0, 0, 201, 201);
    740   scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
    741   SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_TOP);
    742   IsPanelAboveLauncherIcon(w.get());
    743   IsCalloutAboveLauncherIcon(w.get());
    744 }
    745 
    746 // Tests that panels will hide and restore their state with the shelf visibility
    747 // state. This ensures that entering full-screen mode will hide your panels
    748 // until you leave it.
    749 TEST_F(PanelLayoutManagerTest, PanelsHideAndRestoreWithShelf) {
    750   gfx::Rect bounds(0, 0, 201, 201);
    751 
    752   scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
    753   scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
    754   scoped_ptr<aura::Window> w3;
    755   // Minimize w2.
    756   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
    757   RunAllPendingInMessageLoop();
    758   EXPECT_TRUE(w1->IsVisible());
    759   EXPECT_FALSE(w2->IsVisible());
    760 
    761   SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_HIDDEN);
    762   RunAllPendingInMessageLoop();
    763 
    764   // w3 is created while in full-screen mode, should only become visible when
    765   // we exit fullscreen mode.
    766   w3.reset(CreatePanelWindow(bounds));
    767 
    768   EXPECT_FALSE(w1->IsVisible());
    769   EXPECT_FALSE(w2->IsVisible());
    770   EXPECT_FALSE(w3->IsVisible());
    771 
    772   // While in full-screen mode, the panel windows should still be in the
    773   // switchable window list - http://crbug.com/313919.
    774   MruWindowTracker::WindowList switchable_window_list =
    775       Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
    776   EXPECT_EQ(3u, switchable_window_list.size());
    777   EXPECT_NE(switchable_window_list.end(),
    778       std::find(switchable_window_list.begin(), switchable_window_list.end(),
    779           w1.get()));
    780   EXPECT_NE(switchable_window_list.end(),
    781       std::find(switchable_window_list.begin(), switchable_window_list.end(),
    782           w2.get()));
    783   EXPECT_NE(switchable_window_list.end(),
    784       std::find(switchable_window_list.begin(), switchable_window_list.end(),
    785           w3.get()));
    786 
    787   SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_VISIBLE);
    788   RunAllPendingInMessageLoop();
    789 
    790   // Windows should be restored to their prior state.
    791   EXPECT_TRUE(w1->IsVisible());
    792   EXPECT_FALSE(w2->IsVisible());
    793   EXPECT_TRUE(w3->IsVisible());
    794 }
    795 
    796 INSTANTIATE_TEST_CASE_P(LtrRtl, PanelLayoutManagerTextDirectionTest,
    797                         testing::Bool());
    798 
    799 }  // namespace internal
    800 }  // namespace ash
    801