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