summaryrefslogtreecommitdiff
path: root/chromium/ash/shelf/shelf_layout_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/shelf/shelf_layout_manager_unittest.cc')
-rw-r--r--chromium/ash/shelf/shelf_layout_manager_unittest.cc1833
1 files changed, 1833 insertions, 0 deletions
diff --git a/chromium/ash/shelf/shelf_layout_manager_unittest.cc b/chromium/ash/shelf/shelf_layout_manager_unittest.cc
new file mode 100644
index 00000000000..e44fe347a68
--- /dev/null
+++ b/chromium/ash/shelf/shelf_layout_manager_unittest.cc
@@ -0,0 +1,1833 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/shelf/shelf_layout_manager.h"
+
+#include "ash/accelerators/accelerator_controller.h"
+#include "ash/accelerators/accelerator_table.h"
+#include "ash/ash_switches.h"
+#include "ash/display/display_controller.h"
+#include "ash/display/display_manager.h"
+#include "ash/focus_cycler.h"
+#include "ash/launcher/launcher.h"
+#include "ash/launcher/launcher_view.h"
+#include "ash/root_window_controller.h"
+#include "ash/screen_ash.h"
+#include "ash/session_state_delegate.h"
+#include "ash/shelf/shelf_layout_manager_observer.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/system/status_area_widget.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_item.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/wm/window_properties.h"
+#include "ash/wm/window_util.h"
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/base/animation/animation_container_element.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+namespace ash {
+namespace internal {
+
+namespace {
+
+void StepWidgetLayerAnimatorToEnd(views::Widget* widget) {
+ ui::AnimationContainerElement* element =
+ static_cast<ui::AnimationContainerElement*>(
+ widget->GetNativeView()->layer()->GetAnimator());
+ element->Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
+}
+
+ShelfWidget* GetShelfWidget() {
+ return Shell::GetPrimaryRootWindowController()->shelf();
+}
+
+ShelfLayoutManager* GetShelfLayoutManager() {
+ return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
+}
+
+SystemTray* GetSystemTray() {
+ return Shell::GetPrimaryRootWindowController()->GetSystemTray();
+}
+
+// Class which waits till the shelf finishes animating to the target size and
+// counts the number of animation steps.
+class ShelfAnimationWaiter : views::WidgetObserver {
+ public:
+ explicit ShelfAnimationWaiter(const gfx::Rect& target_bounds)
+ : target_bounds_(target_bounds),
+ animation_steps_(0),
+ done_waiting_(false) {
+ GetShelfWidget()->AddObserver(this);
+ }
+
+ virtual ~ShelfAnimationWaiter() {
+ GetShelfWidget()->RemoveObserver(this);
+ }
+
+ // Wait till the shelf finishes animating to its expected bounds.
+ void WaitTillDoneAnimating() {
+ if (IsDoneAnimating())
+ done_waiting_ = true;
+ else
+ base::MessageLoop::current()->Run();
+ }
+
+ // Returns true if the animation has completed and it was valid.
+ bool WasValidAnimation() const {
+ return done_waiting_ && animation_steps_ > 0;
+ }
+
+ private:
+ // Returns true if shelf has finished animating to the target size.
+ bool IsDoneAnimating() const {
+ ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
+ gfx::Rect current_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+ int size = layout_manager->PrimaryAxisValue(current_bounds.height(),
+ current_bounds.width());
+ int desired_size = layout_manager->PrimaryAxisValue(target_bounds_.height(),
+ target_bounds_.width());
+ return (size == desired_size);
+ }
+
+ // views::WidgetObserver override.
+ virtual void OnWidgetBoundsChanged(views::Widget* widget,
+ const gfx::Rect& new_bounds) OVERRIDE {
+ if (done_waiting_)
+ return;
+
+ ++animation_steps_;
+ if (IsDoneAnimating()) {
+ done_waiting_ = true;
+ base::MessageLoop::current()->Quit();
+ }
+ }
+
+ gfx::Rect target_bounds_;
+ int animation_steps_;
+ bool done_waiting_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShelfAnimationWaiter);
+};
+
+class ShelfDragCallback {
+ public:
+ ShelfDragCallback(const gfx::Rect& not_visible, const gfx::Rect& visible)
+ : not_visible_bounds_(not_visible),
+ visible_bounds_(visible),
+ was_visible_on_drag_start_(false) {
+ EXPECT_EQ(not_visible_bounds_.bottom(), visible_bounds_.bottom());
+ }
+
+ virtual ~ShelfDragCallback() {
+ }
+
+ void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
+ if (GetShelfLayoutManager()->visibility_state() == ash::SHELF_HIDDEN)
+ return;
+
+ if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
+ scroll_ = gfx::Vector2dF();
+ was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
+ return;
+ }
+
+ // The state of the shelf at the end of the gesture is tested separately.
+ if (type == ui::ET_GESTURE_SCROLL_END)
+ return;
+
+ if (type == ui::ET_GESTURE_SCROLL_UPDATE)
+ scroll_.Add(delta);
+
+ gfx::Rect shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+ if (GetShelfLayoutManager()->IsHorizontalAlignment()) {
+ EXPECT_EQ(not_visible_bounds_.bottom(), shelf_bounds.bottom());
+ EXPECT_EQ(visible_bounds_.bottom(), shelf_bounds.bottom());
+ } else if (SHELF_ALIGNMENT_RIGHT ==
+ GetShelfLayoutManager()->GetAlignment()){
+ EXPECT_EQ(not_visible_bounds_.right(), shelf_bounds.right());
+ EXPECT_EQ(visible_bounds_.right(), shelf_bounds.right());
+ } else if (SHELF_ALIGNMENT_LEFT ==
+ GetShelfLayoutManager()->GetAlignment()) {
+ EXPECT_EQ(not_visible_bounds_.x(), shelf_bounds.x());
+ EXPECT_EQ(visible_bounds_.x(), shelf_bounds.x());
+ }
+
+ // if the shelf is being dimmed test dimmer bounds as well.
+ if (GetShelfWidget()->GetDimsShelf())
+ EXPECT_EQ(GetShelfWidget()->GetWindowBoundsInScreen(),
+ GetShelfWidget()->GetDimmerBoundsForTest());
+
+ // The shelf should never be smaller than the hidden state.
+ EXPECT_GE(shelf_bounds.height(), not_visible_bounds_.height());
+ float scroll_delta = GetShelfLayoutManager()->PrimaryAxisValue(
+ scroll_.y(),
+ scroll_.x());
+ bool increasing_drag =
+ GetShelfLayoutManager()->SelectValueForShelfAlignment(
+ scroll_delta < 0,
+ scroll_delta > 0,
+ scroll_delta < 0,
+ scroll_delta > 0);
+ int shelf_size = GetShelfLayoutManager()->PrimaryAxisValue(
+ shelf_bounds.height(),
+ shelf_bounds.width());
+ int visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
+ visible_bounds_.height(),
+ visible_bounds_.width());
+ int not_visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
+ not_visible_bounds_.height(),
+ not_visible_bounds_.width());
+ if (was_visible_on_drag_start_) {
+ if (increasing_drag) {
+ // If dragging inwards from the visible state, then the shelf should
+ // increase in size, but not more than the scroll delta.
+ EXPECT_LE(visible_bounds_size, shelf_size);
+ EXPECT_LE(abs(shelf_size - visible_bounds_size),
+ abs(scroll_delta));
+ } else {
+ if (shelf_size > not_visible_bounds_size) {
+ // If dragging outwards from the visible state, then the shelf
+ // should decrease in size, until it reaches the minimum size.
+ EXPECT_EQ(shelf_size, visible_bounds_size - abs(scroll_delta));
+ }
+ }
+ } else {
+ if (fabs(scroll_delta) <
+ visible_bounds_size - not_visible_bounds_size) {
+ // Tests that the shelf sticks with the touch point during the drag
+ // until the shelf is completely visible.
+ EXPECT_EQ(shelf_size, not_visible_bounds_size + abs(scroll_delta));
+ } else {
+ // Tests that after the shelf is completely visible, the shelf starts
+ // resisting the drag.
+ EXPECT_LT(shelf_size, not_visible_bounds_size + abs(scroll_delta));
+ }
+ }
+ }
+
+ private:
+ const gfx::Rect not_visible_bounds_;
+ const gfx::Rect visible_bounds_;
+ gfx::Vector2dF scroll_;
+ bool was_visible_on_drag_start_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback);
+};
+
+class ShelfLayoutObserverTest : public ShelfLayoutManagerObserver {
+ public:
+ ShelfLayoutObserverTest()
+ : changed_auto_hide_state_(false) {
+ }
+
+ virtual ~ShelfLayoutObserverTest() {}
+
+ bool changed_auto_hide_state() const { return changed_auto_hide_state_; }
+
+ private:
+ virtual void OnAutoHideStateChanged(
+ ShelfAutoHideState new_state) OVERRIDE {
+ changed_auto_hide_state_ = true;
+ }
+
+ bool changed_auto_hide_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest);
+};
+
+// Trivial item implementation that tracks its views for testing.
+class TestItem : public SystemTrayItem {
+ public:
+ TestItem()
+ : SystemTrayItem(GetSystemTray()),
+ tray_view_(NULL),
+ default_view_(NULL),
+ detailed_view_(NULL),
+ notification_view_(NULL) {}
+
+ virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE {
+ tray_view_ = new views::View;
+ // Add a label so it has non-zero width.
+ tray_view_->SetLayoutManager(new views::FillLayout);
+ tray_view_->AddChildView(new views::Label(UTF8ToUTF16("Tray")));
+ return tray_view_;
+ }
+
+ virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
+ default_view_ = new views::View;
+ default_view_->SetLayoutManager(new views::FillLayout);
+ default_view_->AddChildView(new views::Label(UTF8ToUTF16("Default")));
+ return default_view_;
+ }
+
+ virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE {
+ detailed_view_ = new views::View;
+ detailed_view_->SetLayoutManager(new views::FillLayout);
+ detailed_view_->AddChildView(new views::Label(UTF8ToUTF16("Detailed")));
+ return detailed_view_;
+ }
+
+ virtual views::View* CreateNotificationView(
+ user::LoginStatus status) OVERRIDE {
+ notification_view_ = new views::View;
+ return notification_view_;
+ }
+
+ virtual void DestroyTrayView() OVERRIDE {
+ tray_view_ = NULL;
+ }
+
+ virtual void DestroyDefaultView() OVERRIDE {
+ default_view_ = NULL;
+ }
+
+ virtual void DestroyDetailedView() OVERRIDE {
+ detailed_view_ = NULL;
+ }
+
+ virtual void DestroyNotificationView() OVERRIDE {
+ notification_view_ = NULL;
+ }
+
+ virtual void UpdateAfterLoginStatusChange(
+ user::LoginStatus status) OVERRIDE {}
+
+ views::View* tray_view() const { return tray_view_; }
+ views::View* default_view() const { return default_view_; }
+ views::View* detailed_view() const { return detailed_view_; }
+ views::View* notification_view() const { return notification_view_; }
+
+ private:
+ views::View* tray_view_;
+ views::View* default_view_;
+ views::View* detailed_view_;
+ views::View* notification_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestItem);
+};
+
+} // namespace
+
+class ShelfLayoutManagerTest : public ash::test::AshTestBase {
+ public:
+ ShelfLayoutManagerTest() {}
+
+ void SetState(ShelfLayoutManager* shelf,
+ ShelfVisibilityState state) {
+ shelf->SetState(state);
+ }
+
+ void UpdateAutoHideStateNow() {
+ GetShelfLayoutManager()->UpdateAutoHideStateNow();
+ }
+
+ aura::Window* CreateTestWindow() {
+ aura::Window* window = new aura::Window(NULL);
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ window->SetType(aura::client::WINDOW_TYPE_NORMAL);
+ window->Init(ui::LAYER_TEXTURED);
+ SetDefaultParentByPrimaryRootWindow(window);
+ return window;
+ }
+
+ views::Widget* CreateTestWidgetWithParams(
+ const views::Widget::InitParams& params) {
+ views::Widget* out = new views::Widget;
+ out->Init(params);
+ out->Show();
+ return out;
+ }
+
+ // Create a simple widget attached to the current context (will
+ // delete on TearDown).
+ views::Widget* CreateTestWidget() {
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ return CreateTestWidgetWithParams(params);
+ }
+
+ // Overridden from AshTestBase:
+ virtual void SetUp() OVERRIDE {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ ash::switches::kAshEnableTrayDragging);
+ test::AshTestBase::SetUp();
+ }
+
+ void RunGestureDragTests(gfx::Vector2d);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
+};
+
+void ShelfLayoutManagerTest::RunGestureDragTests(gfx::Vector2d delta) {
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ widget->Init(params);
+ widget->Show();
+ widget->Maximize();
+
+ aura::Window* window = widget->GetNativeWindow();
+ shelf->LayoutShelf();
+
+ gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
+ gfx::Rect bounds_shelf = window->bounds();
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ shelf->LayoutShelf();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ gfx::Rect bounds_noshelf = window->bounds();
+ gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ shelf->LayoutShelf();
+
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+ const int kNumScrollSteps = 10;
+ ShelfDragCallback handler(shelf_hidden, shelf_shown);
+
+ // Swipe up on the shelf. This should not change any state.
+ gfx::Point start = GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
+ gfx::Point end = start + delta;
+
+ // Swipe down on the shelf to hide it.
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_NE(bounds_shelf.ToString(), window->bounds().ToString());
+ EXPECT_NE(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up to show the shelf.
+ generator.GestureScrollSequenceWithCallback(end, start,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+ EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
+ GetShelfWidget()->GetWindowBoundsInScreen());
+ EXPECT_EQ(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up again. The shelf should hide.
+ end = start - delta;
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up yet again to show it.
+ end = start + delta;
+ generator.GestureScrollSequenceWithCallback(end, start,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+
+ // Swipe down very little. It shouldn't change any state.
+ if (GetShelfLayoutManager()->IsHorizontalAlignment())
+ end.set_y(start.y() + shelf_shown.height() * 3 / 10);
+ else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
+ end.set_x(start.x() - shelf_shown.width() * 3 / 10);
+ else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
+ end.set_x(start.x() + shelf_shown.width() * 3 / 10);
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(100), 1,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+ EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe down again to hide.
+ end = start + delta;
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
+ EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up in extended hit region to show it.
+ gfx::Point extended_start = start;
+ if (GetShelfLayoutManager()->IsHorizontalAlignment())
+ extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() -1);
+ else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
+ extended_start.set_x(
+ GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
+ else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
+ extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
+ end = extended_start - delta;
+ generator.GestureScrollSequenceWithCallback(extended_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+ EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
+ GetShelfWidget()->GetWindowBoundsInScreen());
+ EXPECT_EQ(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe down again to hide.
+ end = start + delta;
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
+ EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up outside the hit area. This should not change anything.
+ gfx::Point outside_start = gfx::Point(
+ (GetShelfWidget()->GetWindowBoundsInScreen().x() +
+ GetShelfWidget()->GetWindowBoundsInScreen().right())/2,
+ GetShelfWidget()->GetWindowBoundsInScreen().y() - 50);
+ end = outside_start + delta;
+ generator.GestureScrollSequence(outside_start,
+ end,
+ base::TimeDelta::FromMilliseconds(10),
+ kNumScrollSteps);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe up from below the shelf where a bezel would be, this should show the
+ // shelf.
+ gfx::Point below_start = start;
+ if (GetShelfLayoutManager()->IsHorizontalAlignment())
+ below_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().bottom() + 1);
+ else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
+ below_start.set_x(
+ GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
+ else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
+ below_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
+ end = below_start - delta;
+ generator.GestureScrollSequence(below_start,
+ end,
+ base::TimeDelta::FromMilliseconds(10),
+ kNumScrollSteps);
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+ EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
+ GetShelfWidget()->GetWindowBoundsInScreen());
+ EXPECT_EQ(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Swipe down again to hide.
+ end = start + delta;
+ generator.GestureScrollSequenceWithCallback(start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
+ EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+
+ // Enter into fullscreen with minimal chrome (immersive fullscreen).
+ widget->SetFullscreen(true);
+ window->SetProperty(ash::internal::kFullscreenUsesMinimalChromeKey, true);
+ shelf->UpdateVisibilityState();
+
+ gfx::Rect bounds_fullscreen = window->bounds();
+ EXPECT_TRUE(widget->IsFullscreen());
+ EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
+
+ // Swipe up. This should show the shelf.
+ end = below_start - delta;
+ generator.GestureScrollSequenceWithCallback(below_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+ EXPECT_EQ(shelf_shown.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+ EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
+
+ // Swipe up again. This should hide the shelf.
+ generator.GestureScrollSequenceWithCallback(below_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(shelf_hidden.ToString(),
+ GetShelfWidget()->GetWindowBoundsInScreen().ToString());
+ EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
+
+ // Put the window into fullscreen without any chrome at all (eg tab
+ // fullscreen).
+ window->SetProperty(ash::internal::kFullscreenUsesMinimalChromeKey, false);
+ shelf->UpdateVisibilityState();
+ EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+ // Swipe-up. This should not change anything.
+ end = start - delta;
+ generator.GestureScrollSequenceWithCallback(below_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+ EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
+
+ // Close actually, otherwise further event may be affected since widget
+ // is fullscreen status.
+ widget->Close();
+ RunAllPendingInMessageLoop();
+
+ // The shelf should be shown because there are no more visible windows.
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+ // Swipe-up to hide. This should have no effect because there are no visible
+ // windows.
+ end = below_start - delta;
+ generator.GestureScrollSequenceWithCallback(below_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+}
+
+// Fails on Mac only. Need to be implemented. http://crbug.com/111279.
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#define MAYBE_SetVisible DISABLED_SetVisible
+#else
+#define MAYBE_SetVisible SetVisible
+#endif
+// Makes sure SetVisible updates work area and widget appropriately.
+TEST_F(ShelfLayoutManagerTest, MAYBE_SetVisible) {
+ ShelfWidget* shelf = GetShelfWidget();
+ ShelfLayoutManager* manager = shelf->shelf_layout_manager();
+ // Force an initial layout.
+ manager->LayoutShelf();
+ EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
+
+ gfx::Rect status_bounds(
+ shelf->status_area_widget()->GetWindowBoundsInScreen());
+ gfx::Rect launcher_bounds(
+ shelf->GetWindowBoundsInScreen());
+ int shelf_height = manager->GetIdealBounds().height();
+ gfx::Screen* screen = Shell::GetScreen();
+ gfx::Display display = screen->GetDisplayNearestWindow(
+ Shell::GetPrimaryRootWindow());
+ ASSERT_NE(-1, display.id());
+ // Bottom inset should be the max of widget heights.
+ EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
+
+ // Hide the shelf.
+ SetState(manager, SHELF_HIDDEN);
+ // Run the animation to completion.
+ StepWidgetLayerAnimatorToEnd(shelf);
+ StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
+ EXPECT_EQ(SHELF_HIDDEN, manager->visibility_state());
+ display = screen->GetDisplayNearestWindow(
+ Shell::GetPrimaryRootWindow());
+
+ EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
+
+ // Make sure the bounds of the two widgets changed.
+ EXPECT_GE(shelf->GetNativeView()->bounds().y(),
+ screen->GetPrimaryDisplay().bounds().bottom());
+ EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
+ screen->GetPrimaryDisplay().bounds().bottom());
+
+ // And show it again.
+ SetState(manager, SHELF_VISIBLE);
+ // Run the animation to completion.
+ StepWidgetLayerAnimatorToEnd(shelf);
+ StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
+ EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
+ display = screen->GetDisplayNearestWindow(
+ Shell::GetPrimaryRootWindow());
+ EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
+
+ // Make sure the bounds of the two widgets changed.
+ launcher_bounds = shelf->GetNativeView()->bounds();
+ int bottom =
+ screen->GetPrimaryDisplay().bounds().bottom() - shelf_height;
+ EXPECT_EQ(launcher_bounds.y(),
+ bottom + (manager->GetIdealBounds().height() -
+ launcher_bounds.height()) / 2);
+ status_bounds = shelf->status_area_widget()->GetNativeView()->bounds();
+ EXPECT_EQ(status_bounds.y(),
+ bottom + shelf_height - status_bounds.height());
+}
+
+// Makes sure LayoutShelf invoked while animating cleans things up.
+TEST_F(ShelfLayoutManagerTest, LayoutShelfWhileAnimating) {
+ ShelfWidget* shelf = GetShelfWidget();
+ // Force an initial layout.
+ shelf->shelf_layout_manager()->LayoutShelf();
+ EXPECT_EQ(SHELF_VISIBLE, shelf->shelf_layout_manager()->visibility_state());
+
+ // Hide the shelf.
+ SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
+ shelf->shelf_layout_manager()->LayoutShelf();
+ EXPECT_EQ(SHELF_HIDDEN, shelf->shelf_layout_manager()->visibility_state());
+ gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
+ Shell::GetPrimaryRootWindow());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
+
+ // Make sure the bounds of the two widgets changed.
+ EXPECT_GE(shelf->GetNativeView()->bounds().y(),
+ Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
+ EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
+ Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
+}
+
+// Test that switching to a different visibility state does not restart the
+// shelf show / hide animation if it is already running. (crbug.com/250918)
+TEST_F(ShelfLayoutManagerTest, SetStateWhileAnimating) {
+ ShelfWidget* shelf = GetShelfWidget();
+ SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
+ gfx::Rect initial_shelf_bounds = shelf->GetWindowBoundsInScreen();
+ gfx::Rect initial_status_bounds =
+ shelf->status_area_widget()->GetWindowBoundsInScreen();
+
+ ui::ScopedAnimationDurationScaleMode normal_animation_duration(
+ ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
+ SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
+ SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
+
+ gfx::Rect current_shelf_bounds = shelf->GetWindowBoundsInScreen();
+ gfx::Rect current_status_bounds =
+ shelf->status_area_widget()->GetWindowBoundsInScreen();
+
+ const int small_change = initial_shelf_bounds.height() / 2;
+ EXPECT_LE(
+ std::abs(initial_shelf_bounds.height() - current_shelf_bounds.height()),
+ small_change);
+ EXPECT_LE(
+ std::abs(initial_status_bounds.height() - current_status_bounds.height()),
+ small_change);
+}
+
+// Makes sure the launcher is sized when the status area changes size.
+TEST_F(ShelfLayoutManagerTest, LauncherUpdatedWhenStatusAreaChangesSize) {
+ Launcher* launcher = Launcher::ForPrimaryDisplay();
+ ASSERT_TRUE(launcher);
+ ShelfWidget* shelf_widget = GetShelfWidget();
+ ASSERT_TRUE(shelf_widget);
+ ASSERT_TRUE(shelf_widget->status_area_widget());
+ shelf_widget->status_area_widget()->SetBounds(
+ gfx::Rect(0, 0, 200, 200));
+ EXPECT_EQ(200, shelf_widget->GetContentsView()->width() -
+ launcher->GetLauncherViewForTest()->width());
+}
+
+
+#if defined(OS_WIN)
+// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
+#define MAYBE_AutoHide DISABLED_AutoHide
+#else
+#define MAYBE_AutoHide AutoHide
+#endif
+
+// Various assertions around auto-hide.
+TEST_F(ShelfLayoutManagerTest, MAYBE_AutoHide) {
+ aura::RootWindow* root = Shell::GetPrimaryRootWindow();
+ aura::test::EventGenerator generator(root, root);
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Maximize();
+ widget->Show();
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // LayoutShelf() forces the animation to completion, at which point the
+ // launcher should go off the screen.
+ shelf->LayoutShelf();
+ EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
+ GetShelfWidget()->GetWindowBoundsInScreen().y());
+ EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
+ Shell::GetScreen()->GetDisplayNearestWindow(
+ root).work_area().bottom());
+
+ // Move the mouse to the bottom of the screen.
+ generator.MoveMouseTo(0, root->bounds().bottom() - 1);
+
+ // Shelf should be shown again (but it shouldn't have changed the work area).
+ SetState(shelf, SHELF_AUTO_HIDE);
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ shelf->LayoutShelf();
+ EXPECT_EQ(root->bounds().bottom() - shelf->GetIdealBounds().height(),
+ GetShelfWidget()->GetWindowBoundsInScreen().y());
+ EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
+ Shell::GetScreen()->GetDisplayNearestWindow(
+ root).work_area().bottom());
+
+ // Move mouse back up.
+ generator.MoveMouseTo(0, 0);
+ SetState(shelf, SHELF_AUTO_HIDE);
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ shelf->LayoutShelf();
+ EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
+ GetShelfWidget()->GetWindowBoundsInScreen().y());
+
+ // Drag mouse to bottom of screen.
+ generator.PressLeftButton();
+ generator.MoveMouseTo(0, root->bounds().bottom() - 1);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ generator.ReleaseLeftButton();
+ generator.MoveMouseTo(1, root->bounds().bottom() - 1);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ generator.PressLeftButton();
+ generator.MoveMouseTo(1, root->bounds().bottom() - 1);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+}
+
+// Test the behavior of the shelf when it is auto hidden and it is on the
+// boundary between the primary and the secondary display.
+TEST_F(ShelfLayoutManagerTest, AutoHideShelfOnScreenBoundary) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("800x600,800x600");
+ DisplayLayout display_layout(DisplayLayout::RIGHT, 0);
+ Shell::GetInstance()->display_controller()->SetLayoutForCurrentDisplays(
+ display_layout);
+ // Put the primary monitor's shelf on the display boundary.
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
+
+ // Create a window because the shelf is always shown when no windows are
+ // visible.
+ CreateTestWidget();
+
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ ASSERT_EQ(root_windows[0],
+ GetShelfWidget()->GetNativeWindow()->GetRootWindow());
+
+ shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+
+ int right_edge = root_windows[0]->GetBoundsInScreen().right() - 1;
+ int y = root_windows[0]->GetBoundsInScreen().y();
+
+ // Start off the mouse nowhere near the shelf; the shelf should be hidden.
+ aura::test::EventGenerator& generator(GetEventGenerator());
+ generator.MoveMouseTo(right_edge - 50, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Moving the mouse over the light bar (but not to the edge of the screen)
+ // should show the shelf.
+ generator.MoveMouseTo(right_edge - 1, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
+
+ // Moving the mouse off the light bar should hide the shelf.
+ generator.MoveMouseTo(right_edge - 50, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Moving the mouse to the right edge of the screen crossing the light bar
+ // should show the shelf despite the mouse cursor getting warped to the
+ // secondary display.
+ generator.MoveMouseTo(right_edge - 1, y);
+ generator.MoveMouseTo(right_edge, y);
+ UpdateAutoHideStateNow();
+ EXPECT_NE(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Hide the shelf.
+ generator.MoveMouseTo(right_edge - 50, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Moving the mouse to the right edge of the screen crossing the light bar and
+ // overshooting by a lot should keep the shelf hidden.
+ generator.MoveMouseTo(right_edge - 1, y);
+ generator.MoveMouseTo(right_edge + 50, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Moving the mouse to the right edge of the screen crossing the light bar and
+ // overshooting a bit should show the shelf.
+ generator.MoveMouseTo(right_edge - 1, y);
+ generator.MoveMouseTo(right_edge + 2, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Keeping the mouse close to the left edge of the secondary display after the
+ // shelf is shown should keep the shelf shown.
+ generator.MoveMouseTo(right_edge + 2, y + 1);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Moving the mouse far from the left edge of the secondary display should
+ // hide the shelf.
+ generator.MoveMouseTo(right_edge + 50, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Moving to the left edge of the secondary display without first crossing
+ // the primary display's right aligned shelf first should not show the shelf.
+ generator.MoveMouseTo(right_edge + 2, y);
+ UpdateAutoHideStateNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+}
+
+// Assertions around the lock screen showing.
+TEST_F(ShelfLayoutManagerTest, VisibleWhenLockScreenShowing) {
+ // Since ShelfLayoutManager queries for mouse location, move the mouse so
+ // it isn't over the shelf.
+ aura::test::EventGenerator generator(
+ Shell::GetPrimaryRootWindow(), gfx::Point());
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Maximize();
+ widget->Show();
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ aura::RootWindow* root = Shell::GetPrimaryRootWindow();
+ // LayoutShelf() forces the animation to completion, at which point the
+ // launcher should go off the screen.
+ shelf->LayoutShelf();
+ EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
+ GetShelfWidget()->GetWindowBoundsInScreen().y());
+
+ aura::Window* lock_container = Shell::GetContainer(
+ Shell::GetPrimaryRootWindow(),
+ internal::kShellWindowId_LockScreenContainer);
+
+ views::Widget* lock_widget = new views::Widget;
+ views::Widget::InitParams lock_params(
+ views::Widget::InitParams::TYPE_WINDOW);
+ lock_params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ lock_params.parent = lock_container;
+ // Widget is now owned by the parent window.
+ lock_widget->Init(lock_params);
+ lock_widget->Maximize();
+ lock_widget->Show();
+
+ // Lock the screen.
+ Shell::GetInstance()->session_state_delegate()->LockScreen();
+ shelf->UpdateVisibilityState();
+ // Showing a widget in the lock screen should force the shelf to be visibile.
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ Shell::GetInstance()->session_state_delegate()->UnlockScreen();
+ shelf->UpdateVisibilityState();
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+}
+
+// Assertions around SetAutoHideBehavior.
+TEST_F(ShelfLayoutManagerTest, SetAutoHideBehavior) {
+ // Since ShelfLayoutManager queries for mouse location, move the mouse so
+ // it isn't over the shelf.
+ aura::test::EventGenerator generator(
+ Shell::GetPrimaryRootWindow(), gfx::Point());
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Show();
+ aura::Window* window = widget->GetNativeWindow();
+ gfx::Rect display_bounds(
+ Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ widget->Maximize();
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
+ window).work_area().bottom(),
+ widget->GetWorkAreaBoundsInScreen().bottom());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
+ window).work_area().bottom(),
+ widget->GetWorkAreaBoundsInScreen().bottom());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
+ window).work_area().bottom(),
+ widget->GetWorkAreaBoundsInScreen().bottom());
+}
+
+// Basic assertions around the dimming of the shelf.
+TEST_F(ShelfLayoutManagerTest, TestDimmingBehavior) {
+ // Since ShelfLayoutManager queries for mouse location, move the mouse so
+ // it isn't over the shelf.
+ aura::test::EventGenerator generator(
+ Shell::GetPrimaryRootWindow(), gfx::Point());
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->shelf_widget()->DisableDimmingAnimationsForTest();
+
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Show();
+ aura::Window* window = widget->GetNativeWindow();
+ gfx::Rect display_bounds(
+ Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
+
+ gfx::Point off_shelf = display_bounds.CenterPoint();
+ gfx::Point on_shelf =
+ shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
+
+ // Test there is no dimming object active at this point.
+ generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
+ EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
+ EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // After maximization, the shelf should be visible and the dimmer created.
+ widget->Maximize();
+
+ on_shelf = shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
+ EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // Moving the mouse off the shelf should dim the bar.
+ generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
+ EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // Adding touch events outside the shelf should still keep the shelf in
+ // dimmed state.
+ generator.PressTouch();
+ generator.MoveTouch(off_shelf);
+ EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ // Move the touch into the shelf area should undim.
+ generator.MoveTouch(on_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.ReleaseTouch();
+ // And a release dims again.
+ EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // Moving the mouse on the shelf should undim the bar.
+ generator.MoveMouseTo(on_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // No matter what the touch events do, the shelf should stay undimmed.
+ generator.PressTouch();
+ generator.MoveTouch(off_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveTouch(on_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveTouch(off_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveTouch(on_shelf);
+ generator.ReleaseTouch();
+
+ // After restore, the dimming object should be deleted again.
+ widget->Restore();
+ EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
+}
+
+// Assertions around the dimming of the shelf in conjunction with menus.
+TEST_F(ShelfLayoutManagerTest, TestDimmingBehaviorWithMenus) {
+ // Since ShelfLayoutManager queries for mouse location, move the mouse so
+ // it isn't over the shelf.
+ aura::test::EventGenerator generator(
+ Shell::GetPrimaryRootWindow(), gfx::Point());
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->shelf_widget()->DisableDimmingAnimationsForTest();
+
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Show();
+ aura::Window* window = widget->GetNativeWindow();
+ gfx::Rect display_bounds(
+ Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
+
+ // After maximization, the shelf should be visible and the dimmer created.
+ widget->Maximize();
+
+ gfx::Point off_shelf = display_bounds.CenterPoint();
+ gfx::Point on_shelf =
+ shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
+
+ // Moving the mouse on the shelf should undim the bar.
+ generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // Simulate a menu opening.
+ shelf->shelf_widget()->ForceUndimming(true);
+
+ // Moving the mouse off the shelf should not dim the bar.
+ generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // No matter what the touch events do, the shelf should stay undimmed.
+ generator.PressTouch();
+ generator.MoveTouch(off_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveTouch(on_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveTouch(off_shelf);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.ReleaseTouch();
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // "Closing the menu" should now turn off the menu since no event is inside
+ // the shelf any longer.
+ shelf->shelf_widget()->ForceUndimming(false);
+ EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+
+ // Moving the mouse again on the shelf which should undim the bar again.
+ // This time we check that the bar stays undimmed when the mouse remains on
+ // the bar and the "menu gets closed".
+ generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ shelf->shelf_widget()->ForceUndimming(true);
+ generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+ shelf->shelf_widget()->ForceUndimming(true);
+ EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
+}
+
+// Verifies the shelf is visible when status/launcher is focused.
+TEST_F(ShelfLayoutManagerTest, VisibleWhenStatusOrLauncherFocused) {
+ // Since ShelfLayoutManager queries for mouse location, move the mouse so
+ // it isn't over the shelf.
+ aura::test::EventGenerator generator(
+ Shell::GetPrimaryRootWindow(), gfx::Point());
+ generator.MoveMouseTo(0, 0);
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ // Widget is now owned by the parent window.
+ widget->Init(params);
+ widget->Show();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Focus the launcher. Have to go through the focus cycler as normal focus
+ // requests to it do nothing.
+ GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ widget->Activate();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Trying to activate the status should fail, since we only allow activating
+ // it when the user is using the keyboard (i.e. through FocusCycler).
+ GetShelfWidget()->status_area_widget()->Activate();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+}
+
+// Makes sure shelf will be visible when app list opens as shelf is in
+// SHELF_VISIBLE state,and toggling app list won't change shelf
+// visibility state.
+TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfVisibleState) {
+ Shell* shell = Shell::GetInstance();
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->LayoutShelf();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+
+ // Create a normal unmaximized windowm shelf should be visible.
+ aura::Window* window = CreateTestWindow();
+ window->SetBounds(gfx::Rect(0, 0, 100, 100));
+ window->Show();
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ // Toggle app list to show, and the shelf stays visible.
+ shell->ToggleAppList(NULL);
+ EXPECT_TRUE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ // Toggle app list to hide, and the shelf stays visible.
+ shell->ToggleAppList(NULL);
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+}
+
+// Makes sure shelf will be shown with SHELF_AUTO_HIDE_SHOWN state
+// when app list opens as shelf is in SHELF_AUTO_HIDE state, and
+// toggling app list won't change shelf visibility state.
+TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
+ Shell* shell = Shell::GetInstance();
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->LayoutShelf();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+
+ // Create a window and show it in maximized state.
+ aura::Window* window = CreateTestWindow();
+ window->SetBounds(gfx::Rect(0, 0, 100, 100));
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ window->Show();
+ wm::ActivateWindow(window);
+
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+
+ // Toggle app list to show.
+ shell->ToggleAppList(NULL);
+ // The shelf's auto hide state won't be changed until the timer fires, so
+ // calling shell->UpdateShelfVisibility() is kind of manually helping it to
+ // update the state.
+ shell->UpdateShelfVisibility();
+ EXPECT_TRUE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Toggle app list to hide.
+ shell->ToggleAppList(NULL);
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+}
+
+// Makes sure shelf will be hidden when app list opens as shelf is in HIDDEN
+// state, and toggling app list won't change shelf visibility state.
+TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
+ Shell* shell = Shell::GetInstance();
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ // For shelf to be visible, app list is not open in initial state.
+ shelf->LayoutShelf();
+
+ // Create a window and make it full screen.
+ aura::Window* window = CreateTestWindow();
+ window->SetBounds(gfx::Rect(0, 0, 100, 100));
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
+ window->Show();
+ wm::ActivateWindow(window);
+
+ // App list and shelf is not shown.
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
+
+ // Toggle app list to show.
+ shell->ToggleAppList(NULL);
+ EXPECT_TRUE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
+
+ // Toggle app list to hide.
+ shell->ToggleAppList(NULL);
+ EXPECT_FALSE(shell->GetAppListTargetVisibility());
+ EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
+}
+
+#if defined(OS_WIN)
+// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
+#define MAYBE_SetAlignment DISABLED_SetAlignment
+#else
+#define MAYBE_SetAlignment SetAlignment
+#endif
+
+// Tests SHELF_ALIGNMENT_(LEFT, RIGHT, TOP).
+TEST_F(ShelfLayoutManagerTest, MAYBE_SetAlignment) {
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ // Force an initial layout.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ shelf->LayoutShelf();
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+
+ shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
+ gfx::Rect launcher_bounds(
+ GetShelfWidget()->GetWindowBoundsInScreen());
+ const gfx::Screen* screen = Shell::GetScreen();
+ gfx::Display display =
+ screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ ASSERT_NE(-1, display.id());
+ EXPECT_EQ(shelf->GetIdealBounds().width(),
+ display.GetWorkAreaInsets().left());
+ EXPECT_GE(
+ launcher_bounds.width(),
+ GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
+ EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment());
+ StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
+ gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
+ EXPECT_GE(status_bounds.width(),
+ status_area_widget->GetContentsView()->GetPreferredSize().width());
+ EXPECT_EQ(shelf->GetIdealBounds().width(),
+ display.GetWorkAreaInsets().left());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().top());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().right());
+ EXPECT_EQ(display.bounds().x(), launcher_bounds.x());
+ EXPECT_EQ(display.bounds().y(), launcher_bounds.y());
+ EXPECT_EQ(display.bounds().height(), launcher_bounds.height());
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
+ display.GetWorkAreaInsets().left());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize, display.work_area().x());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ ASSERT_NE(-1, display.id());
+ EXPECT_EQ(shelf->GetIdealBounds().width(),
+ display.GetWorkAreaInsets().right());
+ EXPECT_GE(launcher_bounds.width(),
+ GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
+ EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, GetSystemTray()->shelf_alignment());
+ status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
+ EXPECT_GE(status_bounds.width(),
+ status_area_widget->GetContentsView()->GetPreferredSize().width());
+ EXPECT_EQ(shelf->GetIdealBounds().width(),
+ display.GetWorkAreaInsets().right());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().top());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().left());
+ EXPECT_EQ(display.work_area().right(), launcher_bounds.x());
+ EXPECT_EQ(display.bounds().y(), launcher_bounds.y());
+ EXPECT_EQ(display.bounds().height(), launcher_bounds.height());
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
+ display.GetWorkAreaInsets().right());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
+ display.bounds().right() - display.work_area().right());
+
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ shelf->SetAlignment(SHELF_ALIGNMENT_TOP);
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ ASSERT_NE(-1, display.id());
+ EXPECT_EQ(shelf->GetIdealBounds().height(),
+ display.GetWorkAreaInsets().top());
+ EXPECT_GE(launcher_bounds.height(),
+ GetShelfWidget()->GetContentsView()->GetPreferredSize().height());
+ EXPECT_EQ(SHELF_ALIGNMENT_TOP, GetSystemTray()->shelf_alignment());
+ status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
+ EXPECT_GE(status_bounds.height(),
+ status_area_widget->GetContentsView()->GetPreferredSize().height());
+ EXPECT_EQ(shelf->GetIdealBounds().height(),
+ display.GetWorkAreaInsets().top());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().right());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
+ EXPECT_EQ(0, display.GetWorkAreaInsets().left());
+ EXPECT_EQ(display.work_area().y(), launcher_bounds.bottom());
+ EXPECT_EQ(display.bounds().x(), launcher_bounds.x());
+ EXPECT_EQ(display.bounds().width(), launcher_bounds.width());
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
+ display.GetWorkAreaInsets().top());
+ EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
+ display.work_area().y() - display.bounds().y());
+}
+
+#if defined(OS_WIN)
+// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
+#define MAYBE_GestureDrag DISABLED_GestureDrag
+#else
+#define MAYBE_GestureDrag GestureDrag
+#endif
+
+TEST_F(ShelfLayoutManagerTest, MAYBE_GestureDrag) {
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ {
+ SCOPED_TRACE("BOTTOM");
+ RunGestureDragTests(gfx::Vector2d(0, 100));
+ }
+
+ {
+ SCOPED_TRACE("LEFT");
+ shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
+ RunGestureDragTests(gfx::Vector2d(-100, 0));
+ }
+
+ {
+ SCOPED_TRACE("RIGHT");
+ shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
+ RunGestureDragTests(gfx::Vector2d(100, 0));
+ }
+}
+
+TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("800x600,800x600");
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->LayoutShelf();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+
+ // Create a visible window so auto-hide behavior is enforced
+ views::Widget* dummy = CreateTestWidget();
+
+ // Window visible => auto hide behaves normally.
+ shelf->UpdateVisibilityState();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Window minimized => auto hide disabled.
+ dummy->Minimize();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Window closed => auto hide disabled.
+ dummy->CloseNow();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Multiple window test
+ views::Widget* window1 = CreateTestWidget();
+ views::Widget* window2 = CreateTestWidget();
+
+ // both visible => normal autohide
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // either minimzed => normal autohide
+ window2->Minimize();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ window2->Restore();
+ window1->Minimize();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // both minimized => disable auto hide
+ window2->Minimize();
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ // Test moving windows to/from other display.
+ window2->Restore();
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ // Move to second display.
+ window2->SetBounds(gfx::Rect(850, 50, 50, 50));
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ // Move back to primary display.
+ window2->SetBounds(gfx::Rect(50, 50, 50, 50));
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+}
+
+// Test that the shelf animates back to its normal position upon a user
+// completing a gesture drag.
+TEST_F(ShelfLayoutManagerTest, ShelfAnimatesWhenGestureComplete) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ // Test the shelf animates back to its original visible bounds when it is
+ // dragged when there are no visible windows.
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ gfx::Rect visible_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+ {
+ // Enable animations so that we can make sure that they occur.
+ ui::ScopedAnimationDurationScaleMode regular_animations(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+ gfx::Rect shelf_bounds_in_screen =
+ GetShelfWidget()->GetWindowBoundsInScreen();
+ gfx::Point start(shelf_bounds_in_screen.CenterPoint());
+ gfx::Point end(start.x(), shelf_bounds_in_screen.bottom());
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(10), 1);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+ ShelfAnimationWaiter waiter(visible_bounds);
+ // Wait till the animation completes and check that it occurred.
+ waiter.WaitTillDoneAnimating();
+ EXPECT_TRUE(waiter.WasValidAnimation());
+ }
+
+ // Create a visible window so auto-hide behavior is enforced.
+ CreateTestWidget();
+
+ // Get the bounds of the shelf when it is hidden.
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ gfx::Rect auto_hidden_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
+
+ {
+ // Enable the animations so that we can make sure they do occur.
+ ui::ScopedAnimationDurationScaleMode regular_animations(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+
+ gfx::Point start =
+ GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
+ gfx::Point end(start.x(), start.y() - 100);
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+
+ // Test that the shelf animates to the visible bounds after a swipe up on
+ // the auto hidden shelf.
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(10), 1);
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ ShelfAnimationWaiter waiter1(visible_bounds);
+ waiter1.WaitTillDoneAnimating();
+ EXPECT_TRUE(waiter1.WasValidAnimation());
+
+ // Test that the shelf animates to the auto hidden bounds after a swipe up
+ // on the visible shelf.
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(10), 1);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ ShelfAnimationWaiter waiter2(auto_hidden_bounds);
+ waiter2.WaitTillDoneAnimating();
+ EXPECT_TRUE(waiter2.WasValidAnimation());
+ }
+}
+
+TEST_F(ShelfLayoutManagerTest, GestureRevealsTrayBubble) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->LayoutShelf();
+
+ // Create a visible window so auto-hide behavior is enforced.
+ CreateTestWidget();
+
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+ SystemTray* tray = GetSystemTray();
+
+ // First, make sure the shelf is visible.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ EXPECT_FALSE(tray->HasSystemBubble());
+
+ // Now, drag up on the tray to show the bubble.
+ gfx::Point start = GetShelfWidget()->status_area_widget()->
+ GetWindowBoundsInScreen().CenterPoint();
+ gfx::Point end(start.x(), start.y() - 100);
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(10), 1);
+ EXPECT_TRUE(tray->HasSystemBubble());
+ tray->CloseSystemBubble();
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(tray->HasSystemBubble());
+
+ // Drag again, but only a small amount, and slowly. The bubble should not be
+ // visible.
+ end.set_y(start.y() - 30);
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(500), 100);
+ EXPECT_FALSE(tray->HasSystemBubble());
+
+ // Now, hide the shelf.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+
+ // Start a drag from the bezel, and drag up to show both the shelf and the
+ // tray bubble.
+ start.set_y(start.y() + 100);
+ end.set_y(start.y() - 400);
+ generator.GestureScrollSequence(start, end,
+ base::TimeDelta::FromMilliseconds(10), 1);
+ EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+ EXPECT_TRUE(tray->HasSystemBubble());
+}
+
+TEST_F(ShelfLayoutManagerTest, ShelfFlickerOnTrayActivation) {
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+
+ // Create a visible window so auto-hide behavior is enforced.
+ CreateTestWidget();
+
+ // Turn on auto-hide for the shelf.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+ // Show the status menu. That should make the shelf visible again.
+ Shell::GetInstance()->accelerator_controller()->PerformAction(
+ SHOW_SYSTEM_TRAY_BUBBLE, ui::Accelerator());
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
+
+ // Now activate the tray (using the keyboard, instead of using the mouse to
+ // make sure the mouse does not alter the auto-hide state in the shelf).
+ // This should not trigger any auto-hide state change in the shelf.
+ ShelfLayoutObserverTest observer;
+ shelf->AddObserver(&observer);
+
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+ generator.PressKey(ui::VKEY_SPACE, 0);
+ generator.ReleaseKey(ui::VKEY_SPACE, 0);
+ EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_FALSE(observer.changed_auto_hide_state());
+
+ shelf->RemoveObserver(&observer);
+}
+
+TEST_F(ShelfLayoutManagerTest, WorkAreaChangeWorkspace) {
+ // Make sure the shelf is always visible.
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ shelf->LayoutShelf();
+
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.context = CurrentContext();
+ views::Widget* widget_one = CreateTestWidgetWithParams(params);
+ widget_one->Maximize();
+
+ views::Widget* widget_two = CreateTestWidgetWithParams(params);
+ widget_two->Maximize();
+ widget_two->Activate();
+
+ // Both windows are maximized. They should be of the same size.
+ EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
+ widget_two->GetNativeWindow()->bounds().ToString());
+ int area_when_shelf_shown =
+ widget_one->GetNativeWindow()->bounds().size().GetArea();
+
+ // Now hide the shelf.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+
+ // Both windows should be resized according to the shelf status.
+ EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
+ widget_two->GetNativeWindow()->bounds().ToString());
+ // Resized to small.
+ EXPECT_LT(area_when_shelf_shown,
+ widget_one->GetNativeWindow()->bounds().size().GetArea());
+
+ // Now show the shelf.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+
+ // Again both windows should be of the same size.
+ EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
+ widget_two->GetNativeWindow()->bounds().ToString());
+ EXPECT_EQ(area_when_shelf_shown,
+ widget_one->GetNativeWindow()->bounds().size().GetArea());
+}
+
+// Confirm that the shelf is dimmed only when content is maximized and
+// shelf is not autohidden.
+TEST_F(ShelfLayoutManagerTest, Dimming) {
+ GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ scoped_ptr<aura::Window> w1(CreateTestWindow());
+ w1->Show();
+ wm::ActivateWindow(w1.get());
+
+ // Normal window doesn't dim shelf.
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ ShelfWidget* shelf = GetShelfWidget();
+ EXPECT_FALSE(shelf->GetDimsShelf());
+
+ // Maximized window does.
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_TRUE(shelf->GetDimsShelf());
+
+ // Change back to normal stops dimming.
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ EXPECT_FALSE(shelf->GetDimsShelf());
+
+ // Changing back to maximized dims again.
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_TRUE(shelf->GetDimsShelf());
+
+ // Changing shelf to autohide stops dimming.
+ GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_FALSE(shelf->GetDimsShelf());
+}
+
+// Make sure that the shelf will not hide if the mouse is between a bubble and
+// the shelf.
+TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) {
+ ShelfLayoutManager* shelf = GetShelfLayoutManager();
+ StatusAreaWidget* status_area_widget =
+ Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
+ SystemTray* tray = GetSystemTray();
+
+ // Create a visible window so auto-hide behavior is enforced.
+ CreateTestWidget();
+
+ shelf->LayoutShelf();
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+
+ // Make two iterations - first without a message bubble which should make
+ // the shelf disappear and then with a message bubble which should keep it
+ // visible.
+ for (int i = 0; i < 2; i++) {
+ // Make sure the shelf is visible and position the mouse over it. Then
+ // allow auto hide.
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+ EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
+ gfx::Point center =
+ status_area_widget->GetWindowBoundsInScreen().CenterPoint();
+ generator.MoveMouseTo(center.x(), center.y());
+ shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ EXPECT_TRUE(shelf->IsVisible());
+ if (!i) {
+ // In our first iteration we make sure there is no bubble.
+ tray->CloseSystemBubble();
+ EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
+ } else {
+ // In our second iteration we show a bubble.
+ TestItem *item = new TestItem;
+ tray->AddTrayItem(item);
+ tray->ShowNotificationView(item);
+ EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
+ }
+ // Move the pointer over the edge of the shelf.
+ generator.MoveMouseTo(
+ center.x(), status_area_widget->GetWindowBoundsInScreen().y() - 8);
+ shelf->UpdateVisibilityState();
+ if (i) {
+ EXPECT_TRUE(shelf->IsVisible());
+ EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
+ } else {
+ EXPECT_FALSE(shelf->IsVisible());
+ EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
+ }
+ }
+}
+
+TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColor) {
+ EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
+
+ scoped_ptr<aura::Window> w1(CreateTestWindow());
+ w1->Show();
+ wm::ActivateWindow(w1.get());
+ EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
+
+ scoped_ptr<aura::Window> w2(CreateTestWindow());
+ w2->Show();
+ wm::ActivateWindow(w2.get());
+ // Overlaps with shelf.
+ w2->SetBounds(GetShelfLayoutManager()->GetIdealBounds());
+
+ // Still background is 'maximized'.
+ EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
+
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
+ w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
+
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
+ w1.reset();
+ EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
+}
+
+// Verify that the shelf doesn't have the opaque background if it's auto-hide
+// status.
+TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColorAutoHide) {
+ EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget ()->GetBackgroundType());
+
+ GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ scoped_ptr<aura::Window> w1(CreateTestWindow());
+ w1->Show();
+ wm::ActivateWindow(w1.get());
+ EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
+ w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
+}
+
+} // namespace internal
+} // namespace ash