Home | History | Annotate | Download | only in shelf
      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/shelf/shelf_layout_manager.h"
      6 
      7 #include "ash/accelerators/accelerator_controller.h"
      8 #include "ash/accelerators/accelerator_table.h"
      9 #include "ash/ash_switches.h"
     10 #include "ash/display/display_controller.h"
     11 #include "ash/display/display_manager.h"
     12 #include "ash/focus_cycler.h"
     13 #include "ash/launcher/launcher.h"
     14 #include "ash/launcher/launcher_view.h"
     15 #include "ash/root_window_controller.h"
     16 #include "ash/screen_ash.h"
     17 #include "ash/session_state_delegate.h"
     18 #include "ash/shelf/shelf_layout_manager_observer.h"
     19 #include "ash/shelf/shelf_widget.h"
     20 #include "ash/shell.h"
     21 #include "ash/shell_window_ids.h"
     22 #include "ash/system/status_area_widget.h"
     23 #include "ash/system/tray/system_tray.h"
     24 #include "ash/system/tray/system_tray_item.h"
     25 #include "ash/test/ash_test_base.h"
     26 #include "ash/wm/window_properties.h"
     27 #include "ash/wm/window_util.h"
     28 #include "base/command_line.h"
     29 #include "base/strings/utf_string_conversions.h"
     30 #include "ui/aura/client/aura_constants.h"
     31 #include "ui/aura/root_window.h"
     32 #include "ui/aura/test/event_generator.h"
     33 #include "ui/aura/window.h"
     34 #include "ui/base/animation/animation_container_element.h"
     35 #include "ui/compositor/layer.h"
     36 #include "ui/compositor/layer_animator.h"
     37 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
     38 #include "ui/gfx/display.h"
     39 #include "ui/gfx/screen.h"
     40 #include "ui/views/controls/label.h"
     41 #include "ui/views/layout/fill_layout.h"
     42 #include "ui/views/view.h"
     43 #include "ui/views/widget/widget.h"
     44 
     45 #if defined(OS_WIN)
     46 #include "base/win/windows_version.h"
     47 #endif
     48 
     49 namespace ash {
     50 namespace internal {
     51 
     52 namespace {
     53 
     54 void StepWidgetLayerAnimatorToEnd(views::Widget* widget) {
     55   ui::AnimationContainerElement* element =
     56       static_cast<ui::AnimationContainerElement*>(
     57       widget->GetNativeView()->layer()->GetAnimator());
     58   element->Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
     59 }
     60 
     61 ShelfWidget* GetShelfWidget() {
     62   return Shell::GetPrimaryRootWindowController()->shelf();
     63 }
     64 
     65 ShelfLayoutManager* GetShelfLayoutManager() {
     66   return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
     67 }
     68 
     69 SystemTray* GetSystemTray() {
     70   return Shell::GetPrimaryRootWindowController()->GetSystemTray();
     71 }
     72 
     73 class ShelfDragCallback {
     74  public:
     75   ShelfDragCallback(const gfx::Rect& not_visible, const gfx::Rect& visible)
     76       : not_visible_bounds_(not_visible),
     77         visible_bounds_(visible),
     78         was_visible_on_drag_start_(false) {
     79     EXPECT_EQ(not_visible_bounds_.bottom(), visible_bounds_.bottom());
     80   }
     81 
     82   virtual ~ShelfDragCallback() {
     83   }
     84 
     85   void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
     86     if (GetShelfLayoutManager()->visibility_state() == ash::SHELF_HIDDEN)
     87       return;
     88 
     89     if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
     90       scroll_ = gfx::Vector2dF();
     91       was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
     92       return;
     93     }
     94 
     95     // The state of the shelf at the end of the gesture is tested separately.
     96     if (type == ui::ET_GESTURE_SCROLL_END)
     97       return;
     98 
     99     if (type == ui::ET_GESTURE_SCROLL_UPDATE)
    100       scroll_.Add(delta);
    101 
    102     gfx::Rect shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
    103     if (GetShelfLayoutManager()->IsHorizontalAlignment()) {
    104       EXPECT_EQ(not_visible_bounds_.bottom(), shelf_bounds.bottom());
    105       EXPECT_EQ(visible_bounds_.bottom(), shelf_bounds.bottom());
    106     } else if (SHELF_ALIGNMENT_RIGHT ==
    107         GetShelfLayoutManager()->GetAlignment()){
    108       EXPECT_EQ(not_visible_bounds_.right(), shelf_bounds.right());
    109       EXPECT_EQ(visible_bounds_.right(), shelf_bounds.right());
    110     } else if (SHELF_ALIGNMENT_LEFT ==
    111         GetShelfLayoutManager()->GetAlignment()) {
    112       EXPECT_EQ(not_visible_bounds_.x(), shelf_bounds.x());
    113       EXPECT_EQ(visible_bounds_.x(), shelf_bounds.x());
    114     }
    115 
    116     // if the shelf is being dimmed test dimmer bounds as well.
    117     if (GetShelfWidget()->GetDimsShelf())
    118       EXPECT_EQ(GetShelfWidget()->GetWindowBoundsInScreen(),
    119                 GetShelfWidget()->GetDimmerBoundsForTest());
    120 
    121     // The shelf should never be smaller than the hidden state.
    122     EXPECT_GE(shelf_bounds.height(), not_visible_bounds_.height());
    123     float scroll_delta = GetShelfLayoutManager()->PrimaryAxisValue(
    124         scroll_.y(),
    125         scroll_.x());
    126     bool increasing_drag =
    127         GetShelfLayoutManager()->SelectValueForShelfAlignment(
    128             scroll_delta < 0,
    129             scroll_delta > 0,
    130             scroll_delta < 0,
    131             scroll_delta > 0);
    132     int shelf_size = GetShelfLayoutManager()->PrimaryAxisValue(
    133         shelf_bounds.height(),
    134         shelf_bounds.width());
    135     int visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
    136         visible_bounds_.height(),
    137         visible_bounds_.width());
    138     int not_visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
    139         not_visible_bounds_.height(),
    140         not_visible_bounds_.width());
    141     if (was_visible_on_drag_start_) {
    142       if (increasing_drag) {
    143         // If dragging inwards from the visible state, then the shelf should
    144         // increase in size, but not more than the scroll delta.
    145         EXPECT_LE(visible_bounds_size, shelf_size);
    146         EXPECT_LE(abs(shelf_size - visible_bounds_size),
    147                   abs(scroll_delta));
    148       } else {
    149         if (shelf_size > not_visible_bounds_size) {
    150           // If dragging outwards from the visible state, then the shelf
    151           // should decrease in size, until it reaches the minimum size.
    152           EXPECT_EQ(shelf_size, visible_bounds_size - abs(scroll_delta));
    153         }
    154       }
    155     } else {
    156       if (fabs(scroll_delta) <
    157           visible_bounds_size - not_visible_bounds_size) {
    158         // Tests that the shelf sticks with the touch point during the drag
    159         // until the shelf is completely visible.
    160         EXPECT_EQ(shelf_size, not_visible_bounds_size + abs(scroll_delta));
    161       } else {
    162         // Tests that after the shelf is completely visible, the shelf starts
    163         // resisting the drag.
    164         EXPECT_LT(shelf_size, not_visible_bounds_size + abs(scroll_delta));
    165       }
    166     }
    167   }
    168 
    169  private:
    170   const gfx::Rect not_visible_bounds_;
    171   const gfx::Rect visible_bounds_;
    172   gfx::Vector2dF scroll_;
    173   bool was_visible_on_drag_start_;
    174 
    175   DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback);
    176 };
    177 
    178 class ShelfLayoutObserverTest : public ShelfLayoutManagerObserver {
    179  public:
    180   ShelfLayoutObserverTest()
    181       : changed_auto_hide_state_(false) {
    182   }
    183 
    184   virtual ~ShelfLayoutObserverTest() {}
    185 
    186   bool changed_auto_hide_state() const { return changed_auto_hide_state_; }
    187 
    188  private:
    189   virtual void OnAutoHideStateChanged(
    190       ShelfAutoHideState new_state) OVERRIDE {
    191     changed_auto_hide_state_ = true;
    192   }
    193 
    194   bool changed_auto_hide_state_;
    195 
    196   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest);
    197 };
    198 
    199 // Trivial item implementation that tracks its views for testing.
    200 class TestItem : public SystemTrayItem {
    201  public:
    202   TestItem()
    203       : SystemTrayItem(GetSystemTray()),
    204         tray_view_(NULL),
    205         default_view_(NULL),
    206         detailed_view_(NULL),
    207         notification_view_(NULL) {}
    208 
    209   virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE {
    210     tray_view_ = new views::View;
    211     // Add a label so it has non-zero width.
    212     tray_view_->SetLayoutManager(new views::FillLayout);
    213     tray_view_->AddChildView(new views::Label(UTF8ToUTF16("Tray")));
    214     return tray_view_;
    215   }
    216 
    217   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
    218     default_view_ = new views::View;
    219     default_view_->SetLayoutManager(new views::FillLayout);
    220     default_view_->AddChildView(new views::Label(UTF8ToUTF16("Default")));
    221     return default_view_;
    222   }
    223 
    224   virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE {
    225     detailed_view_ = new views::View;
    226     detailed_view_->SetLayoutManager(new views::FillLayout);
    227     detailed_view_->AddChildView(new views::Label(UTF8ToUTF16("Detailed")));
    228     return detailed_view_;
    229   }
    230 
    231   virtual views::View* CreateNotificationView(
    232       user::LoginStatus status) OVERRIDE {
    233     notification_view_ = new views::View;
    234     return notification_view_;
    235   }
    236 
    237   virtual void DestroyTrayView() OVERRIDE {
    238     tray_view_ = NULL;
    239   }
    240 
    241   virtual void DestroyDefaultView() OVERRIDE {
    242     default_view_ = NULL;
    243   }
    244 
    245   virtual void DestroyDetailedView() OVERRIDE {
    246     detailed_view_ = NULL;
    247   }
    248 
    249   virtual void DestroyNotificationView() OVERRIDE {
    250     notification_view_ = NULL;
    251   }
    252 
    253   virtual void UpdateAfterLoginStatusChange(
    254       user::LoginStatus status) OVERRIDE {}
    255 
    256   views::View* tray_view() const { return tray_view_; }
    257   views::View* default_view() const { return default_view_; }
    258   views::View* detailed_view() const { return detailed_view_; }
    259   views::View* notification_view() const { return notification_view_; }
    260 
    261  private:
    262   views::View* tray_view_;
    263   views::View* default_view_;
    264   views::View* detailed_view_;
    265   views::View* notification_view_;
    266 
    267   DISALLOW_COPY_AND_ASSIGN(TestItem);
    268 };
    269 
    270 }  // namespace
    271 
    272 class ShelfLayoutManagerTest : public ash::test::AshTestBase {
    273  public:
    274   ShelfLayoutManagerTest() {}
    275 
    276   void SetState(ShelfLayoutManager* shelf,
    277                 ShelfVisibilityState state) {
    278     shelf->SetState(state);
    279   }
    280 
    281   void UpdateAutoHideStateNow() {
    282     GetShelfLayoutManager()->UpdateAutoHideStateNow();
    283   }
    284 
    285   aura::Window* CreateTestWindow() {
    286     aura::Window* window = new aura::Window(NULL);
    287     window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    288     window->SetType(aura::client::WINDOW_TYPE_NORMAL);
    289     window->Init(ui::LAYER_TEXTURED);
    290     SetDefaultParentByPrimaryRootWindow(window);
    291     return window;
    292   }
    293 
    294   views::Widget* CreateTestWidgetWithParams(
    295       const views::Widget::InitParams& params) {
    296     views::Widget* out = new views::Widget;
    297     out->Init(params);
    298     out->Show();
    299     return out;
    300   }
    301 
    302   // Create a simple widget attached to the current context (will
    303   // delete on TearDown).
    304   views::Widget* CreateTestWidget() {
    305     views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    306     params.bounds = gfx::Rect(0, 0, 200, 200);
    307     params.context = CurrentContext();
    308     return CreateTestWidgetWithParams(params);
    309   }
    310 
    311   // Overridden from AshTestBase:
    312   virtual void SetUp() OVERRIDE {
    313     CommandLine::ForCurrentProcess()->AppendSwitch(
    314         ash::switches::kAshEnableTrayDragging);
    315     test::AshTestBase::SetUp();
    316   }
    317 
    318   void RunGestureDragTests(gfx::Vector2d);
    319 
    320  private:
    321   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
    322 };
    323 
    324 void ShelfLayoutManagerTest::RunGestureDragTests(gfx::Vector2d delta) {
    325   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    326   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
    327   views::Widget* widget = new views::Widget;
    328   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    329   params.bounds = gfx::Rect(0, 0, 200, 200);
    330   params.context = CurrentContext();
    331   widget->Init(params);
    332   widget->Show();
    333   widget->Maximize();
    334 
    335   aura::Window* window = widget->GetNativeWindow();
    336   shelf->LayoutShelf();
    337 
    338   gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
    339   gfx::Rect bounds_shelf = window->bounds();
    340   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    341 
    342   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    343   shelf->LayoutShelf();
    344   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    345 
    346   gfx::Rect bounds_noshelf = window->bounds();
    347   gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
    348 
    349   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
    350   shelf->LayoutShelf();
    351 
    352   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
    353   const int kNumScrollSteps = 10;
    354   ShelfDragCallback handler(shelf_hidden, shelf_shown);
    355 
    356   // Swipe up on the shelf. This should not change any state.
    357   gfx::Point start = GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
    358   gfx::Point end = start + delta;
    359 
    360   // Swipe down on the shelf to hide it.
    361   generator.GestureScrollSequenceWithCallback(start, end,
    362       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    363       base::Bind(&ShelfDragCallback::ProcessScroll,
    364                  base::Unretained(&handler)));
    365   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    366   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    367   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    368   EXPECT_NE(bounds_shelf.ToString(), window->bounds().ToString());
    369   EXPECT_NE(shelf_shown.ToString(),
    370             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    371 
    372   // Swipe up to show the shelf.
    373   generator.GestureScrollSequenceWithCallback(end, start,
    374       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    375       base::Bind(&ShelfDragCallback::ProcessScroll,
    376                  base::Unretained(&handler)));
    377   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    378   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
    379   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
    380   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
    381             GetShelfWidget()->GetWindowBoundsInScreen());
    382   EXPECT_EQ(shelf_shown.ToString(),
    383             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    384 
    385   // Swipe up again. The shelf should hide.
    386   end = start - delta;
    387   generator.GestureScrollSequenceWithCallback(start, end,
    388       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    389       base::Bind(&ShelfDragCallback::ProcessScroll,
    390                  base::Unretained(&handler)));
    391   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    392   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    393   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    394   EXPECT_EQ(shelf_hidden.ToString(),
    395             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    396 
    397   // Swipe up yet again to show it.
    398   end = start + delta;
    399   generator.GestureScrollSequenceWithCallback(end, start,
    400       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    401       base::Bind(&ShelfDragCallback::ProcessScroll,
    402                  base::Unretained(&handler)));
    403 
    404   // Swipe down very little. It shouldn't change any state.
    405   if (GetShelfLayoutManager()->IsHorizontalAlignment())
    406     end.set_y(start.y() + shelf_shown.height() * 3 / 10);
    407   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
    408     end.set_x(start.x() - shelf_shown.width() * 3 / 10);
    409   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
    410     end.set_x(start.x() + shelf_shown.width() * 3 / 10);
    411   generator.GestureScrollSequenceWithCallback(start, end,
    412       base::TimeDelta::FromMilliseconds(100), 1,
    413       base::Bind(&ShelfDragCallback::ProcessScroll,
    414                  base::Unretained(&handler)));
    415   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    416   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
    417   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
    418   EXPECT_EQ(shelf_shown.ToString(),
    419             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    420 
    421   // Swipe down again to hide.
    422   end = start + delta;
    423   generator.GestureScrollSequenceWithCallback(start, end,
    424       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    425       base::Bind(&ShelfDragCallback::ProcessScroll,
    426                  base::Unretained(&handler)));
    427   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    428   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    429   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    430   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
    431   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
    432   EXPECT_EQ(shelf_hidden.ToString(),
    433             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    434 
    435   // Swipe up in extended hit region to show it.
    436   gfx::Point extended_start = start;
    437   if (GetShelfLayoutManager()->IsHorizontalAlignment())
    438     extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() -1);
    439   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
    440     extended_start.set_x(
    441         GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
    442   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
    443     extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
    444   end = extended_start - delta;
    445   generator.GestureScrollSequenceWithCallback(extended_start, end,
    446       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    447       base::Bind(&ShelfDragCallback::ProcessScroll,
    448                  base::Unretained(&handler)));
    449   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    450   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
    451   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
    452   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
    453             GetShelfWidget()->GetWindowBoundsInScreen());
    454   EXPECT_EQ(shelf_shown.ToString(),
    455             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    456 
    457   // Swipe down again to hide.
    458   end = start + delta;
    459   generator.GestureScrollSequenceWithCallback(start, end,
    460       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    461       base::Bind(&ShelfDragCallback::ProcessScroll,
    462                  base::Unretained(&handler)));
    463   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    464   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    465   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    466   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
    467   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
    468   EXPECT_EQ(shelf_hidden.ToString(),
    469             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    470 
    471   // Swipe up outside the hit area. This should not change anything.
    472   gfx::Point outside_start = gfx::Point(
    473       (GetShelfWidget()->GetWindowBoundsInScreen().x() +
    474        GetShelfWidget()->GetWindowBoundsInScreen().right())/2,
    475       GetShelfWidget()->GetWindowBoundsInScreen().y() - 50);
    476   end = outside_start + delta;
    477   generator.GestureScrollSequence(outside_start,
    478                                   end,
    479                                   base::TimeDelta::FromMilliseconds(10),
    480                                   kNumScrollSteps);
    481   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    482   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    483   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    484   EXPECT_EQ(shelf_hidden.ToString(),
    485             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    486 
    487   // Swipe up from below the shelf where a bezel would be, this should show the
    488   // shelf.
    489   gfx::Point below_start = start;
    490   if (GetShelfLayoutManager()->IsHorizontalAlignment())
    491     below_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().bottom() + 1);
    492   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
    493     below_start.set_x(
    494         GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
    495   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
    496     below_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
    497   end = below_start - delta;
    498   generator.GestureScrollSequence(below_start,
    499                                   end,
    500                                   base::TimeDelta::FromMilliseconds(10),
    501                                   kNumScrollSteps);
    502   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    503   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
    504   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
    505   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
    506             GetShelfWidget()->GetWindowBoundsInScreen());
    507   EXPECT_EQ(shelf_shown.ToString(),
    508             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    509 
    510   // Swipe down again to hide.
    511   end = start + delta;
    512   generator.GestureScrollSequenceWithCallback(start, end,
    513       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    514       base::Bind(&ShelfDragCallback::ProcessScroll,
    515                  base::Unretained(&handler)));
    516   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    517   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    518   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    519   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
    520   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
    521   EXPECT_EQ(shelf_hidden.ToString(),
    522             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    523 
    524   // Enter into fullscreen with minimal chrome (immersive fullscreen).
    525   widget->SetFullscreen(true);
    526   window->SetProperty(ash::internal::kFullscreenUsesMinimalChromeKey, true);
    527   shelf->UpdateVisibilityState();
    528 
    529   gfx::Rect bounds_fullscreen = window->bounds();
    530   EXPECT_TRUE(widget->IsFullscreen());
    531   EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
    532 
    533   // Swipe up. This should show the shelf.
    534   end = below_start - delta;
    535   generator.GestureScrollSequenceWithCallback(below_start, end,
    536       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    537       base::Bind(&ShelfDragCallback::ProcessScroll,
    538                  base::Unretained(&handler)));
    539   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    540   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    541   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
    542   EXPECT_EQ(shelf_shown.ToString(),
    543             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    544   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
    545 
    546   // Swipe up again. This should hide the shelf.
    547   generator.GestureScrollSequenceWithCallback(below_start, end,
    548       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    549       base::Bind(&ShelfDragCallback::ProcessScroll,
    550                  base::Unretained(&handler)));
    551   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    552   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    553   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    554   EXPECT_EQ(shelf_hidden.ToString(),
    555             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
    556   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
    557 
    558   // Put the window into fullscreen without any chrome at all (eg tab
    559   // fullscreen).
    560   window->SetProperty(ash::internal::kFullscreenUsesMinimalChromeKey, false);
    561   shelf->UpdateVisibilityState();
    562   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
    563   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    564 
    565   // Swipe-up. This should not change anything.
    566   end = start - delta;
    567   generator.GestureScrollSequenceWithCallback(below_start, end,
    568       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    569       base::Bind(&ShelfDragCallback::ProcessScroll,
    570                  base::Unretained(&handler)));
    571   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
    572   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    573   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
    574 
    575   // Close actually, otherwise further event may be affected since widget
    576   // is fullscreen status.
    577   widget->Close();
    578   RunAllPendingInMessageLoop();
    579 
    580   // The shelf should be shown because there are no more visible windows.
    581   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    582   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    583   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    584 
    585   // Swipe-up to hide. This should have no effect because there are no visible
    586   // windows.
    587   end = below_start - delta;
    588   generator.GestureScrollSequenceWithCallback(below_start, end,
    589       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
    590       base::Bind(&ShelfDragCallback::ProcessScroll,
    591                  base::Unretained(&handler)));
    592   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    593   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    594   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
    595 }
    596 
    597 // Fails on Mac only.  Need to be implemented.  http://crbug.com/111279.
    598 #if defined(OS_MACOSX) || defined(OS_WIN)
    599 #define MAYBE_SetVisible DISABLED_SetVisible
    600 #else
    601 #define MAYBE_SetVisible SetVisible
    602 #endif
    603 // Makes sure SetVisible updates work area and widget appropriately.
    604 TEST_F(ShelfLayoutManagerTest, MAYBE_SetVisible) {
    605   ShelfWidget* shelf = GetShelfWidget();
    606   ShelfLayoutManager* manager = shelf->shelf_layout_manager();
    607   // Force an initial layout.
    608   manager->LayoutShelf();
    609   EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
    610 
    611   gfx::Rect status_bounds(
    612       shelf->status_area_widget()->GetWindowBoundsInScreen());
    613   gfx::Rect launcher_bounds(
    614       shelf->GetWindowBoundsInScreen());
    615   int shelf_height = manager->GetIdealBounds().height();
    616   gfx::Screen* screen = Shell::GetScreen();
    617   gfx::Display display = screen->GetDisplayNearestWindow(
    618       Shell::GetPrimaryRootWindow());
    619   ASSERT_NE(-1, display.id());
    620   // Bottom inset should be the max of widget heights.
    621   EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
    622 
    623   // Hide the shelf.
    624   SetState(manager, SHELF_HIDDEN);
    625   // Run the animation to completion.
    626   StepWidgetLayerAnimatorToEnd(shelf);
    627   StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
    628   EXPECT_EQ(SHELF_HIDDEN, manager->visibility_state());
    629   display = screen->GetDisplayNearestWindow(
    630       Shell::GetPrimaryRootWindow());
    631 
    632   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
    633 
    634   // Make sure the bounds of the two widgets changed.
    635   EXPECT_GE(shelf->GetNativeView()->bounds().y(),
    636             screen->GetPrimaryDisplay().bounds().bottom());
    637   EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
    638             screen->GetPrimaryDisplay().bounds().bottom());
    639 
    640   // And show it again.
    641   SetState(manager, SHELF_VISIBLE);
    642   // Run the animation to completion.
    643   StepWidgetLayerAnimatorToEnd(shelf);
    644   StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
    645   EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
    646   display = screen->GetDisplayNearestWindow(
    647       Shell::GetPrimaryRootWindow());
    648   EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
    649 
    650   // Make sure the bounds of the two widgets changed.
    651   launcher_bounds = shelf->GetNativeView()->bounds();
    652   int bottom =
    653       screen->GetPrimaryDisplay().bounds().bottom() - shelf_height;
    654   EXPECT_EQ(launcher_bounds.y(),
    655             bottom + (manager->GetIdealBounds().height() -
    656                       launcher_bounds.height()) / 2);
    657   status_bounds = shelf->status_area_widget()->GetNativeView()->bounds();
    658   EXPECT_EQ(status_bounds.y(),
    659             bottom + shelf_height - status_bounds.height());
    660 }
    661 
    662 // Makes sure LayoutShelf invoked while animating cleans things up.
    663 TEST_F(ShelfLayoutManagerTest, LayoutShelfWhileAnimating) {
    664   ShelfWidget* shelf = GetShelfWidget();
    665   // Force an initial layout.
    666   shelf->shelf_layout_manager()->LayoutShelf();
    667   EXPECT_EQ(SHELF_VISIBLE, shelf->shelf_layout_manager()->visibility_state());
    668 
    669   // Hide the shelf.
    670   SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
    671   shelf->shelf_layout_manager()->LayoutShelf();
    672   EXPECT_EQ(SHELF_HIDDEN, shelf->shelf_layout_manager()->visibility_state());
    673   gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
    674       Shell::GetPrimaryRootWindow());
    675   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
    676 
    677   // Make sure the bounds of the two widgets changed.
    678   EXPECT_GE(shelf->GetNativeView()->bounds().y(),
    679             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
    680   EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
    681             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
    682 }
    683 
    684 // Test that switching to a different visibility state does not restart the
    685 // shelf show / hide animation if it is already running. (crbug.com/250918)
    686 TEST_F(ShelfLayoutManagerTest, SetStateWhileAnimating) {
    687   ShelfWidget* shelf = GetShelfWidget();
    688   SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
    689   gfx::Rect initial_shelf_bounds = shelf->GetWindowBoundsInScreen();
    690   gfx::Rect initial_status_bounds =
    691       shelf->status_area_widget()->GetWindowBoundsInScreen();
    692 
    693   ui::ScopedAnimationDurationScaleMode normal_animation_duration(
    694       ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
    695   SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
    696   SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
    697 
    698   gfx::Rect current_shelf_bounds = shelf->GetWindowBoundsInScreen();
    699   gfx::Rect current_status_bounds =
    700       shelf->status_area_widget()->GetWindowBoundsInScreen();
    701 
    702   const int small_change = initial_shelf_bounds.height() / 2;
    703   EXPECT_LE(
    704       std::abs(initial_shelf_bounds.height() - current_shelf_bounds.height()),
    705       small_change);
    706   EXPECT_LE(
    707       std::abs(initial_status_bounds.height() - current_status_bounds.height()),
    708       small_change);
    709 }
    710 
    711 // Makes sure the launcher is sized when the status area changes size.
    712 TEST_F(ShelfLayoutManagerTest, LauncherUpdatedWhenStatusAreaChangesSize) {
    713   Launcher* launcher = Launcher::ForPrimaryDisplay();
    714   ASSERT_TRUE(launcher);
    715   ShelfWidget* shelf_widget = GetShelfWidget();
    716   ASSERT_TRUE(shelf_widget);
    717   ASSERT_TRUE(shelf_widget->status_area_widget());
    718   shelf_widget->status_area_widget()->SetBounds(
    719       gfx::Rect(0, 0, 200, 200));
    720   EXPECT_EQ(200, shelf_widget->GetContentsView()->width() -
    721             launcher->GetLauncherViewForTest()->width());
    722 }
    723 
    724 
    725 #if defined(OS_WIN)
    726 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
    727 #define MAYBE_AutoHide DISABLED_AutoHide
    728 #else
    729 #define MAYBE_AutoHide AutoHide
    730 #endif
    731 
    732 // Various assertions around auto-hide.
    733 TEST_F(ShelfLayoutManagerTest, MAYBE_AutoHide) {
    734   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
    735   aura::test::EventGenerator generator(root, root);
    736   generator.MoveMouseTo(0, 0);
    737 
    738   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    739   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    740   views::Widget* widget = new views::Widget;
    741   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    742   params.bounds = gfx::Rect(0, 0, 200, 200);
    743   params.context = CurrentContext();
    744   // Widget is now owned by the parent window.
    745   widget->Init(params);
    746   widget->Maximize();
    747   widget->Show();
    748   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    749   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    750 
    751   // LayoutShelf() forces the animation to completion, at which point the
    752   // launcher should go off the screen.
    753   shelf->LayoutShelf();
    754   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
    755             GetShelfWidget()->GetWindowBoundsInScreen().y());
    756   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
    757             Shell::GetScreen()->GetDisplayNearestWindow(
    758                 root).work_area().bottom());
    759 
    760   // Move the mouse to the bottom of the screen.
    761   generator.MoveMouseTo(0, root->bounds().bottom() - 1);
    762 
    763   // Shelf should be shown again (but it shouldn't have changed the work area).
    764   SetState(shelf, SHELF_AUTO_HIDE);
    765   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    766   shelf->LayoutShelf();
    767   EXPECT_EQ(root->bounds().bottom() - shelf->GetIdealBounds().height(),
    768             GetShelfWidget()->GetWindowBoundsInScreen().y());
    769   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
    770             Shell::GetScreen()->GetDisplayNearestWindow(
    771                 root).work_area().bottom());
    772 
    773   // Move mouse back up.
    774   generator.MoveMouseTo(0, 0);
    775   SetState(shelf, SHELF_AUTO_HIDE);
    776   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    777   shelf->LayoutShelf();
    778   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
    779             GetShelfWidget()->GetWindowBoundsInScreen().y());
    780 
    781   // Drag mouse to bottom of screen.
    782   generator.PressLeftButton();
    783   generator.MoveMouseTo(0, root->bounds().bottom() - 1);
    784   UpdateAutoHideStateNow();
    785   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    786 
    787   generator.ReleaseLeftButton();
    788   generator.MoveMouseTo(1, root->bounds().bottom() - 1);
    789   UpdateAutoHideStateNow();
    790   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    791   generator.PressLeftButton();
    792   generator.MoveMouseTo(1, root->bounds().bottom() - 1);
    793   UpdateAutoHideStateNow();
    794   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    795 }
    796 
    797 // Test the behavior of the shelf when it is auto hidden and it is on the
    798 // boundary between the primary and the secondary display.
    799 TEST_F(ShelfLayoutManagerTest, AutoHideShelfOnScreenBoundary) {
    800   if (!SupportsMultipleDisplays())
    801     return;
    802 
    803   UpdateDisplay("800x600,800x600");
    804   DisplayLayout display_layout(DisplayLayout::RIGHT, 0);
    805   Shell::GetInstance()->display_controller()->SetLayoutForCurrentDisplays(
    806       display_layout);
    807   // Put the primary monitor's shelf on the display boundary.
    808   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    809   shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
    810 
    811   // Create a window because the shelf is always shown when no windows are
    812   // visible.
    813   CreateTestWidget();
    814 
    815   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
    816   ASSERT_EQ(root_windows[0],
    817             GetShelfWidget()->GetNativeWindow()->GetRootWindow());
    818 
    819   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    820   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    821 
    822   int right_edge = root_windows[0]->GetBoundsInScreen().right() - 1;
    823   int y = root_windows[0]->GetBoundsInScreen().y();
    824 
    825   // Start off the mouse nowhere near the shelf; the shelf should be hidden.
    826   aura::test::EventGenerator& generator(GetEventGenerator());
    827   generator.MoveMouseTo(right_edge - 50, y);
    828   UpdateAutoHideStateNow();
    829   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    830 
    831   // Moving the mouse over the light bar (but not to the edge of the screen)
    832   // should show the shelf.
    833   generator.MoveMouseTo(right_edge - 1, y);
    834   UpdateAutoHideStateNow();
    835   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    836   EXPECT_EQ(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
    837 
    838   // Moving the mouse off the light bar should hide the shelf.
    839   generator.MoveMouseTo(right_edge - 50, y);
    840   UpdateAutoHideStateNow();
    841   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    842 
    843   // Moving the mouse to the right edge of the screen crossing the light bar
    844   // should show the shelf despite the mouse cursor getting warped to the
    845   // secondary display.
    846   generator.MoveMouseTo(right_edge - 1, y);
    847   generator.MoveMouseTo(right_edge, y);
    848   UpdateAutoHideStateNow();
    849   EXPECT_NE(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
    850   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    851 
    852   // Hide the shelf.
    853   generator.MoveMouseTo(right_edge - 50, y);
    854   UpdateAutoHideStateNow();
    855   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    856 
    857   // Moving the mouse to the right edge of the screen crossing the light bar and
    858   // overshooting by a lot should keep the shelf hidden.
    859   generator.MoveMouseTo(right_edge - 1, y);
    860   generator.MoveMouseTo(right_edge + 50, y);
    861   UpdateAutoHideStateNow();
    862   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    863 
    864   // Moving the mouse to the right edge of the screen crossing the light bar and
    865   // overshooting a bit should show the shelf.
    866   generator.MoveMouseTo(right_edge - 1, y);
    867   generator.MoveMouseTo(right_edge + 2, y);
    868   UpdateAutoHideStateNow();
    869   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    870 
    871   // Keeping the mouse close to the left edge of the secondary display after the
    872   // shelf is shown should keep the shelf shown.
    873   generator.MoveMouseTo(right_edge + 2, y + 1);
    874   UpdateAutoHideStateNow();
    875   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
    876 
    877   // Moving the mouse far from the left edge of the secondary display should
    878   // hide the shelf.
    879   generator.MoveMouseTo(right_edge + 50, y);
    880   UpdateAutoHideStateNow();
    881   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    882 
    883   // Moving to the left edge of the secondary display without first crossing
    884   // the primary display's right aligned shelf first should not show the shelf.
    885   generator.MoveMouseTo(right_edge + 2, y);
    886   UpdateAutoHideStateNow();
    887   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    888 }
    889 
    890 // Assertions around the lock screen showing.
    891 TEST_F(ShelfLayoutManagerTest, VisibleWhenLockScreenShowing) {
    892   // Since ShelfLayoutManager queries for mouse location, move the mouse so
    893   // it isn't over the shelf.
    894   aura::test::EventGenerator generator(
    895       Shell::GetPrimaryRootWindow(), gfx::Point());
    896   generator.MoveMouseTo(0, 0);
    897 
    898   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    899   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    900   views::Widget* widget = new views::Widget;
    901   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    902   params.bounds = gfx::Rect(0, 0, 200, 200);
    903   params.context = CurrentContext();
    904   // Widget is now owned by the parent window.
    905   widget->Init(params);
    906   widget->Maximize();
    907   widget->Show();
    908   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    909   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    910 
    911   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
    912   // LayoutShelf() forces the animation to completion, at which point the
    913   // launcher should go off the screen.
    914   shelf->LayoutShelf();
    915   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
    916             GetShelfWidget()->GetWindowBoundsInScreen().y());
    917 
    918   aura::Window* lock_container = Shell::GetContainer(
    919       Shell::GetPrimaryRootWindow(),
    920       internal::kShellWindowId_LockScreenContainer);
    921 
    922   views::Widget* lock_widget = new views::Widget;
    923   views::Widget::InitParams lock_params(
    924       views::Widget::InitParams::TYPE_WINDOW);
    925   lock_params.bounds = gfx::Rect(0, 0, 200, 200);
    926   params.context = CurrentContext();
    927   lock_params.parent = lock_container;
    928   // Widget is now owned by the parent window.
    929   lock_widget->Init(lock_params);
    930   lock_widget->Maximize();
    931   lock_widget->Show();
    932 
    933   // Lock the screen.
    934   Shell::GetInstance()->session_state_delegate()->LockScreen();
    935   shelf->UpdateVisibilityState();
    936   // Showing a widget in the lock screen should force the shelf to be visibile.
    937   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    938 
    939   Shell::GetInstance()->session_state_delegate()->UnlockScreen();
    940   shelf->UpdateVisibilityState();
    941   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    942 }
    943 
    944 // Assertions around SetAutoHideBehavior.
    945 TEST_F(ShelfLayoutManagerTest, SetAutoHideBehavior) {
    946   // Since ShelfLayoutManager queries for mouse location, move the mouse so
    947   // it isn't over the shelf.
    948   aura::test::EventGenerator generator(
    949       Shell::GetPrimaryRootWindow(), gfx::Point());
    950   generator.MoveMouseTo(0, 0);
    951 
    952   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    953   views::Widget* widget = new views::Widget;
    954   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    955   params.bounds = gfx::Rect(0, 0, 200, 200);
    956   params.context = CurrentContext();
    957   // Widget is now owned by the parent window.
    958   widget->Init(params);
    959   widget->Show();
    960   aura::Window* window = widget->GetNativeWindow();
    961   gfx::Rect display_bounds(
    962       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
    963 
    964   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    965   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    966 
    967   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
    968   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    969 
    970   widget->Maximize();
    971   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    972   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    973                 window).work_area().bottom(),
    974             widget->GetWorkAreaBoundsInScreen().bottom());
    975 
    976   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    977   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
    978   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    979                 window).work_area().bottom(),
    980             widget->GetWorkAreaBoundsInScreen().bottom());
    981 
    982   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
    983   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
    984   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    985                 window).work_area().bottom(),
    986             widget->GetWorkAreaBoundsInScreen().bottom());
    987 }
    988 
    989 // Basic assertions around the dimming of the shelf.
    990 TEST_F(ShelfLayoutManagerTest, TestDimmingBehavior) {
    991   // Since ShelfLayoutManager queries for mouse location, move the mouse so
    992   // it isn't over the shelf.
    993   aura::test::EventGenerator generator(
    994       Shell::GetPrimaryRootWindow(), gfx::Point());
    995   generator.MoveMouseTo(0, 0);
    996 
    997   ShelfLayoutManager* shelf = GetShelfLayoutManager();
    998   shelf->shelf_widget()->DisableDimmingAnimationsForTest();
    999 
   1000   views::Widget* widget = new views::Widget;
   1001   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   1002   params.bounds = gfx::Rect(0, 0, 200, 200);
   1003   params.context = CurrentContext();
   1004   // Widget is now owned by the parent window.
   1005   widget->Init(params);
   1006   widget->Show();
   1007   aura::Window* window = widget->GetNativeWindow();
   1008   gfx::Rect display_bounds(
   1009       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
   1010 
   1011   gfx::Point off_shelf = display_bounds.CenterPoint();
   1012   gfx::Point on_shelf =
   1013       shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
   1014 
   1015   // Test there is no dimming object active at this point.
   1016   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
   1017   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1018   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
   1019   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1020 
   1021   // After maximization, the shelf should be visible and the dimmer created.
   1022   widget->Maximize();
   1023 
   1024   on_shelf = shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
   1025   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1026 
   1027   // Moving the mouse off the shelf should dim the bar.
   1028   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
   1029   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1030 
   1031   // Adding touch events outside the shelf should still keep the shelf in
   1032   // dimmed state.
   1033   generator.PressTouch();
   1034   generator.MoveTouch(off_shelf);
   1035   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1036   // Move the touch into the shelf area should undim.
   1037   generator.MoveTouch(on_shelf);
   1038   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1039   generator.ReleaseTouch();
   1040   // And a release dims again.
   1041   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1042 
   1043   // Moving the mouse on the shelf should undim the bar.
   1044   generator.MoveMouseTo(on_shelf);
   1045   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1046 
   1047   // No matter what the touch events do, the shelf should stay undimmed.
   1048   generator.PressTouch();
   1049   generator.MoveTouch(off_shelf);
   1050   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1051   generator.MoveTouch(on_shelf);
   1052   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1053   generator.MoveTouch(off_shelf);
   1054   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1055   generator.MoveTouch(on_shelf);
   1056   generator.ReleaseTouch();
   1057 
   1058   // After restore, the dimming object should be deleted again.
   1059   widget->Restore();
   1060   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1061 }
   1062 
   1063 // Assertions around the dimming of the shelf in conjunction with menus.
   1064 TEST_F(ShelfLayoutManagerTest, TestDimmingBehaviorWithMenus) {
   1065   // Since ShelfLayoutManager queries for mouse location, move the mouse so
   1066   // it isn't over the shelf.
   1067   aura::test::EventGenerator generator(
   1068       Shell::GetPrimaryRootWindow(), gfx::Point());
   1069   generator.MoveMouseTo(0, 0);
   1070 
   1071   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1072   shelf->shelf_widget()->DisableDimmingAnimationsForTest();
   1073 
   1074   views::Widget* widget = new views::Widget;
   1075   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   1076   params.bounds = gfx::Rect(0, 0, 200, 200);
   1077   params.context = CurrentContext();
   1078   // Widget is now owned by the parent window.
   1079   widget->Init(params);
   1080   widget->Show();
   1081   aura::Window* window = widget->GetNativeWindow();
   1082   gfx::Rect display_bounds(
   1083       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
   1084 
   1085   // After maximization, the shelf should be visible and the dimmer created.
   1086   widget->Maximize();
   1087 
   1088   gfx::Point off_shelf = display_bounds.CenterPoint();
   1089   gfx::Point on_shelf =
   1090       shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
   1091 
   1092   // Moving the mouse on the shelf should undim the bar.
   1093   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
   1094   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1095 
   1096   // Simulate a menu opening.
   1097   shelf->shelf_widget()->ForceUndimming(true);
   1098 
   1099   // Moving the mouse off the shelf should not dim the bar.
   1100   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
   1101   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1102 
   1103   // No matter what the touch events do, the shelf should stay undimmed.
   1104   generator.PressTouch();
   1105   generator.MoveTouch(off_shelf);
   1106   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1107   generator.MoveTouch(on_shelf);
   1108   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1109   generator.MoveTouch(off_shelf);
   1110   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1111   generator.ReleaseTouch();
   1112   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1113 
   1114   // "Closing the menu" should now turn off the menu since no event is inside
   1115   // the shelf any longer.
   1116   shelf->shelf_widget()->ForceUndimming(false);
   1117   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1118 
   1119   // Moving the mouse again on the shelf which should undim the bar again.
   1120   // This time we check that the bar stays undimmed when the mouse remains on
   1121   // the bar and the "menu gets closed".
   1122   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
   1123   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1124   shelf->shelf_widget()->ForceUndimming(true);
   1125   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
   1126   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1127   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
   1128   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1129   shelf->shelf_widget()->ForceUndimming(true);
   1130   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
   1131 }
   1132 
   1133 // Verifies the shelf is visible when status/launcher is focused.
   1134 TEST_F(ShelfLayoutManagerTest, VisibleWhenStatusOrLauncherFocused) {
   1135   // Since ShelfLayoutManager queries for mouse location, move the mouse so
   1136   // it isn't over the shelf.
   1137   aura::test::EventGenerator generator(
   1138       Shell::GetPrimaryRootWindow(), gfx::Point());
   1139   generator.MoveMouseTo(0, 0);
   1140 
   1141   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1142   views::Widget* widget = new views::Widget;
   1143   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   1144   params.bounds = gfx::Rect(0, 0, 200, 200);
   1145   params.context = CurrentContext();
   1146   // Widget is now owned by the parent window.
   1147   widget->Init(params);
   1148   widget->Show();
   1149   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1150   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1151   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1152 
   1153   // Focus the launcher. Have to go through the focus cycler as normal focus
   1154   // requests to it do nothing.
   1155   GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
   1156   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1157 
   1158   widget->Activate();
   1159   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1160 
   1161   // Trying to activate the status should fail, since we only allow activating
   1162   // it when the user is using the keyboard (i.e. through FocusCycler).
   1163   GetShelfWidget()->status_area_widget()->Activate();
   1164   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1165 
   1166   GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
   1167   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1168 }
   1169 
   1170 // Makes sure shelf will be visible when app list opens as shelf is in
   1171 // SHELF_VISIBLE state,and toggling app list won't change shelf
   1172 // visibility state.
   1173 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfVisibleState) {
   1174   Shell* shell = Shell::GetInstance();
   1175   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1176   shelf->LayoutShelf();
   1177   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1178 
   1179   // Create a normal unmaximized windowm shelf should be visible.
   1180   aura::Window* window = CreateTestWindow();
   1181   window->SetBounds(gfx::Rect(0, 0, 100, 100));
   1182   window->Show();
   1183   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1184   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
   1185 
   1186   // Toggle app list to show, and the shelf stays visible.
   1187   shell->ToggleAppList(NULL);
   1188   EXPECT_TRUE(shell->GetAppListTargetVisibility());
   1189   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
   1190 
   1191   // Toggle app list to hide, and the shelf stays visible.
   1192   shell->ToggleAppList(NULL);
   1193   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1194   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
   1195 }
   1196 
   1197 // Makes sure shelf will be shown with SHELF_AUTO_HIDE_SHOWN state
   1198 // when app list opens as shelf is in SHELF_AUTO_HIDE state, and
   1199 // toggling app list won't change shelf visibility state.
   1200 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
   1201   Shell* shell = Shell::GetInstance();
   1202   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1203   shelf->LayoutShelf();
   1204   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1205 
   1206   // Create a window and show it in maximized state.
   1207   aura::Window* window = CreateTestWindow();
   1208   window->SetBounds(gfx::Rect(0, 0, 100, 100));
   1209   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1210   window->Show();
   1211   wm::ActivateWindow(window);
   1212 
   1213   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1214   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1215 
   1216   // Toggle app list to show.
   1217   shell->ToggleAppList(NULL);
   1218   // The shelf's auto hide state won't be changed until the timer fires, so
   1219   // calling shell->UpdateShelfVisibility() is kind of manually helping it to
   1220   // update the state.
   1221   shell->UpdateShelfVisibility();
   1222   EXPECT_TRUE(shell->GetAppListTargetVisibility());
   1223   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1224   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1225 
   1226   // Toggle app list to hide.
   1227   shell->ToggleAppList(NULL);
   1228   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1229   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1230 }
   1231 
   1232 // Makes sure shelf will be hidden when app list opens as shelf is in HIDDEN
   1233 // state, and toggling app list won't change shelf visibility state.
   1234 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
   1235   Shell* shell = Shell::GetInstance();
   1236   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1237   // For shelf to be visible, app list is not open in initial state.
   1238   shelf->LayoutShelf();
   1239 
   1240   // Create a window and make it full screen.
   1241   aura::Window* window = CreateTestWindow();
   1242   window->SetBounds(gfx::Rect(0, 0, 100, 100));
   1243   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
   1244   window->Show();
   1245   wm::ActivateWindow(window);
   1246 
   1247   // App list and shelf is not shown.
   1248   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1249   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
   1250 
   1251   // Toggle app list to show.
   1252   shell->ToggleAppList(NULL);
   1253   EXPECT_TRUE(shell->GetAppListTargetVisibility());
   1254   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
   1255 
   1256   // Toggle app list to hide.
   1257   shell->ToggleAppList(NULL);
   1258   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   1259   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
   1260 }
   1261 
   1262 #if defined(OS_WIN)
   1263 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
   1264 #define MAYBE_SetAlignment DISABLED_SetAlignment
   1265 #else
   1266 #define MAYBE_SetAlignment SetAlignment
   1267 #endif
   1268 
   1269 // Tests SHELF_ALIGNMENT_(LEFT, RIGHT, TOP).
   1270 TEST_F(ShelfLayoutManagerTest, MAYBE_SetAlignment) {
   1271   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1272   // Force an initial layout.
   1273   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1274   shelf->LayoutShelf();
   1275   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
   1276 
   1277   shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
   1278   gfx::Rect launcher_bounds(
   1279       GetShelfWidget()->GetWindowBoundsInScreen());
   1280   const gfx::Screen* screen = Shell::GetScreen();
   1281   gfx::Display display =
   1282       screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1283   ASSERT_NE(-1, display.id());
   1284   EXPECT_EQ(shelf->GetIdealBounds().width(),
   1285             display.GetWorkAreaInsets().left());
   1286   EXPECT_GE(
   1287       launcher_bounds.width(),
   1288       GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
   1289   EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment());
   1290   StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
   1291   gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
   1292   EXPECT_GE(status_bounds.width(),
   1293             status_area_widget->GetContentsView()->GetPreferredSize().width());
   1294   EXPECT_EQ(shelf->GetIdealBounds().width(),
   1295             display.GetWorkAreaInsets().left());
   1296   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
   1297   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
   1298   EXPECT_EQ(0, display.GetWorkAreaInsets().right());
   1299   EXPECT_EQ(display.bounds().x(), launcher_bounds.x());
   1300   EXPECT_EQ(display.bounds().y(), launcher_bounds.y());
   1301   EXPECT_EQ(display.bounds().height(), launcher_bounds.height());
   1302   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1303   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1304   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
   1305       display.GetWorkAreaInsets().left());
   1306   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize, display.work_area().x());
   1307 
   1308   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1309   shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
   1310   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1311   launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
   1312   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1313   ASSERT_NE(-1, display.id());
   1314   EXPECT_EQ(shelf->GetIdealBounds().width(),
   1315             display.GetWorkAreaInsets().right());
   1316   EXPECT_GE(launcher_bounds.width(),
   1317       GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
   1318   EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, GetSystemTray()->shelf_alignment());
   1319   status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
   1320   EXPECT_GE(status_bounds.width(),
   1321             status_area_widget->GetContentsView()->GetPreferredSize().width());
   1322   EXPECT_EQ(shelf->GetIdealBounds().width(),
   1323             display.GetWorkAreaInsets().right());
   1324   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
   1325   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
   1326   EXPECT_EQ(0, display.GetWorkAreaInsets().left());
   1327   EXPECT_EQ(display.work_area().right(), launcher_bounds.x());
   1328   EXPECT_EQ(display.bounds().y(), launcher_bounds.y());
   1329   EXPECT_EQ(display.bounds().height(), launcher_bounds.height());
   1330   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1331   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1332   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
   1333       display.GetWorkAreaInsets().right());
   1334   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
   1335       display.bounds().right() - display.work_area().right());
   1336 
   1337   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1338   shelf->SetAlignment(SHELF_ALIGNMENT_TOP);
   1339   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1340   launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
   1341   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1342   ASSERT_NE(-1, display.id());
   1343   EXPECT_EQ(shelf->GetIdealBounds().height(),
   1344             display.GetWorkAreaInsets().top());
   1345   EXPECT_GE(launcher_bounds.height(),
   1346       GetShelfWidget()->GetContentsView()->GetPreferredSize().height());
   1347   EXPECT_EQ(SHELF_ALIGNMENT_TOP, GetSystemTray()->shelf_alignment());
   1348   status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
   1349   EXPECT_GE(status_bounds.height(),
   1350             status_area_widget->GetContentsView()->GetPreferredSize().height());
   1351   EXPECT_EQ(shelf->GetIdealBounds().height(),
   1352             display.GetWorkAreaInsets().top());
   1353   EXPECT_EQ(0, display.GetWorkAreaInsets().right());
   1354   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
   1355   EXPECT_EQ(0, display.GetWorkAreaInsets().left());
   1356   EXPECT_EQ(display.work_area().y(), launcher_bounds.bottom());
   1357   EXPECT_EQ(display.bounds().x(), launcher_bounds.x());
   1358   EXPECT_EQ(display.bounds().width(), launcher_bounds.width());
   1359   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1360   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
   1361   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
   1362       display.GetWorkAreaInsets().top());
   1363   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
   1364             display.work_area().y() - display.bounds().y());
   1365 }
   1366 
   1367 #if defined(OS_WIN)
   1368 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
   1369 #define MAYBE_GestureDrag DISABLED_GestureDrag
   1370 #else
   1371 #define MAYBE_GestureDrag GestureDrag
   1372 #endif
   1373 
   1374 TEST_F(ShelfLayoutManagerTest, MAYBE_GestureDrag) {
   1375   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1376   {
   1377     SCOPED_TRACE("BOTTOM");
   1378     RunGestureDragTests(gfx::Vector2d(0, 100));
   1379   }
   1380 
   1381   {
   1382     SCOPED_TRACE("LEFT");
   1383     shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
   1384     RunGestureDragTests(gfx::Vector2d(-100, 0));
   1385   }
   1386 
   1387   {
   1388     SCOPED_TRACE("RIGHT");
   1389     shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
   1390     RunGestureDragTests(gfx::Vector2d(100, 0));
   1391   }
   1392 }
   1393 
   1394 TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) {
   1395   if (!SupportsMultipleDisplays())
   1396     return;
   1397 
   1398   UpdateDisplay("800x600,800x600");
   1399   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1400   shelf->LayoutShelf();
   1401   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1402 
   1403   // Create a visible window so auto-hide behavior is enforced
   1404   views::Widget* dummy = CreateTestWidget();
   1405 
   1406   // Window visible => auto hide behaves normally.
   1407   shelf->UpdateVisibilityState();
   1408   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1409 
   1410   // Window minimized => auto hide disabled.
   1411   dummy->Minimize();
   1412   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1413 
   1414   // Window closed => auto hide disabled.
   1415   dummy->CloseNow();
   1416   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1417 
   1418   // Multiple window test
   1419   views::Widget* window1 = CreateTestWidget();
   1420   views::Widget* window2 = CreateTestWidget();
   1421 
   1422   // both visible => normal autohide
   1423   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1424 
   1425   // either minimzed => normal autohide
   1426   window2->Minimize();
   1427   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1428   window2->Restore();
   1429   window1->Minimize();
   1430   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1431 
   1432   // both minimzed => disable auto hide
   1433   window2->Minimize();
   1434   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1435 
   1436   // Test moving windows to/from other display.
   1437   window2->Restore();
   1438   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1439   // Move to second display.
   1440   window2->SetBounds(gfx::Rect(850, 50, 50, 50));
   1441   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1442   // Move back to primary display.
   1443   window2->SetBounds(gfx::Rect(50, 50, 50, 50));
   1444   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1445 }
   1446 
   1447 #if defined(OS_WIN)
   1448 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
   1449 #define MAYBE_GestureRevealsTrayBubble DISABLED_GestureRevealsTrayBubble
   1450 #else
   1451 #define MAYBE_GestureRevealsTrayBubble GestureRevealsTrayBubble
   1452 #endif
   1453 
   1454 TEST_F(ShelfLayoutManagerTest, MAYBE_GestureRevealsTrayBubble) {
   1455   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1456   shelf->LayoutShelf();
   1457 
   1458   // Create a visible window so auto-hide behavior is enforced.
   1459   CreateTestWidget();
   1460 
   1461   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   1462   SystemTray* tray = GetSystemTray();
   1463 
   1464   // First, make sure the shelf is visible.
   1465   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1466   EXPECT_FALSE(tray->HasSystemBubble());
   1467 
   1468   // Now, drag up on the tray to show the bubble.
   1469   gfx::Point start = GetShelfWidget()->status_area_widget()->
   1470       GetWindowBoundsInScreen().CenterPoint();
   1471   gfx::Point end(start.x(), start.y() - 100);
   1472   generator.GestureScrollSequence(start, end,
   1473       base::TimeDelta::FromMilliseconds(10), 1);
   1474   EXPECT_TRUE(tray->HasSystemBubble());
   1475   tray->CloseSystemBubble();
   1476   RunAllPendingInMessageLoop();
   1477   EXPECT_FALSE(tray->HasSystemBubble());
   1478 
   1479   // Drag again, but only a small amount, and slowly. The bubble should not be
   1480   // visible.
   1481   end.set_y(start.y() - 30);
   1482   generator.GestureScrollSequence(start, end,
   1483       base::TimeDelta::FromMilliseconds(500), 100);
   1484   EXPECT_FALSE(tray->HasSystemBubble());
   1485 
   1486   // Now, hide the shelf.
   1487   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1488 
   1489   // Start a drag from the bezel, and drag up to show both the shelf and the
   1490   // tray bubble.
   1491   start.set_y(start.y() + 100);
   1492   end.set_y(start.y() - 400);
   1493   generator.GestureScrollSequence(start, end,
   1494       base::TimeDelta::FromMilliseconds(10), 1);
   1495   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
   1496   EXPECT_TRUE(tray->HasSystemBubble());
   1497 }
   1498 
   1499 TEST_F(ShelfLayoutManagerTest, ShelfFlickerOnTrayActivation) {
   1500   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1501 
   1502   // Create a visible window so auto-hide behavior is enforced.
   1503   CreateTestWidget();
   1504 
   1505   // Turn on auto-hide for the shelf.
   1506   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1507   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1508   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
   1509 
   1510   // Show the status menu. That should make the shelf visible again.
   1511   Shell::GetInstance()->accelerator_controller()->PerformAction(
   1512       SHOW_SYSTEM_TRAY_BUBBLE, ui::Accelerator());
   1513   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1514   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1515   EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
   1516 
   1517   // Now activate the tray (using the keyboard, instead of using the mouse to
   1518   // make sure the mouse does not alter the auto-hide state in the shelf).
   1519   // This should not trigger any auto-hide state change in the shelf.
   1520   ShelfLayoutObserverTest observer;
   1521   shelf->AddObserver(&observer);
   1522 
   1523   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   1524   generator.PressKey(ui::VKEY_SPACE, 0);
   1525   generator.ReleaseKey(ui::VKEY_SPACE, 0);
   1526   EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
   1527   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   1528   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   1529   EXPECT_FALSE(observer.changed_auto_hide_state());
   1530 
   1531   shelf->RemoveObserver(&observer);
   1532 }
   1533 
   1534 TEST_F(ShelfLayoutManagerTest, WorkAreaChangeWorkspace) {
   1535   // Make sure the shelf is always visible.
   1536   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1537   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1538   shelf->LayoutShelf();
   1539 
   1540   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   1541   params.bounds = gfx::Rect(0, 0, 200, 200);
   1542   params.context = CurrentContext();
   1543   views::Widget* widget_one = CreateTestWidgetWithParams(params);
   1544   widget_one->Maximize();
   1545 
   1546   views::Widget* widget_two = CreateTestWidgetWithParams(params);
   1547   widget_two->Maximize();
   1548   widget_two->Activate();
   1549 
   1550   // Both windows are maximized. They should be of the same size.
   1551   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
   1552             widget_two->GetNativeWindow()->bounds().ToString());
   1553   int area_when_shelf_shown =
   1554       widget_one->GetNativeWindow()->bounds().size().GetArea();
   1555 
   1556   // Now hide the shelf.
   1557   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1558 
   1559   // Both windows should be resized according to the shelf status.
   1560   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
   1561             widget_two->GetNativeWindow()->bounds().ToString());
   1562   // Resized to small.
   1563   EXPECT_LT(area_when_shelf_shown,
   1564             widget_one->GetNativeWindow()->bounds().size().GetArea());
   1565 
   1566   // Now show the shelf.
   1567   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1568 
   1569   // Again both windows should be of the same size.
   1570   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
   1571             widget_two->GetNativeWindow()->bounds().ToString());
   1572   EXPECT_EQ(area_when_shelf_shown,
   1573             widget_one->GetNativeWindow()->bounds().size().GetArea());
   1574 }
   1575 
   1576 // Confirm that the shelf is dimmed only when content is maximized and
   1577 // shelf is not autohidden.
   1578 TEST_F(ShelfLayoutManagerTest, Dimming) {
   1579   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1580   scoped_ptr<aura::Window> w1(CreateTestWindow());
   1581   w1->Show();
   1582   wm::ActivateWindow(w1.get());
   1583 
   1584   // Normal window doesn't dim shelf.
   1585   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
   1586   ShelfWidget* shelf = GetShelfWidget();
   1587   EXPECT_FALSE(shelf->GetDimsShelf());
   1588 
   1589   // Maximized window does.
   1590   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1591   EXPECT_TRUE(shelf->GetDimsShelf());
   1592 
   1593   // Change back to normal stops dimming.
   1594   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
   1595   EXPECT_FALSE(shelf->GetDimsShelf());
   1596 
   1597   // Changing back to maximized dims again.
   1598   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1599   EXPECT_TRUE(shelf->GetDimsShelf());
   1600 
   1601   // Changing shelf to autohide stops dimming.
   1602   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1603   EXPECT_FALSE(shelf->GetDimsShelf());
   1604 }
   1605 
   1606 // Make sure that the shelf will not hide if the mouse is between a bubble and
   1607 // the shelf.
   1608 TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) {
   1609   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   1610   StatusAreaWidget* status_area_widget =
   1611       Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
   1612   SystemTray* tray = GetSystemTray();
   1613 
   1614   // Create a visible window so auto-hide behavior is enforced.
   1615   CreateTestWidget();
   1616 
   1617   shelf->LayoutShelf();
   1618   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   1619 
   1620   // Make two iterations - first without a message bubble which should make
   1621   // the shelf disappear and then with a message bubble which should keep it
   1622   // visible.
   1623   for (int i = 0; i < 2; i++) {
   1624     // Make sure the shelf is visible and position the mouse over it. Then
   1625     // allow auto hide.
   1626     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1627     EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
   1628     gfx::Point center =
   1629         status_area_widget->GetWindowBoundsInScreen().CenterPoint();
   1630     generator.MoveMouseTo(center.x(), center.y());
   1631     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1632     EXPECT_TRUE(shelf->IsVisible());
   1633     if (!i) {
   1634       // In our first iteration we make sure there is no bubble.
   1635       tray->CloseSystemBubble();
   1636       EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
   1637     } else {
   1638       // In our second iteration we show a bubble.
   1639       TestItem *item = new TestItem;
   1640       tray->AddTrayItem(item);
   1641       tray->ShowNotificationView(item);
   1642       EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
   1643     }
   1644     // Move the pointer over the edge of the shelf.
   1645     generator.MoveMouseTo(
   1646         center.x(), status_area_widget->GetWindowBoundsInScreen().y() - 8);
   1647     shelf->UpdateVisibilityState();
   1648     if (i) {
   1649       EXPECT_TRUE(shelf->IsVisible());
   1650       EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
   1651     } else {
   1652       EXPECT_FALSE(shelf->IsVisible());
   1653       EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
   1654     }
   1655   }
   1656 }
   1657 
   1658 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColor) {
   1659   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
   1660 
   1661   scoped_ptr<aura::Window> w1(CreateTestWindow());
   1662   w1->Show();
   1663   wm::ActivateWindow(w1.get());
   1664   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
   1665   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1666   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
   1667 
   1668   scoped_ptr<aura::Window> w2(CreateTestWindow());
   1669   w2->Show();
   1670   wm::ActivateWindow(w2.get());
   1671   // Overlaps with shelf.
   1672   w2->SetBounds(GetShelfLayoutManager()->GetIdealBounds());
   1673 
   1674   // Still background is 'maximized'.
   1675   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
   1676 
   1677   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
   1678   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
   1679   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
   1680   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
   1681 
   1682   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1683   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
   1684   w1.reset();
   1685   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
   1686 }
   1687 
   1688 // Verify that the shelf doesn't have the opaque background if it's auto-hide
   1689 // status.
   1690 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColorAutoHide) {
   1691   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget ()->GetBackgroundType());
   1692 
   1693   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1694   scoped_ptr<aura::Window> w1(CreateTestWindow());
   1695   w1->Show();
   1696   wm::ActivateWindow(w1.get());
   1697   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
   1698   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   1699   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
   1700 }
   1701 
   1702 }  // namespace internal
   1703 }  // namespace ash
   1704