From 478c6c3aa0165dfd120993c5ec0757d594e70fe6 Mon Sep 17 00:00:00 2001 From: "harrym@chromium.org" Date: Sat, 9 Mar 2013 02:50:58 +0000 Subject: Refactor: Shelf Widget Refactor the classes related with displaying the shelf (background behind the launcher/status area widget) to be a separate class. Removing background delegates from the launcher and status area widget (represented on tray views). TBR=ben@chromium.org BUG=163002 Review URL: https://chromiumcodereview.appspot.com/12313118 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187122 0039d316-1c4b-4281-b951-d872f2087c98 --- ash/accelerators/accelerator_controller.cc | 5 +- ash/ash.gyp | 15 +- ash/dip_unittest.cc | 3 +- ash/display/display_controller_unittest.cc | 5 +- ash/focus_cycler_unittest.cc | 92 +- ash/launcher/background_animator.cc | 57 - ash/launcher/background_animator.h | 72 -- ash/launcher/launcher.cc | 321 +----- ash/launcher/launcher.h | 72 +- ash/launcher/launcher_alignment_menu.cc | 4 +- ash/launcher/launcher_button.cc | 2 +- ash/launcher/launcher_tooltip_manager.cc | 2 +- ash/launcher/launcher_tooltip_manager.h | 4 +- ash/launcher/launcher_tooltip_manager_unittest.cc | 14 +- ash/launcher/launcher_unittest.cc | 124 +-- ash/launcher/launcher_view.cc | 3 +- ash/launcher/launcher_view.h | 1 - ash/launcher/launcher_view_unittest.cc | 12 +- ash/launcher/overflow_bubble.cc | 2 +- ash/launcher/overflow_button.cc | 2 +- ash/launcher/overflow_button.h | 2 +- ash/root_window_controller.cc | 139 +-- ash/root_window_controller.h | 39 +- ash/root_window_controller_unittest.cc | 6 +- ash/screen_ash.cc | 5 +- ash/screen_ash_unittest.cc | 6 +- ash/shelf/background_animator.cc | 57 + ash/shelf/background_animator.h | 71 ++ ash/shelf/shelf_layout_manager.cc | 923 ++++++++++++++++ ash/shelf/shelf_layout_manager.h | 332 ++++++ ash/shelf/shelf_layout_manager_unittest.cc | 1108 +++++++++++++++++++ ash/shelf/shelf_types.h | 46 + ash/shelf/shelf_widget.cc | 312 ++++++ ash/shelf/shelf_widget.h | 104 ++ ash/shelf/shelf_widget_unittest.cc | 156 +++ ash/shelf_types.h | 46 - ash/shell.cc | 25 +- ash/shell.h | 16 +- ash/shell/context_menu.cc | 2 +- ash/shell/context_menu.h | 8 +- ash/shell/window_type_launcher.cc | 5 +- ash/shell/window_watcher.cc | 7 +- ash/shell_unittest.cc | 16 +- ash/shell_window_ids.h | 4 +- ash/system/ime/tray_ime.cc | 2 +- .../tray_session_length_limit.cc | 2 +- ash/system/status_area_widget.cc | 12 +- ash/system/status_area_widget.h | 8 +- ash/system/status_area_widget_delegate.h | 2 +- ash/system/tray/system_tray.cc | 2 +- ash/system/tray/system_tray_item.h | 2 +- ash/system/tray/system_tray_unittest.cc | 7 +- ash/system/tray/tray_background_view.cc | 25 +- ash/system/tray/tray_background_view.h | 11 +- ash/system/tray/tray_event_filter.cc | 2 +- ash/system/tray/tray_item_view.cc | 2 +- ash/system/tray/tray_views.h | 2 +- ash/system/tray_update.cc | 5 +- .../web_notification/web_notification_tray.cc | 2 +- .../web_notification_tray_unittest.cc | 5 +- ash/wm/activation_controller.cc | 2 +- ash/wm/app_list_controller.cc | 5 +- ash/wm/ash_activation_controller.cc | 23 +- ash/wm/ash_activation_controller_unittest.cc | 3 +- ash/wm/ash_focus_rules.cc | 2 +- ash/wm/base_layout_manager.cc | 2 +- ash/wm/drag_window_resizer_unittest.cc | 4 +- ash/wm/gestures/shelf_gesture_handler.cc | 16 +- ash/wm/gestures/system_pinch_handler.cc | 3 +- ash/wm/maximize_bubble_controller.cc | 2 +- ash/wm/panels/panel_layout_manager.cc | 15 +- ash/wm/panels/panel_layout_manager_unittest.cc | 7 +- ash/wm/panels/panel_window_resizer.cc | 7 +- ash/wm/panels/panel_window_resizer_unittest.cc | 6 +- ash/wm/session_state_animator.cc | 4 +- ash/wm/shelf_layout_manager.cc | 945 ---------------- ash/wm/shelf_layout_manager.h | 338 ------ ash/wm/shelf_layout_manager_unittest.cc | 1132 -------------------- ash/wm/stacking_controller_unittest.cc | 2 +- ash/wm/status_area_layout_manager.cc | 9 +- ash/wm/status_area_layout_manager.h | 7 +- ash/wm/workspace/frame_maximize_button.cc | 3 +- ash/wm/workspace/phantom_window_controller.cc | 2 +- ash/wm/workspace/workspace_cycler_animator.cc | 12 +- .../workspace/workspace_layout_manager_unittest.cc | 7 +- ash/wm/workspace/workspace_manager.cc | 2 +- ash/wm/workspace/workspace_manager_unittest.cc | 16 +- .../workspace/workspace_window_resizer_unittest.cc | 8 +- 88 files changed, 3466 insertions(+), 3456 deletions(-) delete mode 100644 ash/launcher/background_animator.cc delete mode 100644 ash/launcher/background_animator.h create mode 100644 ash/shelf/background_animator.cc create mode 100644 ash/shelf/background_animator.h create mode 100644 ash/shelf/shelf_layout_manager.cc create mode 100644 ash/shelf/shelf_layout_manager.h create mode 100644 ash/shelf/shelf_layout_manager_unittest.cc create mode 100644 ash/shelf/shelf_types.h create mode 100644 ash/shelf/shelf_widget.cc create mode 100644 ash/shelf/shelf_widget.h create mode 100644 ash/shelf/shelf_widget_unittest.cc delete mode 100644 ash/shelf_types.h delete mode 100644 ash/wm/shelf_layout_manager.cc delete mode 100644 ash/wm/shelf_layout_manager.h delete mode 100644 ash/wm/shelf_layout_manager_unittest.cc (limited to 'ash') diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 6829148..943e75f 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -25,6 +25,7 @@ #include "ash/root_window_controller.h" #include "ash/rotator/screen_rotation.h" #include "ash/screenshot_delegate.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" @@ -614,7 +615,7 @@ bool AcceleratorController::PerformAction(int action, break; case FOCUS_LAUNCHER: return shell->focus_cycler()->FocusWidget( - Launcher::ForPrimaryDisplay()->widget()); + Launcher::ForPrimaryDisplay()->shelf_widget()); break; case FOCUS_NEXT_PANE: return HandleRotatePaneFocus(Shell::FORWARD); @@ -645,7 +646,7 @@ bool AcceleratorController::PerformAction(int action, internal::RootWindowController::ForActiveRootWindow() : Shell::GetPrimaryRootWindowController(); internal::StatusAreaWidget* status_area_widget = - controller->status_area_widget(); + controller->shelf()->status_area_widget(); if (status_area_widget) { WebNotificationTray* notification_tray = status_area_widget->web_notification_tray(); diff --git a/ash/ash.gyp b/ash/ash.gyp index 59b2f62..03b9b77 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -118,8 +118,6 @@ 'keyboard_overlay/keyboard_overlay_view.h', 'launcher/app_list_button.cc', 'launcher/app_list_button.h', - 'launcher/background_animator.cc', - 'launcher/background_animator.h', 'launcher/launcher.cc', 'launcher/launcher.h', 'launcher/launcher_alignment_menu.cc', @@ -161,11 +159,17 @@ 'screensaver/screensaver_view.cc', 'screensaver/screensaver_view.h', 'screenshot_delegate.h', + 'shelf/background_animator.cc', + 'shelf/background_animator.h', + 'shelf/shelf_layout_manager.cc', + 'shelf/shelf_layout_manager.h', + 'shelf/shelf_types.h', + 'shelf/shelf_widget.cc', + 'shelf/shelf_widget.h', 'shell.cc', 'shell.h', 'shell_delegate.h', 'shell_factory.h', - 'shelf_types.h', 'shell_window_ids.h', 'system/audio/audio_observer.h', 'system/audio/tray_volume.cc', @@ -388,8 +392,6 @@ 'wm/session_state_controller_impl2.cc', 'wm/session_state_controller_impl2.h', 'wm/session_state_observer.h', - 'wm/shelf_layout_manager.cc', - 'wm/shelf_layout_manager.h', 'wm/stacking_controller.cc', 'wm/stacking_controller.h', 'wm/status_area_layout_manager.cc', @@ -613,6 +615,8 @@ 'root_window_controller_unittest.cc', 'screen_ash_unittest.cc', 'screensaver/screensaver_view_unittest.cc', + 'shelf/shelf_layout_manager_unittest.cc', + 'shelf/shelf_widget_unittest.cc', 'shell_unittest.cc', 'shell/app_list.cc', 'shell/bubble.cc', @@ -644,7 +648,6 @@ 'wm/power_button_controller_unittest.cc', 'wm/screen_dimmer_unittest.cc', 'wm/session_state_controller_impl2_unittest.cc', - 'wm/shelf_layout_manager_unittest.cc', 'wm/stacking_controller_unittest.cc', 'wm/system_gesture_event_filter_unittest.cc', 'wm/system_modal_container_layout_manager_unittest.cc', diff --git a/ash/dip_unittest.cc b/ash/dip_unittest.cc index 2c00d71a..c21fb88 100644 --- a/ash/dip_unittest.cc +++ b/ash/dip_unittest.cc @@ -7,6 +7,7 @@ #include "ash/display/display_manager.h" #include "ash/launcher/launcher.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_properties.h" @@ -63,7 +64,7 @@ TEST_F(DIPTest, WorkArea) { Launcher* launcher = Launcher::ForPrimaryDisplay(); EXPECT_EQ( display_2x.bounds().InsetsFrom(work_area).height(), - launcher->widget()->GetNativeView()->layer()->bounds().height()); + launcher->shelf_widget()->GetNativeView()->layer()->bounds().height()); } } // namespace ash diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc index f1eb859..c9b94d4 100644 --- a/ash/display/display_controller_unittest.cc +++ b/ash/display/display_controller_unittest.cc @@ -7,6 +7,7 @@ #include "ash/display/display_manager.h" #include "ash/launcher/launcher.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" @@ -249,7 +250,7 @@ TEST_F(DisplayControllerTest, SwapPrimary) { display_controller->GetRootWindowForDisplayId(secondary_display.id()); EXPECT_NE(primary_root, secondary_root); aura::Window* launcher_window = - Launcher::ForPrimaryDisplay()->widget()->GetNativeView(); + Launcher::ForPrimaryDisplay()->shelf_widget()->GetNativeView(); EXPECT_TRUE(primary_root->Contains(launcher_window)); EXPECT_FALSE(secondary_root->Contains(launcher_window)); EXPECT_EQ(primary_display.id(), @@ -340,7 +341,7 @@ TEST_F(DisplayControllerTest, SwapPrimaryById) { aura::RootWindow* secondary_root = display_controller->GetRootWindowForDisplayId(secondary_display.id()); aura::Window* launcher_window = - Launcher::ForPrimaryDisplay()->widget()->GetNativeView(); + Launcher::ForPrimaryDisplay()->shelf_widget()->GetNativeView(); EXPECT_TRUE(primary_root->Contains(launcher_window)); EXPECT_FALSE(secondary_root->Contains(launcher_window)); EXPECT_NE(primary_root, secondary_root); diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc index c4fd2d1..bb75052 100644 --- a/ash/focus_cycler_unittest.cc +++ b/ash/focus_cycler_unittest.cc @@ -6,6 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/system/status_area_widget.h" @@ -54,7 +55,7 @@ class FocusCyclerTest : public AshTestBase { tray_.reset(); } - Launcher::ForPrimaryDisplay()->SetFocusCycler(NULL); + shelf_widget()->SetFocusCycler(NULL); focus_cycler_.reset(); @@ -85,14 +86,13 @@ class FocusCyclerTest : public AshTestBase { SystemTray* tray() { return tray_.get(); } - views::Widget* launcher_widget() { - return Launcher::ForPrimaryDisplay()->widget(); + ShelfWidget* shelf_widget() { + return Launcher::ForPrimaryDisplay()->shelf_widget(); } - void InstallFocusCycleOnLauncher() { - // Add the launcher - Launcher* launcher = Launcher::ForPrimaryDisplay(); - launcher->SetFocusCycler(focus_cycler()); + void InstallFocusCycleOnShelf() { + // Add the shelf. + shelf_widget()->SetFocusCycler(focus_cycler()); } private: @@ -116,22 +116,22 @@ TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) { TEST_F(FocusCyclerTest, CycleFocusForward) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); + InstallFocusCycleOnShelf(); // Create a single test window. scoped_ptr window0(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window0.get()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::FORWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } @@ -139,22 +139,22 @@ TEST_F(FocusCyclerTest, CycleFocusForward) { TEST_F(FocusCyclerTest, CycleFocusBackward) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); + InstallFocusCycleOnShelf(); // Create a single test window. scoped_ptr window0(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window0.get()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } @@ -162,34 +162,34 @@ TEST_F(FocusCyclerTest, CycleFocusBackward) { TEST_F(FocusCyclerTest, CycleFocusForwardBackward) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); + InstallFocusCycleOnShelf(); // Create a single test window. scoped_ptr window0(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window0.get()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::FORWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } @@ -197,66 +197,66 @@ TEST_F(FocusCyclerTest, CycleFocusForwardBackward) { TEST_F(FocusCyclerTest, CycleFocusNoBrowser) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); + InstallFocusCycleOnShelf(); - // Add the launcher and focus it - focus_cycler()->FocusWidget(launcher_widget()); + // Add the shelf and focus it. + focus_cycler()->FocusWidget(shelf_widget()); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::FORWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the launcher + // Cycle focus to the shelf. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); - EXPECT_TRUE(launcher_widget()->IsActive()); + EXPECT_TRUE(shelf_widget()->IsActive()); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); } -TEST_F(FocusCyclerTest, Launcher_CycleFocusForward) { +TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); - launcher_widget()->Hide(); + InstallFocusCycleOnShelf(); + shelf_widget()->Hide(); // Create a single test window. scoped_ptr window0(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window0.get()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::FORWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } -TEST_F(FocusCyclerTest, Launcher_CycleFocusBackwardInvisible) { +TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) { ASSERT_TRUE(CreateTray()); - InstallFocusCycleOnLauncher(); - launcher_widget()->Hide(); + InstallFocusCycleOnShelf(); + shelf_widget()->Hide(); // Create a single test window. scoped_ptr window0(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window0.get()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - // Cycle focus to the status area + // Cycle focus to the status area. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(tray()->GetWidget()->IsActive()); - // Cycle focus to the browser + // Cycle focus to the browser. focus_cycler()->RotateFocus(FocusCycler::BACKWARD); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } diff --git a/ash/launcher/background_animator.cc b/ash/launcher/background_animator.cc deleted file mode 100644 index db1d8aa..0000000 --- a/ash/launcher/background_animator.cc +++ /dev/null @@ -1,57 +0,0 @@ -// 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/launcher/background_animator.h" - - -namespace ash { -namespace internal { - -namespace { - -// Duration of the background animation. -const int kBackgroundDurationMS = 1000; - -} - -BackgroundAnimator::BackgroundAnimator(BackgroundAnimatorDelegate* delegate, - int min_alpha, - int max_alpha) - : delegate_(delegate), - min_alpha_(min_alpha), - max_alpha_(max_alpha), - ALLOW_THIS_IN_INITIALIZER_LIST(animation_(this)), - paints_background_(false), - alpha_(min_alpha) { - animation_.SetSlideDuration(kBackgroundDurationMS); -} - -BackgroundAnimator::~BackgroundAnimator() { -} - -void BackgroundAnimator::SetPaintsBackground(bool value, ChangeType type) { - if (paints_background_ == value) - return; - paints_background_ = value; - if (type == CHANGE_IMMEDIATE && !animation_.is_animating()) { - animation_.Reset(value ? 1.0f : 0.0f); - AnimationProgressed(&animation_); - return; - } - if (paints_background_) - animation_.Show(); - else - animation_.Hide(); -} - -void BackgroundAnimator::AnimationProgressed(const ui::Animation* animation) { - int alpha = animation->CurrentValueBetween(min_alpha_, max_alpha_); - if (alpha_ == alpha) - return; - alpha_ = alpha; - delegate_->UpdateBackground(alpha_); -} - -} // namespace internal -} // namespace ash diff --git a/ash/launcher/background_animator.h b/ash/launcher/background_animator.h deleted file mode 100644 index cb4bdcd..0000000 --- a/ash/launcher/background_animator.h +++ /dev/null @@ -1,72 +0,0 @@ -// 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. - -#ifndef ASH_LAUNCHER_BACKGROUND_ANIMATOR_H_ -#define ASH_LAUNCHER_BACKGROUND_ANIMATOR_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/slide_animation.h" - -namespace ash { -namespace internal { - -// Delegate is notified any time the background changes. -class ASH_EXPORT BackgroundAnimatorDelegate { - public: - virtual void UpdateBackground(int alpha) = 0; - - protected: - virtual ~BackgroundAnimatorDelegate() {} -}; - -// BackgroundAnimator is used by the launcher and system tray to animate the -// background (alpha). -class ASH_EXPORT BackgroundAnimator : public ui::AnimationDelegate { - public: - // How the background can be changed. - enum ChangeType { - CHANGE_ANIMATE, - CHANGE_IMMEDIATE - }; - - BackgroundAnimator(BackgroundAnimatorDelegate* delegate, - int min_alpha, - int max_alpha); - virtual ~BackgroundAnimator(); - - // Sets whether a background is rendered. Initial value is false. If |type| - // is |CHANGE_IMMEDIATE| and an animation is not in progress this notifies - // the delegate immediately (synchronously from this method). - void SetPaintsBackground(bool value, ChangeType type); - bool paints_background() const { return paints_background_; } - - // Current alpha. - int alpha() const { return alpha_; } - - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - - private: - BackgroundAnimatorDelegate* delegate_; - - const int min_alpha_; - const int max_alpha_; - - ui::SlideAnimation animation_; - - // Whether the background is painted. - bool paints_background_; - - // Current alpha value of the background. - int alpha_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundAnimator); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_LAUNCHER_BACKGROUND_ANIMATOR_H_ diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc index b794bac..54c8e0c 100644 --- a/ash/launcher/launcher.cc +++ b/ash/launcher/launcher.cc @@ -13,11 +13,12 @@ #include "ash/launcher/launcher_navigator.h" #include "ash/launcher/launcher_view.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_properties.h" #include "grit/ash_resources.h" #include "ui/aura/client/activation_client.h" @@ -43,310 +44,43 @@ const int kDimAlpha = 96; namespace ash { -// The contents view of the Widget. This view contains LauncherView and -// sizes it to the width of the widget minus the size of the status area. -class Launcher::DelegateView : public views::WidgetDelegate, - public views::AccessiblePaneView, - public internal::BackgroundAnimatorDelegate { - public: - explicit DelegateView(Launcher* launcher); - virtual ~DelegateView(); - - void set_focus_cycler(internal::FocusCycler* focus_cycler) { - focus_cycler_ = focus_cycler; - } - internal::FocusCycler* focus_cycler() { - return focus_cycler_; - } - - // views::View overrides - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void Layout() OVERRIDE; - virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; - - // views::WidgetDelegateView overrides: - virtual views::Widget* GetWidget() OVERRIDE { - return View::GetWidget(); - } - virtual const views::Widget* GetWidget() const OVERRIDE { - return View::GetWidget(); - } - virtual bool CanActivate() const OVERRIDE { - // Allow to activate as fallback. - if (launcher_->activating_as_fallback_) - return true; - // Allow to activate from the focus cycler. - if (focus_cycler_ && focus_cycler_->widget_activating() == GetWidget()) - return true; - // Disallow activating in other cases, especially when using mouse. - return false; - } - - // BackgroundAnimatorDelegate overrides: - virtual void UpdateBackground(int alpha) OVERRIDE; - - private: - Launcher* launcher_; - internal::FocusCycler* focus_cycler_; - int alpha_; - - DISALLOW_COPY_AND_ASSIGN(DelegateView); -}; - -// Class used to slightly dim shelf items when maximized and visible. It also -// makes sure the widget changes size to always be of the same size as the -// shelf. -class Launcher::DimmerView : public views::View, - public aura::WindowObserver { - public: - explicit DimmerView(Launcher* launcher) - : launcher_(launcher) { - launcher_->widget()->GetNativeWindow()->AddObserver(this); - } - - virtual ~DimmerView() { - if (launcher_) - launcher_->widget()->GetNativeWindow()->RemoveObserver(this); - } - - private: - // views::View overrides: - virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE { - ash::internal::ShelfLayoutManager* shelf = ash::GetRootWindowController( - GetWidget()->GetNativeView()->GetRootWindow())->shelf(); - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - gfx::ImageSkia background_image = - *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_DIMMING); - if (SHELF_ALIGNMENT_BOTTOM != launcher_->alignment_) - background_image = gfx::ImageSkiaOperations::CreateRotatedImage( - background_image, - shelf->SelectValueForShelfAlignment( - SkBitmapOperations::ROTATION_90_CW, - SkBitmapOperations::ROTATION_90_CW, - SkBitmapOperations::ROTATION_270_CW, - SkBitmapOperations::ROTATION_180_CW)); - - SkPaint paint; - paint.setAlpha(kDimAlpha); - canvas->DrawImageInt( - background_image, - 0, 0, background_image.width(), background_image.height(), - 0, 0, width(), height(), - false, - paint); - } - - // aura::WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE { - CHECK_EQ(window, launcher_->widget()->GetNativeWindow()); - GetWidget()->GetNativeWindow()->SetBounds(window->bounds()); - } - - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - CHECK_EQ(window, launcher_->widget()->GetNativeWindow()); - launcher_->widget()->GetNativeWindow()->RemoveObserver(this); - launcher_ = NULL; - } - - Launcher* launcher_; - DISALLOW_COPY_AND_ASSIGN(DimmerView); -}; - -Launcher::DelegateView::DelegateView(Launcher* launcher) - : launcher_(launcher), - focus_cycler_(NULL), - alpha_(0) { - // Allow the launcher to surrender the focus to another window upon - // navigation completion by the user. - set_allow_deactivate_on_esc(true); -} - -Launcher::DelegateView::~DelegateView() { -} - -gfx::Size Launcher::DelegateView::GetPreferredSize() { - return child_count() > 0 ? child_at(0)->GetPreferredSize() : gfx::Size(); -} - -void Launcher::DelegateView::Layout() { - if (child_count() == 0) - return; - View* launcher_view = child_at(0); - - if (launcher_->alignment_ == SHELF_ALIGNMENT_BOTTOM || - launcher_->alignment_ == SHELF_ALIGNMENT_TOP) { - int w = std::max(0, width() - launcher_->status_size_.width()); - launcher_view->SetBounds(0, 0, w, height()); - } else { - int h = std::max(0, height() - launcher_->status_size_.height()); - launcher_view->SetBounds(0, 0, width(), h); - } -} - -void Launcher::DelegateView::OnPaintBackground(gfx::Canvas* canvas) { - ash::internal::ShelfLayoutManager* shelf = ash::GetRootWindowController( - GetWidget()->GetNativeView()->GetRootWindow())->shelf(); - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - gfx::ImageSkia launcher_background = - *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND); - if (launcher_->alignment_ != SHELF_ALIGNMENT_BOTTOM) - launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage( - launcher_background, - shelf->SelectValueForShelfAlignment( - SkBitmapOperations::ROTATION_90_CW, - SkBitmapOperations::ROTATION_90_CW, - SkBitmapOperations::ROTATION_270_CW, - SkBitmapOperations::ROTATION_180_CW)); - - gfx::Rect black_rect = shelf->SelectValueForShelfAlignment( - gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels), - gfx::Rect(0, 0, kNumBlackPixels, height()), - gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()), - gfx::Rect(0, 0, width(), kNumBlackPixels)); - - SkPaint paint; - paint.setAlpha(alpha_); - canvas->DrawImageInt( - launcher_background, - 0, 0, launcher_background.width(), launcher_background.height(), - 0, 0, width(), height(), - false, - paint); - canvas->FillRect(black_rect, SK_ColorBLACK); -} - -void Launcher::DelegateView::UpdateBackground(int alpha) { - alpha_ = alpha; - SchedulePaint(); -} - -// Launcher -------------------------------------------------------------------- - Launcher::Launcher(LauncherModel* launcher_model, LauncherDelegate* launcher_delegate, - aura::Window* window_container, - internal::ShelfLayoutManager* shelf_layout_manager) - : widget_(NULL), - window_container_(window_container), - delegate_view_(new DelegateView(this)), - launcher_view_(NULL), + ShelfWidget* shelf_widget) + : launcher_view_(NULL), alignment_(SHELF_ALIGNMENT_BOTTOM), delegate_(launcher_delegate), - background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha), - activating_as_fallback_(false) { - widget_.reset(new views::Widget); - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.transparent = true; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = Shell::GetContainer( - window_container_->GetRootWindow(), - ash::internal::kShellWindowId_LauncherContainer); + shelf_widget_(shelf_widget) { launcher_view_ = new internal::LauncherView( - launcher_model, delegate_, shelf_layout_manager); + launcher_model, delegate_, shelf_widget_->shelf_layout_manager()); launcher_view_->Init(); - delegate_view_->AddChildView(launcher_view_); - params.delegate = delegate_view_; - widget_->Init(params); - widget_->GetNativeWindow()->SetName("LauncherWindow"); - // The launcher should not take focus when it is initially shown. - widget_->set_focus_on_creation(false); - widget_->SetContentsView(delegate_view_); - widget_->GetNativeView()->SetName("LauncherView"); - widget_->GetNativeView()->SetProperty(internal::kStayInSameRootWindowKey, - true); - - // SetBounds() has to be called after kStayInSameRootWindowKey is set. - gfx::Size pref = - static_cast(launcher_view_)->GetPreferredSize(); - widget_->SetBounds(gfx::Rect(pref)); - - widget_->AddObserver(this); + shelf_widget_->GetContentsView()->AddChildView(launcher_view_); + shelf_widget_->GetNativeView()->SetName("LauncherView"); + shelf_widget_->GetNativeView()->SetProperty( + internal::kStayInSameRootWindowKey, true); } Launcher::~Launcher() { - widget_->RemoveObserver(this); } // static Launcher* Launcher::ForPrimaryDisplay() { return internal::RootWindowController::ForLauncher( - Shell::GetPrimaryRootWindow())->launcher(); + Shell::GetPrimaryRootWindow())->shelf()->launcher(); } // static Launcher* Launcher::ForWindow(aura::Window* window) { - return internal::RootWindowController::ForLauncher(window)->launcher(); -} - -void Launcher::SetFocusCycler(internal::FocusCycler* focus_cycler) { - delegate_view_->set_focus_cycler(focus_cycler); - if (focus_cycler) - focus_cycler->AddWidget(widget_.get()); -} - -internal::FocusCycler* Launcher::GetFocusCycler() { - return delegate_view_->focus_cycler(); + return internal::RootWindowController::ForLauncher(window)-> + shelf()->launcher(); } void Launcher::SetAlignment(ShelfAlignment alignment) { alignment_ = alignment; - delegate_view_->SchedulePaint(); launcher_view_->OnShelfAlignmentChanged(); // ShelfLayoutManager will resize the launcher. } -void Launcher::SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type) { - background_animator_.SetPaintsBackground(value, change_type); -} - -void Launcher::SetDimsShelf(bool value) { - if (value == (dimmer_.get() != NULL)) - return; - - if (!value) { - dimmer_.reset(); - return; - } - - dimmer_.reset(new views::Widget); - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.transparent = true; - params.can_activate = false; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = Shell::GetContainer( - window_container_->GetRootWindow(), - ash::internal::kShellWindowId_LauncherContainer); - params.accept_events = false; - dimmer_->Init(params); - dimmer_->GetNativeWindow()->SetName("LauncherDimmer"); - dimmer_->SetBounds(widget_->GetWindowBoundsInScreen()); - // The launcher should not take focus when it is initially shown. - dimmer_->set_focus_on_creation(false); - dimmer_->SetContentsView(new DimmerView(this)); - dimmer_->GetNativeView()->SetName("LauncherDimmerView"); - dimmer_->GetNativeView()->SetProperty(internal::kStayInSameRootWindowKey, - true); - dimmer_->Show(); -} - -bool Launcher::GetDimsShelf() const { - return dimmer_.get() && dimmer_->IsVisible(); -} - -void Launcher::SetStatusSize(const gfx::Size& size) { - if (status_size_ == size) - return; - - status_size_ = size; - delegate_view_->Layout(); -} - gfx::Rect Launcher::GetScreenBoundsOfItemIconForWindow(aura::Window* window) { LauncherID id = delegate_->GetIDByWindow(window); gfx::Rect bounds(launcher_view_->GetIdealBoundsOfItemIcon(id)); @@ -399,17 +133,15 @@ bool Launcher::IsShowingOverflowBubble() const { } void Launcher::SetVisible(bool visible) const { - delegate_view_->SetVisible(visible); + launcher_view_->SetVisible(visible); } -views::View* Launcher::GetAppListButtonView() const { - return launcher_view_->GetAppListButtonView(); +bool Launcher::IsVisible() const { + return launcher_view_->visible(); } -void Launcher::SetWidgetBounds(const gfx::Rect bounds) { - widget_->SetBounds(bounds); - if (dimmer_.get()) - dimmer_->SetBounds(bounds); +views::View* Launcher::GetAppListButtonView() const { + return launcher_view_->GetAppListButtonView(); } void Launcher::SwitchToWindow(int window_index) { @@ -440,17 +172,16 @@ void Launcher::SwitchToWindow(int window_index) { } } -void Launcher::OnWidgetActivationChanged(views::Widget* widget, bool active) { - activating_as_fallback_ = false; - if (active) { - delegate_view_->SetPaneFocusAndFocusDefault(); - } else { - delegate_view_->GetFocusManager()->ClearFocus(); - } -} - internal::LauncherView* Launcher::GetLauncherViewForTest() { return launcher_view_; } +void Launcher::SetLauncherViewBounds(gfx::Rect bounds) { + launcher_view_->SetBoundsRect(bounds); +} + +gfx::Rect Launcher::GetLauncherViewBounds() const { + return launcher_view_->bounds(); +} + } // namespace ash diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h index 79389b0..a90f23a 100644 --- a/ash/launcher/launcher.h +++ b/ash/launcher/launcher.h @@ -6,9 +6,8 @@ #define ASH_LAUNCHER_LAUNCHER_H_ #include "ash/ash_export.h" -#include "ash/launcher/background_animator.h" #include "ash/launcher/launcher_types.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "ui/gfx/size.h" @@ -24,7 +23,6 @@ class Rect; namespace views { class View; -class Widget; } namespace ash { @@ -38,13 +36,13 @@ class ShelfLayoutManager; class LauncherIconObserver; class LauncherDelegate; class LauncherModel; +class ShelfWidget; -class ASH_EXPORT Launcher: public views::WidgetObserver { +class ASH_EXPORT Launcher { public: Launcher(LauncherModel* launcher_model, LauncherDelegate* launcher_delegate, - aura::Window* window_container, - internal::ShelfLayoutManager* shelf_layout_manager); + ShelfWidget* shelf_widget); virtual ~Launcher(); // Return the launcher for the primary display. NULL if no user is @@ -56,30 +54,9 @@ class ASH_EXPORT Launcher: public views::WidgetObserver { // is disabled. NULL if no user is logged in yet. static Launcher* ForWindow(aura::Window* window); - // Sets the focus cycler. Also adds the launcher to the cycle. - void SetFocusCycler(internal::FocusCycler* focus_cycler); - internal::FocusCycler* GetFocusCycler(); - void SetAlignment(ShelfAlignment alignment); ShelfAlignment alignment() const { return alignment_; } - // Sets whether the launcher paints a background. Default is false, but is set - // to true if a window overlaps the shelf. - void SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type); - bool paints_background() const { - return background_animator_.paints_background(); - } - - // Causes shelf items to be slightly dimmed. - void SetDimsShelf(bool value); - bool GetDimsShelf() const; - - // Sets the size of the status area. - void SetStatusSize(const gfx::Size& size); - const gfx::Size& status_size() const { return status_size_; } - // Returns the screen bounds of the item for the specified window. If there is // no item for the specified window an empty rect is returned. gfx::Rect GetScreenBoundsOfItemIconForWindow(aura::Window* window); @@ -103,12 +80,10 @@ class ASH_EXPORT Launcher: public views::WidgetObserver { bool IsShowingOverflowBubble() const; void SetVisible(bool visible) const; + bool IsVisible() const; views::View* GetAppListButtonView() const; - // Sets the bounds of the launcher widget, and the dimmer if visible. - void SetWidgetBounds(const gfx::Rect bounds); - // Switches to a 0-indexed (in order of creation) window. // A negative index switches to the last window in the list. void SwitchToWindow(int window_index); @@ -119,33 +94,13 @@ class ASH_EXPORT Launcher: public views::WidgetObserver { LauncherDelegate* delegate() { return delegate_; } - views::Widget* widget() { return widget_.get(); } - - views::Widget* GetDimmerWidgetForTest() { return dimmer_.get(); } - - aura::Window* window_container() { return window_container_; } + ShelfWidget* shelf_widget() { return shelf_widget_; } - // Called by the activation delegate, before the launcher is activated - // when no other windows are visible. - void WillActivateAsFallback() { activating_as_fallback_ = true; } - - // Overridden from views::WidgetObserver: - virtual void OnWidgetActivationChanged( - views::Widget* widget, bool active) OVERRIDE; + // Set the bounds of the launcher view. + void SetLauncherViewBounds(gfx::Rect bounds); + gfx::Rect GetLauncherViewBounds() const; private: - class DelegateView; - class DimmerView; - - // Widget hosting the view. - scoped_ptr widget_; - scoped_ptr dimmer_; - - aura::Window* window_container_; - - // Contents view of the widget. Houses the LauncherView. - DelegateView* delegate_view_; - // LauncherView used to display icons. internal::LauncherView* launcher_view_; @@ -153,14 +108,7 @@ class ASH_EXPORT Launcher: public views::WidgetObserver { LauncherDelegate* delegate_; - // Size reserved for the status area. - gfx::Size status_size_; - - // Used to animate the background. - internal::BackgroundAnimator background_animator_; - - // Used then activation is forced from the activation delegate. - bool activating_as_fallback_; + ShelfWidget* shelf_widget_; DISALLOW_COPY_AND_ASSIGN(Launcher); }; diff --git a/ash/launcher/launcher_alignment_menu.cc b/ash/launcher/launcher_alignment_menu.cc index 32b50d1..4648272 100644 --- a/ash/launcher/launcher_alignment_menu.cc +++ b/ash/launcher/launcher_alignment_menu.cc @@ -4,9 +4,9 @@ #include "ash/launcher/launcher_alignment_menu.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" #include "ash/shell.h" -#include "ash/wm/shelf_layout_manager.h" #include "grit/ash_strings.h" #include "ui/aura/root_window.h" #include "ui/base/l10n/l10n_util.h" diff --git a/ash/launcher/launcher_button.cc b/ash/launcher/launcher_button.cc index 2abc608..25b7a54 100644 --- a/ash/launcher/launcher_button.cc +++ b/ash/launcher/launcher_button.cc @@ -7,7 +7,7 @@ #include #include "ash/launcher/launcher_button_host.h" -#include "ash/wm/shelf_layout_manager.h" +#include "ash/shelf/shelf_layout_manager.h" #include "grit/ash_resources.h" #include "skia/ext/image_operations.h" #include "ui/base/accessibility/accessible_view_state.h" diff --git a/ash/launcher/launcher_tooltip_manager.cc b/ash/launcher/launcher_tooltip_manager.cc index 5d5e230..b1dca2e 100644 --- a/ash/launcher/launcher_tooltip_manager.cc +++ b/ash/launcher/launcher_tooltip_manager.cc @@ -5,9 +5,9 @@ #include "ash/launcher/launcher_tooltip_manager.h" #include "ash/launcher/launcher_view.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "base/bind.h" #include "base/message_loop.h" diff --git a/ash/launcher/launcher_tooltip_manager.h b/ash/launcher/launcher_tooltip_manager.h index edd48bb..c2418f5 100644 --- a/ash/launcher/launcher_tooltip_manager.h +++ b/ash/launcher/launcher_tooltip_manager.h @@ -6,8 +6,8 @@ #define ASH_LAUNCHER_LAUNCHER_TOOLTIP_MANAGER_H_ #include "ash/ash_export.h" -#include "ash/shelf_types.h" -#include "ash/wm/shelf_layout_manager.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" #include "base/basictypes.h" #include "base/string16.h" #include "ui/base/events/event_handler.h" diff --git a/ash/launcher/launcher_tooltip_manager_unittest.cc b/ash/launcher/launcher_tooltip_manager_unittest.cc index a4b50cd..0cdd3734 100644 --- a/ash/launcher/launcher_tooltip_manager_unittest.cc +++ b/ash/launcher/launcher_tooltip_manager_unittest.cc @@ -5,10 +5,11 @@ #include "ash/launcher/launcher_tooltip_manager.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_util.h" #include "base/string16.h" #include "base/time.h" @@ -42,8 +43,8 @@ class LauncherTooltipManagerTest : public AshTestBase { internal::RootWindowController* controller = Shell::GetPrimaryRootWindowController(); tooltip_manager_.reset(new internal::LauncherTooltipManager( - controller->shelf(), - controller->launcher()->GetLauncherViewForTest())); + controller->GetShelfLayoutManager(), + controller->shelf()->launcher()->GetLauncherViewForTest())); } virtual void TearDown() OVERRIDE { @@ -93,7 +94,7 @@ class LauncherTooltipManagerTest : public AshTestBase { params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.parent = Shell::GetContainer( Shell::GetPrimaryRootWindow(), - ash::internal::kShellWindowId_LauncherContainer); + ash::internal::kShellWindowId_ShelfContainer); widget_->Init(params); widget_->SetContentsView(dummy_anchor_.get()); @@ -129,7 +130,8 @@ TEST_F(LauncherTooltipManagerTest, HideWhenShelfIsHidden) { // Once the shelf is hidden, the tooltip should be invisible. ASSERT_EQ( SHELF_HIDDEN, - Shell::GetPrimaryRootWindowController()->shelf()->visibility_state()); + Shell::GetPrimaryRootWindowController()-> + GetShelfLayoutManager()->visibility_state()); EXPECT_FALSE(TooltipIsVisible()); // Do not show the view if the shelf is hidden. @@ -154,7 +156,7 @@ TEST_F(LauncherTooltipManagerTest, HideWhenShelfIsAutoHide) { ASSERT_TRUE(TooltipIsVisible()); internal::ShelfLayoutManager* shelf = - Shell::GetPrimaryRootWindowController()->shelf(); + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); shelf->UpdateAutoHideState(); ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); diff --git a/ash/launcher/launcher_unittest.cc b/ash/launcher/launcher_unittest.cc index f16aae6..d4085ba 100644 --- a/ash/launcher/launcher_unittest.cc +++ b/ash/launcher/launcher_unittest.cc @@ -7,6 +7,7 @@ #include "ash/launcher/launcher_model.h" #include "ash/launcher/launcher_view.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/launcher_view_test_api.h" @@ -28,38 +29,6 @@ using ash::internal::LauncherButton; namespace ash { -// Makes sure invoking SetStatusSize on the launcher changes the size of the -// LauncherView. -TEST_F(LauncherTest, SetStatusSize) { - Launcher* launcher = Launcher::ForPrimaryDisplay(); - LauncherView* launcher_view = launcher->GetLauncherViewForTest(); - - gfx::Size launcher_size = - launcher->widget()->GetWindowBoundsInScreen().size(); - int total_width = launcher_size.width(); - ASSERT_GT(total_width, 0); - launcher->SetStatusSize(gfx::Size(total_width / 2, launcher_size.height())); - EXPECT_EQ(total_width - total_width / 2, launcher_view->width()); -} - -// Tests that the dimmer widget resizes itself as appropriate. -TEST_F(LauncherTest, DimmerSize) { - Launcher* launcher = Launcher::ForPrimaryDisplay(); - launcher->SetDimsShelf(true); - - gfx::Size launcher_size = - launcher->widget()->GetWindowBoundsInScreen().size(); - EXPECT_EQ( - launcher->widget()->GetWindowBoundsInScreen().ToString(), - launcher->GetDimmerWidgetForTest()->GetWindowBoundsInScreen().ToString()); - - launcher->widget()->SetSize( - gfx::Size(launcher_size.width() / 2, launcher_size.height() + 10)); - EXPECT_EQ( - launcher->widget()->GetWindowBoundsInScreen().ToString(), - launcher->GetDimmerWidgetForTest()->GetWindowBoundsInScreen().ToString()); -} - // Confirm that launching a browser gets the appropriate state reflected in // its button. TEST_F(LauncherTest, OpenBrowser) { @@ -120,95 +89,4 @@ TEST_F(LauncherTest, ShowOverflowBubble) { EXPECT_FALSE(launcher->IsShowingOverflowBubble()); } -// Launcher can't be activated on mouse click, but it is activable from -// the focus cycler or as fallback. -TEST_F(LauncherTest, ActivateAsFallback) { - // TODO(mtomasz): make this test work with the FocusController. - if (views::corewm::UseFocusController()) - return; - - Launcher* launcher = Launcher::ForPrimaryDisplay(); - views::Widget* launcher_widget = launcher->widget(); - EXPECT_FALSE(launcher_widget->CanActivate()); - - launcher->WillActivateAsFallback(); - EXPECT_TRUE(launcher_widget->CanActivate()); - - wm::ActivateWindow(launcher_widget->GetNativeWindow()); - EXPECT_FALSE(launcher_widget->CanActivate()); -} - -void TestLauncherAlignment(aura::RootWindow* root, - ShelfAlignment alignment, - const std::string& expected) { - Shell::GetInstance()->SetShelfAlignment(alignment, root); - gfx::Screen* screen = gfx::Screen::GetScreenFor(root); - EXPECT_EQ(expected, - screen->GetDisplayNearestWindow(root).work_area().ToString()); -} - -TEST_F(LauncherTest, TestAlignment) { - Launcher* launcher = Launcher::ForPrimaryDisplay(); - UpdateDisplay("400x400"); - ASSERT_TRUE(launcher); - { - SCOPED_TRACE("Single Bottom"); - TestLauncherAlignment(Shell::GetPrimaryRootWindow(), - SHELF_ALIGNMENT_BOTTOM, - "0,0 400x352"); - } - { - SCOPED_TRACE("Single Right"); - TestLauncherAlignment(Shell::GetPrimaryRootWindow(), - SHELF_ALIGNMENT_RIGHT, - "0,0 348x400"); - } - { - SCOPED_TRACE("Single Left"); - TestLauncherAlignment(Shell::GetPrimaryRootWindow(), - SHELF_ALIGNMENT_LEFT, - "52,0 348x400"); - } - UpdateDisplay("300x300,500x500"); - Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); - { - SCOPED_TRACE("Primary Bottom"); - TestLauncherAlignment(root_windows[0], - SHELF_ALIGNMENT_BOTTOM, - "0,0 300x252"); - } - { - SCOPED_TRACE("Primary Right"); - TestLauncherAlignment(root_windows[0], - SHELF_ALIGNMENT_RIGHT, - "0,0 248x300"); - } - { - SCOPED_TRACE("Primary Left"); - TestLauncherAlignment(root_windows[0], - SHELF_ALIGNMENT_LEFT, - "52,0 248x300"); - } - if (Shell::IsLauncherPerDisplayEnabled()) { - { - SCOPED_TRACE("Secondary Bottom"); - TestLauncherAlignment(root_windows[1], - SHELF_ALIGNMENT_BOTTOM, - "300,0 500x452"); - } - { - SCOPED_TRACE("Secondary Right"); - TestLauncherAlignment(root_windows[1], - SHELF_ALIGNMENT_RIGHT, - "300,0 448x500"); - } - { - SCOPED_TRACE("Secondary Left"); - TestLauncherAlignment(root_windows[1], - SHELF_ALIGNMENT_LEFT, - "352,0 448x500"); - } - } -} - } // namespace ash diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc index 44adc22..635617b 100644 --- a/ash/launcher/launcher_view.cc +++ b/ash/launcher/launcher_view.cc @@ -18,8 +18,9 @@ #include "ash/launcher/overflow_button.h" #include "ash/launcher/tabbed_launcher_button.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell_delegate.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/auto_reset.h" #include "base/memory/scoped_ptr.h" #include "grit/ash_resources.h" diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h index 784698e..d32c408 100644 --- a/ash/launcher/launcher_view.h +++ b/ash/launcher/launcher_view.h @@ -10,7 +10,6 @@ #include "ash/launcher/launcher_button_host.h" #include "ash/launcher/launcher_model_observer.h" -#include "ash/shelf_types.h" #include "ash/wm/gestures/shelf_gesture_handler.h" #include "base/observer_list.h" #include "ui/views/animation/bounds_animator_observer.h" diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc index 0614f7a..cf4ca53 100644 --- a/ash/launcher/launcher_view_unittest.cc +++ b/ash/launcher/launcher_view_unittest.cc @@ -13,6 +13,7 @@ #include "ash/launcher/launcher_model.h" #include "ash/launcher/launcher_tooltip_manager.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" @@ -174,12 +175,13 @@ TEST_F(LauncherViewIconObserverTest, MAYBE_AddRemoveWithMultipleDisplays) { } TEST_F(LauncherViewIconObserverTest, BoundsChanged) { + ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf(); Launcher* launcher = Launcher::ForPrimaryDisplay(); - gfx::Size launcher_size = - launcher->widget()->GetWindowBoundsInScreen().size(); - int total_width = launcher_size.width() / 2; - ASSERT_GT(total_width, 0); - launcher->SetStatusSize(gfx::Size(total_width, launcher_size.height())); + gfx::Size shelf_size = + shelf->GetWindowBoundsInScreen().size(); + shelf_size.set_width(shelf_size.width() / 2); + ASSERT_GT(shelf_size.width(), 0); + launcher->SetLauncherViewBounds(gfx::Rect(shelf_size)); // No animation happens for LauncherView bounds change. EXPECT_TRUE(observer()->change_notified()); observer()->Reset(); diff --git a/ash/launcher/overflow_bubble.cc b/ash/launcher/overflow_bubble.cc index 601090e..1fa7255 100644 --- a/ash/launcher/overflow_bubble.cc +++ b/ash/launcher/overflow_bubble.cc @@ -9,9 +9,9 @@ #include "ash/launcher/launcher_types.h" #include "ash/launcher/launcher_view.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/system/tray/system_tray.h" -#include "ash/wm/shelf_layout_manager.h" #include "ui/aura/root_window.h" #include "ui/gfx/insets.h" #include "ui/gfx/screen.h" diff --git a/ash/launcher/overflow_button.cc b/ash/launcher/overflow_button.cc index 7f1e581..1a4ad3a 100644 --- a/ash/launcher/overflow_button.cc +++ b/ash/launcher/overflow_button.cc @@ -4,7 +4,7 @@ #include "ash/launcher/overflow_button.h" -#include "ash/wm/shelf_layout_manager.h" +#include "ash/shelf/shelf_layout_manager.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "third_party/skia/include/core/SkPaint.h" diff --git a/ash/launcher/overflow_button.h b/ash/launcher/overflow_button.h index 69cc795..b1d2db1 100644 --- a/ash/launcher/overflow_button.h +++ b/ash/launcher/overflow_button.h @@ -5,7 +5,7 @@ #ifndef ASH_LAUNCHER_OVERFLOW_BUTTON_H_ #define ASH_LAUNCHER_OVERFLOW_BUTTON_H_ -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ui/views/controls/button/custom_button.h" diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 1fa22c2..f216c7a 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc @@ -12,7 +12,9 @@ #include "ash/display/display_controller.h" #include "ash/display/display_manager.h" #include "ash/focus_cycler.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_factory.h" @@ -25,7 +27,6 @@ #include "ash/wm/property_util.h" #include "ash/wm/root_window_layout_manager.h" #include "ash/wm/screen_dimmer.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/stacking_controller.h" #include "ash/wm/status_area_layout_manager.h" #include "ash/wm/system_background_controller.h" @@ -165,7 +166,6 @@ namespace internal { RootWindowController::RootWindowController(aura::RootWindow* root_window) : root_window_(root_window), root_window_layout_(NULL), - status_area_widget_(NULL), shelf_(NULL), panel_layout_manager_(NULL) { SetRootWindowController(root_window, this); @@ -216,13 +216,6 @@ void RootWindowController::Shutdown() { root_window_->PrepareForShutdown(); system_background_.reset(); - - // Launcher widget has an InputMethodBridge that references to - // |input_method_filter_|'s |input_method_|. So explicitly release - // |launcher_| before |input_method_filter_|. And this needs to be - // after we delete all containers in case there are still live - // browser windows which access LauncherModel during close. - launcher_.reset(); } SystemModalContainerLayoutManager* @@ -272,34 +265,14 @@ void RootWindowController::InitLayoutManagers() { } void RootWindowController::InitForPrimaryDisplay() { - DCHECK(!status_area_widget_); + DCHECK(!shelf_.get()); + aura::Window* shelf_container = + GetContainer(ash::internal::kShellWindowId_ShelfContainer); + // TODO(harrym): Remove when status area is view. aura::Window* status_container = GetContainer(ash::internal::kShellWindowId_StatusContainer); - // Initialize Primary RootWindow specific items. - status_area_widget_ = new internal::StatusAreaWidget(status_container); - status_area_widget_->CreateTrayViews(); - // Login screen manages status area visibility by itself. - ShellDelegate* shell_delegate = Shell::GetInstance()->delegate(); - if (shell_delegate->IsSessionStarted()) - status_area_widget_->Show(); - - Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_); - - internal::ShelfLayoutManager* shelf_layout_manager = - new internal::ShelfLayoutManager(status_area_widget_); - GetContainer(internal::kShellWindowId_LauncherContainer)-> - SetLayoutManager(shelf_layout_manager); - shelf_ = shelf_layout_manager; - - internal::StatusAreaLayoutManager* status_area_layout_manager = - new internal::StatusAreaLayoutManager(shelf_layout_manager); - GetContainer(internal::kShellWindowId_StatusContainer)-> - SetLayoutManager(status_area_layout_manager); - - shelf_layout_manager->set_workspace_controller( - workspace_controller()); - - workspace_controller()->SetShelf(shelf_); + shelf_.reset(new ash::ShelfWidget( + shelf_container, status_container, workspace_controller())); if (Shell::IsLauncherPerDisplayEnabled() || root_window_ == Shell::GetPrimaryRootWindow()) { @@ -312,9 +285,8 @@ void RootWindowController::InitForPrimaryDisplay() { new ToplevelWindowEventHandler(panel_container)); panel_container->SetLayoutManager(panel_layout_manager_); } - - if (shell_delegate->IsUserLoggedIn()) - CreateLauncher(); + if (Shell::GetInstance()->delegate()->IsUserLoggedIn()) + shelf_->CreateLauncher(); } void RootWindowController::CreateContainers() { @@ -343,50 +315,29 @@ void RootWindowController::CreateSystemBackground( #endif } -void RootWindowController::CreateLauncher() { - if (launcher_.get()) - return; - - aura::Window* default_container = - GetContainer(internal::kShellWindowId_DefaultContainer); - // Get the delegate first to make sure the launcher model is created. - LauncherDelegate* launcher_delegate = - Shell::GetInstance()->GetLauncherDelegate(); - launcher_.reset(new Launcher(Shell::GetInstance()->launcher_model(), - launcher_delegate, - default_container, - shelf_)); - - launcher_->SetFocusCycler(Shell::GetInstance()->focus_cycler()); - shelf_->SetLauncher(launcher_.get()); - +void RootWindowController::OnLauncherCreated() { if (panel_layout_manager_) - panel_layout_manager_->SetLauncher(launcher_.get()); - - ShellDelegate* delegate = Shell::GetInstance()->delegate(); - if (delegate) - launcher_->SetVisible(delegate->IsSessionStarted()); - launcher_->widget()->Show(); + panel_layout_manager_->SetLauncher(shelf_->launcher()); } void RootWindowController::ShowLauncher() { - if (!launcher_.get()) + if (!shelf_.get() || !shelf_->launcher()) return; - launcher_->SetVisible(true); - status_area_widget_->Show(); + shelf_->launcher()->SetVisible(true); + shelf_->status_area_widget()->Show(); } void RootWindowController::OnLoginStateChanged(user::LoginStatus status) { // TODO(oshima): remove if when launcher per display is enabled by // default. - if (shelf_) - shelf_->UpdateVisibilityState(); + if (shelf_.get()) + shelf_->shelf_layout_manager()->UpdateVisibilityState(); } void RootWindowController::UpdateAfterLoginStatusChange( user::LoginStatus status) { - if (status_area_widget_) - status_area_widget_->UpdateAfterLoginStatusChange(status); + if (shelf_.get() && shelf_->status_area_widget()) + shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status); } void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() { @@ -406,21 +357,18 @@ void RootWindowController::HandleDesktopBackgroundVisible() { } void RootWindowController::CloseChildWindows() { - // The status area needs to be shut down before the windows are destroyed. - if (status_area_widget_) { - status_area_widget_->Shutdown(); - status_area_widget_ = NULL; - } - // panel_layout_manager_ needs to be shut down before windows are destroyed. if (panel_layout_manager_) { panel_layout_manager_->Shutdown(); panel_layout_manager_ = NULL; } - // Closing the windows frees the workspace controller. - if (shelf_) - shelf_->set_workspace_controller(NULL); + // TODO(harrym): Remove when Status Area Widget is a child view. + if (shelf_.get()) + shelf_->ShutdownStatusAreaWidget(); + + if (shelf_.get() && shelf_->shelf_layout_manager()) + shelf_->shelf_layout_manager()->set_workspace_controller(NULL); // Close background widget first as it depends on tooltip. root_window_->SetProperty(kDesktopController, @@ -435,9 +383,8 @@ void RootWindowController::CloseChildWindows() { aura::Window* child = root_window_->children()[0]; delete child; } - launcher_.reset(); - // All containers are deleted, so reset shelf_. - shelf_ = NULL; + + shelf_.reset(NULL); } void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) { @@ -475,12 +422,15 @@ void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) { } } +ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() { + return shelf_.get() ? shelf_->shelf_layout_manager() : NULL; +} + SystemTray* RootWindowController::GetSystemTray() { // We assume in throughout the code that this will not return NULL. If code // triggers this for valid reasons, it should test status_area_widget first. - internal::StatusAreaWidget* status_area = status_area_widget(); - CHECK(status_area); - return status_area->system_tray(); + CHECK(shelf_.get() && shelf_->status_area_widget()); + return shelf_->status_area_widget()->system_tray(); } void RootWindowController::ShowContextMenu( @@ -508,24 +458,7 @@ void RootWindowController::ShowContextMenu( } void RootWindowController::UpdateShelfVisibility() { - shelf_->UpdateVisibilityState(); -} - -void RootWindowController::SetShelfAutoHideBehavior( - ShelfAutoHideBehavior behavior) { - shelf_->SetAutoHideBehavior(behavior); -} - -ShelfAutoHideBehavior RootWindowController::GetShelfAutoHideBehavior() const { - return shelf_->auto_hide_behavior(); -} - -bool RootWindowController::SetShelfAlignment(ShelfAlignment alignment) { - return shelf_->SetAlignment(alignment); -} - -ShelfAlignment RootWindowController::GetShelfAlignment() { - return shelf_->GetAlignment(); + shelf_->shelf_layout_manager()->UpdateVisibilityState(); } bool RootWindowController::IsImmersiveMode() const { @@ -609,7 +542,7 @@ void RootWindowController::CreateContainersInRootWindow( SetUsesScreenCoordinates(panel_container); aura::Window* launcher_container = - CreateContainer(kShellWindowId_LauncherContainer, + CreateContainer(kShellWindowId_ShelfContainer, "LauncherContainer", non_lock_screen_containers); SetUsesScreenCoordinates(launcher_container); diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h index 83865c0..d10c6b1 100644 --- a/ash/root_window_controller.h +++ b/ash/root_window_controller.h @@ -6,7 +6,7 @@ #define ASH_ROOT_WINDOW_CONTROLLER_H_ #include "ash/ash_export.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/user/login_status.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" @@ -31,8 +31,8 @@ class RootWindowEventFilter; } namespace ash { -class Launcher; class StackingController; +class ShelfWidget; class SystemTray; class ToplevelWindowEventHandler; @@ -80,13 +80,13 @@ class ASH_EXPORT RootWindowController { ScreenDimmer* screen_dimmer() { return screen_dimmer_.get(); } - Launcher* launcher() { return launcher_.get(); } + // Access the shelf associated with this root window controller, + // NULL if no such shelf exists. + ShelfWidget* shelf() { return shelf_.get(); } - ShelfLayoutManager* shelf() const { return shelf_; } - - StatusAreaWidget* status_area_widget() { - return status_area_widget_; - } + // Access the shelf layout manager associated with this root + // window controller, NULL if no such shelf exists. + ShelfLayoutManager* GetShelfLayoutManager(); // Returns the system tray on this root window. Note that // calling this on the root window that doesn't have a launcher will @@ -120,12 +120,12 @@ class ASH_EXPORT RootWindowController { // |is_first_run_after_boot| determines the background's initial color. void CreateSystemBackground(bool is_first_run_after_boot); - // Initializes |launcher_|. Does nothing if it's already initialized. - void CreateLauncher(); - // Show launcher view if it was created hidden (before session has started). void ShowLauncher(); + // Called when the launcher associated with this root window is created. + void OnLauncherCreated(); + // Called when the user logs in. void OnLoginStateChanged(user::LoginStatus status); @@ -157,14 +157,6 @@ class ASH_EXPORT RootWindowController { // Force the shelf to query for it's current visibility state. void UpdateShelfVisibility(); - // Sets/gets the shelf auto-hide behavior. - void SetShelfAutoHideBehavior(ShelfAutoHideBehavior behavior); - ShelfAutoHideBehavior GetShelfAutoHideBehavior() const; - - // Sets/gets the shelf alignemnt. - bool SetShelfAlignment(ShelfAlignment alignment); - ShelfAlignment GetShelfAlignment(); - // Returns true if the active workspace is in immersive mode. Exposed here // so clients of Ash don't need to know the details of workspace management. bool IsImmersiveMode() const; @@ -179,19 +171,12 @@ class ASH_EXPORT RootWindowController { scoped_ptr stacking_controller_; - // Widget containing system tray. - StatusAreaWidget* status_area_widget_; - // The shelf for managing the launcher and the status widget. - // RootWindowController does not own the shelf. Instead, it is owned - // by container of the status area. - ShelfLayoutManager* shelf_; + scoped_ptr shelf_; // Manages layout of panels. Owned by PanelContainer. PanelLayoutManager* panel_layout_manager_; - scoped_ptr launcher_; - scoped_ptr system_background_; scoped_ptr boot_splash_screen_; diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc index 6aef751f..55f0763 100644 --- a/ash/root_window_controller_unittest.cc +++ b/ash/root_window_controller_unittest.cc @@ -5,6 +5,7 @@ #include "ash/root_window_controller.h" #include "ash/display/display_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" @@ -129,7 +130,10 @@ TEST_F(RootWindowControllerTest, MAYBE_MoveWindows_Basic) { Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); internal::RootWindowController* controller = Shell::GetPrimaryRootWindowController(); - controller->SetShelfAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + internal::ShelfLayoutManager* shelf_layout_manager = + controller->GetShelfLayoutManager(); + shelf_layout_manager->SetAutoHideBehavior( + ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100)); EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow()); diff --git a/ash/screen_ash.cc b/ash/screen_ash.cc index 4635ed6..aabd5b6 100644 --- a/ash/screen_ash.cc +++ b/ash/screen_ash.cc @@ -7,10 +7,11 @@ #include "ash/display/display_controller.h" #include "ash/display/display_manager.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/wm/property_util.h" #include "ash/wm/coordinate_conversion.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/logging.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" @@ -39,7 +40,7 @@ gfx::Display ScreenAsh::FindDisplayContainingPoint(const gfx::Point& point) { // static gfx::Rect ScreenAsh::GetMaximizedWindowBoundsInParent(aura::Window* window) { - if (GetRootWindowController(window->GetRootWindow())->launcher()) + if (GetRootWindowController(window->GetRootWindow())->shelf()->launcher()) return GetDisplayWorkAreaBoundsInParent(window); else return GetDisplayBoundsInParent(window); diff --git a/ash/screen_ash_unittest.cc b/ash/screen_ash_unittest.cc index cdc854a..b00eb54 100644 --- a/ash/screen_ash_unittest.cc +++ b/ash/screen_ash_unittest.cc @@ -6,6 +6,8 @@ #include "ash/display/display_controller.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_util.h" @@ -22,8 +24,8 @@ typedef test::AshTestBase ScreenAshTest; TEST_F(ScreenAshTest, Bounds) { UpdateDisplay("600x600,500x500"); - Shell::GetPrimaryRootWindowController()->SetShelfAutoHideBehavior( - ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> + SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); views::Widget* primary = views::Widget::CreateWindowWithContextAndBounds( NULL, CurrentContext(), gfx::Rect(10, 10, 100, 100)); diff --git a/ash/shelf/background_animator.cc b/ash/shelf/background_animator.cc new file mode 100644 index 0000000..7b968c8 --- /dev/null +++ b/ash/shelf/background_animator.cc @@ -0,0 +1,57 @@ +// 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/background_animator.h" + + +namespace ash { +namespace internal { + +namespace { + +// Duration of the background animation. +const int kBackgroundDurationMS = 1000; + +} + +BackgroundAnimator::BackgroundAnimator(BackgroundAnimatorDelegate* delegate, + int min_alpha, + int max_alpha) + : delegate_(delegate), + min_alpha_(min_alpha), + max_alpha_(max_alpha), + ALLOW_THIS_IN_INITIALIZER_LIST(animation_(this)), + paints_background_(false), + alpha_(min_alpha) { + animation_.SetSlideDuration(kBackgroundDurationMS); +} + +BackgroundAnimator::~BackgroundAnimator() { +} + +void BackgroundAnimator::SetPaintsBackground(bool value, ChangeType type) { + if (paints_background_ == value) + return; + paints_background_ = value; + if (type == CHANGE_IMMEDIATE && !animation_.is_animating()) { + animation_.Reset(value ? 1.0f : 0.0f); + AnimationProgressed(&animation_); + return; + } + if (paints_background_) + animation_.Show(); + else + animation_.Hide(); +} + +void BackgroundAnimator::AnimationProgressed(const ui::Animation* animation) { + int alpha = animation->CurrentValueBetween(min_alpha_, max_alpha_); + if (alpha_ == alpha) + return; + alpha_ = alpha; + delegate_->UpdateBackground(alpha_); +} + +} // namespace internal +} // namespace ash diff --git a/ash/shelf/background_animator.h b/ash/shelf/background_animator.h new file mode 100644 index 0000000..7e87fd7 --- /dev/null +++ b/ash/shelf/background_animator.h @@ -0,0 +1,71 @@ +// 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. + +#ifndef ASH_SHELF_BACKGROUND_ANIMATOR_H_ +#define ASH_SHELF_BACKGROUND_ANIMATOR_H_ + +#include "ash/ash_export.h" +#include "base/basictypes.h" +#include "ui/base/animation/animation_delegate.h" +#include "ui/base/animation/slide_animation.h" + +namespace ash { +namespace internal { + +// Delegate is notified any time the background changes. +class ASH_EXPORT BackgroundAnimatorDelegate { + public: + virtual void UpdateBackground(int alpha) = 0; + + protected: + virtual ~BackgroundAnimatorDelegate() {} +}; + +// BackgroundAnimator is used by the shelf to animate the background (alpha). +class ASH_EXPORT BackgroundAnimator : public ui::AnimationDelegate { + public: + // How the background can be changed. + enum ChangeType { + CHANGE_ANIMATE, + CHANGE_IMMEDIATE + }; + + BackgroundAnimator(BackgroundAnimatorDelegate* delegate, + int min_alpha, + int max_alpha); + virtual ~BackgroundAnimator(); + + // Sets whether a background is rendered. Initial value is false. If |type| + // is |CHANGE_IMMEDIATE| and an animation is not in progress this notifies + // the delegate immediately (synchronously from this method). + void SetPaintsBackground(bool value, ChangeType type); + bool paints_background() const { return paints_background_; } + + // Current alpha. + int alpha() const { return alpha_; } + + // ui::AnimationDelegate overrides: + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + + private: + BackgroundAnimatorDelegate* delegate_; + + const int min_alpha_; + const int max_alpha_; + + ui::SlideAnimation animation_; + + // Whether the background is painted. + bool paints_background_; + + // Current alpha value of the background. + int alpha_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundAnimator); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_SHELF_BACKGROUND_ANIMATOR_H_ diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc new file mode 100644 index 0000000..56c50a4 --- /dev/null +++ b/ash/shelf/shelf_layout_manager.cc @@ -0,0 +1,923 @@ +// 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 +#include + +#include "ash/ash_switches.h" +#include "ash/launcher/launcher.h" +#include "ash/launcher/launcher_types.h" +#include "ash/root_window_controller.h" +#include "ash/screen_ash.h" +#include "ash/shelf/shelf_widget.h" +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "ash/shell_window_ids.h" +#include "ash/system/status_area_widget.h" +#include "ash/wm/property_util.h" +#include "ash/wm/window_cycle_controller.h" +#include "ash/wm/window_util.h" +#include "ash/wm/workspace_controller.h" +#include "ash/wm/workspace/workspace_animations.h" +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "base/i18n/rtl.h" +#include "ui/aura/client/activation_client.h" +#include "ui/aura/root_window.h" +#include "ui/base/events/event.h" +#include "ui/base/events/event_handler.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/layer_animation_observer.h" +#include "ui/compositor/layer_animator.h" +#include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/screen.h" +#include "ui/views/widget/widget.h" + +namespace ash { +namespace internal { + +namespace { + +// Delay before showing the launcher. This is after the mouse stops moving. +const int kAutoHideDelayMS = 200; + +// To avoid hiding the shelf when the mouse transitions from a message bubble +// into the shelf, the hit test area is enlarged by this amount of pixels to +// keep the shelf from hiding. +const int kNotificationBubbleGapHeight = 6; + +ui::Layer* GetLayer(views::Widget* widget) { + return widget->GetNativeView()->layer(); +} + +bool IsDraggingTrayEnabled() { + static bool dragging_tray_allowed = CommandLine::ForCurrentProcess()-> + HasSwitch(ash::switches::kAshEnableTrayDragging); + return dragging_tray_allowed; +} + +} // namespace + +// static +const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; + +// static +const int ShelfLayoutManager::kAutoHideSize = 3; + +// ShelfLayoutManager::AutoHideEventFilter ------------------------------------- + +// Notifies ShelfLayoutManager any time the mouse moves. +class ShelfLayoutManager::AutoHideEventFilter : public ui::EventHandler { + public: + explicit AutoHideEventFilter(ShelfLayoutManager* shelf); + virtual ~AutoHideEventFilter(); + + // Returns true if the last mouse event was a mouse drag. + bool in_mouse_drag() const { return in_mouse_drag_; } + + // Overridden from ui::EventHandler: + virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; + + private: + ShelfLayoutManager* shelf_; + bool in_mouse_drag_; + + DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter); +}; + +ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter( + ShelfLayoutManager* shelf) + : shelf_(shelf), + in_mouse_drag_(false) { + Shell::GetInstance()->AddPreTargetHandler(this); +} + +ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() { + Shell::GetInstance()->RemovePreTargetHandler(this); +} + +void ShelfLayoutManager::AutoHideEventFilter::OnMouseEvent( + ui::MouseEvent* event) { + // This also checks IsShelfWindow() to make sure we don't attempt to hide the + // shelf if the mouse down occurs on the shelf. + in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED || + (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED && + event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) && + !shelf_->IsShelfWindow(static_cast(event->target())); + if (event->type() == ui::ET_MOUSE_MOVED) + shelf_->UpdateAutoHideState(); + return; +} + +// ShelfLayoutManager:UpdateShelfObserver -------------------------------------- + +// UpdateShelfObserver is used to delay updating the background until the +// animation completes. +class ShelfLayoutManager::UpdateShelfObserver + : public ui::ImplicitAnimationObserver { + public: + explicit UpdateShelfObserver(ShelfLayoutManager* shelf) : shelf_(shelf) { + shelf_->update_shelf_observer_ = this; + } + + void Detach() { + shelf_ = NULL; + } + + virtual void OnImplicitAnimationsCompleted() OVERRIDE { + if (shelf_) { + shelf_->UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); + } + delete this; + } + + private: + virtual ~UpdateShelfObserver() { + if (shelf_) + shelf_->update_shelf_observer_ = NULL; + } + + // Shelf we're in. NULL if deleted before we're deleted. + ShelfLayoutManager* shelf_; + + DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); +}; + +// ShelfLayoutManager ---------------------------------------------------------- + +ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf) + : root_window_(shelf->GetNativeView()->GetRootWindow()), + in_layout_(false), + auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER), + alignment_(SHELF_ALIGNMENT_BOTTOM), + shelf_(shelf), + workspace_controller_(NULL), + window_overlaps_shelf_(false), + gesture_drag_status_(GESTURE_DRAG_NONE), + gesture_drag_amount_(0.f), + gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), + update_shelf_observer_(NULL) { + Shell::GetInstance()->AddShellObserver(this); + aura::client::GetActivationClient(root_window_)->AddObserver(this); +} + +ShelfLayoutManager::~ShelfLayoutManager() { + if (update_shelf_observer_) + update_shelf_observer_->Detach(); + + FOR_EACH_OBSERVER(Observer, observers_, WillDeleteShelf()); + Shell::GetInstance()->RemoveShellObserver(this); + aura::client::GetActivationClient(root_window_)->RemoveObserver(this); +} + +void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) { + if (auto_hide_behavior_ == behavior) + return; + auto_hide_behavior_ = behavior; + UpdateVisibilityState(); + FOR_EACH_OBSERVER(Observer, observers_, + OnAutoHideStateChanged(state_.auto_hide_state)); +} + +bool ShelfLayoutManager::IsVisible() const { + return shelf_->status_area_widget()->IsVisible() && + (state_.visibility_state == SHELF_VISIBLE || + (state_.visibility_state == SHELF_AUTO_HIDE && + state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)); +} + +bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) { + if (alignment_ == alignment) + return false; + + alignment_ = alignment; + if (shelf_->launcher()) + shelf_->launcher()->SetAlignment(alignment); + shelf_->status_area_widget()->SetShelfAlignment(alignment); + LayoutShelf(); + return true; +} + +gfx::Rect ShelfLayoutManager::GetIdealBounds() { + // TODO(oshima): this is wrong. Figure out what display shelf is on + // and everything should be based on it. + gfx::Rect bounds( + ScreenAsh::GetDisplayBoundsInParent(shelf_->GetNativeView())); + int width = 0, height = 0; + GetShelfSize(&width, &height); + return SelectValueForShelfAlignment( + gfx::Rect(bounds.x(), bounds.bottom() - height, bounds.width(), height), + gfx::Rect(bounds.x(), bounds.y(), width, bounds.height()), + gfx::Rect(bounds.right() - width, bounds.y(), width, bounds.height()), + gfx::Rect(bounds.x(), bounds.y(), bounds.width(), height)); +} + +void ShelfLayoutManager::LayoutShelf() { + base::AutoReset auto_reset_in_layout(&in_layout_, true); + StopAnimating(); + TargetBounds target_bounds; + CalculateTargetBounds(state_, &target_bounds); + GetLayer(shelf_)->SetOpacity(target_bounds.opacity); + shelf_->SetBounds( + ScreenAsh::ConvertRectToScreen( + shelf_->GetNativeView()->parent(), + target_bounds.shelf_bounds_in_root)); + if (shelf_->launcher()) + shelf_->launcher()->SetLauncherViewBounds( + target_bounds.launcher_bounds_in_shelf); + GetLayer(shelf_->status_area_widget())->SetOpacity(target_bounds.opacity); + // TODO(harrym): Once status area widget is a child view of shelf + // this can be simplified. + gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf; + status_bounds.set_x(status_bounds.x() + + target_bounds.shelf_bounds_in_root.x()); + status_bounds.set_y(status_bounds.y() + + target_bounds.shelf_bounds_in_root.y()); + shelf_->status_area_widget()->SetBounds( + ScreenAsh::ConvertRectToScreen( + shelf_->status_area_widget()->GetNativeView()->parent(), + status_bounds)); + Shell::GetInstance()->SetDisplayWorkAreaInsets( + root_window_, target_bounds.work_area_insets); + UpdateHitTestBounds(); +} + +ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { + switch(auto_hide_behavior_) { + case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: + return SHELF_AUTO_HIDE; + case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: + return SHELF_VISIBLE; + case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: + return SHELF_HIDDEN; + } + return SHELF_VISIBLE; +} + +ShelfVisibilityState +ShelfLayoutManager::CalculateShelfVisibilityWhileDragging() { + switch(auto_hide_behavior_) { + case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: + case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: + return SHELF_AUTO_HIDE; + case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: + return SHELF_HIDDEN; + } + return SHELF_VISIBLE; +} + +void ShelfLayoutManager::UpdateVisibilityState() { + ShellDelegate* delegate = Shell::GetInstance()->delegate(); + if (delegate && delegate->IsScreenLocked()) { + SetState(SHELF_VISIBLE); + } else if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) { + // TODO(zelidrag): Verify shelf drag animation still shows on the device + // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. + SetState(CalculateShelfVisibilityWhileDragging()); + } else if (GetRootWindowController(root_window_)->IsImmersiveMode()) { + // The user choosing immersive mode indicates he or she wants to maximize + // screen real-estate for content, so always auto-hide the shelf. + DCHECK_NE(auto_hide_behavior_, SHELF_AUTO_HIDE_ALWAYS_HIDDEN); + SetState(SHELF_AUTO_HIDE); + } else { + WorkspaceWindowState window_state(workspace_controller_->GetWindowState()); + switch (window_state) { + case WORKSPACE_WINDOW_STATE_FULL_SCREEN: + SetState(SHELF_HIDDEN); + break; + + case WORKSPACE_WINDOW_STATE_MAXIMIZED: + SetState(CalculateShelfVisibility()); + break; + + case WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF: + case WORKSPACE_WINDOW_STATE_DEFAULT: + SetState(CalculateShelfVisibility()); + SetWindowOverlapsShelf(window_state == + WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF); + break; + } + } +} + +void ShelfLayoutManager::UpdateAutoHideState() { + ShelfAutoHideState auto_hide_state = + CalculateAutoHideState(state_.visibility_state); + if (auto_hide_state != state_.auto_hide_state) { + if (auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { + // Hides happen immediately. + SetState(state_.visibility_state); + FOR_EACH_OBSERVER(Observer, observers_, + OnAutoHideStateChanged(auto_hide_state)); + } else { + auto_hide_timer_.Stop(); + auto_hide_timer_.Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds(kAutoHideDelayMS), + this, &ShelfLayoutManager::UpdateAutoHideStateNow); + FOR_EACH_OBSERVER(Observer, observers_, OnAutoHideStateChanged( + CalculateAutoHideState(state_.visibility_state))); + } + } else { + auto_hide_timer_.Stop(); + } +} + +void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { + window_overlaps_shelf_ = value; + UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); +} + +void ShelfLayoutManager::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void ShelfLayoutManager::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +//////////////////////////////////////////////////////////////////////////////// +// ShelfLayoutManager, Gesture dragging: + +void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) { + gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS; + gesture_drag_amount_ = 0.f; + gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE ? + auto_hide_state() : SHELF_AUTO_HIDE_SHOWN; + UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); +} + +ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag( + const ui::GestureEvent& gesture) { + bool horizontal = IsHorizontalAlignment(); + gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() : + gesture.details().scroll_x(); + LayoutShelf(); + + // Start reveling the status menu when: + // - dragging up on an already visible shelf + // - dragging up on a hidden shelf, but it is currently completely visible. + if (horizontal && gesture.details().scroll_y() < 0) { + int min_height = 0; + if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && shelf_) + min_height = shelf_->GetContentsView()->GetPreferredSize().height(); + + if (min_height < shelf_->GetWindowBoundsInScreen().height() && + gesture.root_location().x() >= + shelf_->status_area_widget()->GetWindowBoundsInScreen().x() && + IsDraggingTrayEnabled()) + return DRAG_TRAY; + } + + return DRAG_SHELF; +} + +void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { + bool horizontal = IsHorizontalAlignment(); + bool should_change = false; + if (gesture.type() == ui::ET_GESTURE_SCROLL_END) { + // The visibility of the shelf changes only if the shelf was dragged X% + // along the correct axis. If the shelf was already visible, then the + // direction of the drag does not matter. + const float kDragHideThreshold = 0.4f; + gfx::Rect bounds = GetIdealBounds(); + float drag_ratio = fabs(gesture_drag_amount_) / + (horizontal ? bounds.height() : bounds.width()); + if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { + should_change = drag_ratio > kDragHideThreshold; + } else { + bool correct_direction = false; + switch (alignment_) { + case SHELF_ALIGNMENT_BOTTOM: + case SHELF_ALIGNMENT_RIGHT: + correct_direction = gesture_drag_amount_ < 0; + break; + case SHELF_ALIGNMENT_LEFT: + case SHELF_ALIGNMENT_TOP: + correct_direction = gesture_drag_amount_ > 0; + break; + } + should_change = correct_direction && drag_ratio > kDragHideThreshold; + } + } else if (gesture.type() == ui::ET_SCROLL_FLING_START) { + if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { + should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 : + fabs(gesture.details().velocity_x()) > 0; + } else { + should_change = SelectValueForShelfAlignment( + gesture.details().velocity_y() < 0, + gesture.details().velocity_x() > 0, + gesture.details().velocity_x() < 0, + gesture.details().velocity_y() > 0); + } + } else { + NOTREACHED(); + } + + if (!should_change) { + CancelGestureDrag(); + return; + } + + gesture_drag_auto_hide_state_ = + gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ? + SHELF_AUTO_HIDE_HIDDEN : SHELF_AUTO_HIDE_SHOWN; + if (shelf_) + shelf_->Deactivate(); + shelf_->status_area_widget()->Deactivate(); + if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && + auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) { + gesture_drag_status_ = GESTURE_DRAG_NONE; + SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + } else if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN && + auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER) { + gesture_drag_status_ = GESTURE_DRAG_NONE; + SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); + } else { + gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; + UpdateVisibilityState(); + gesture_drag_status_ = GESTURE_DRAG_NONE; + } +} + +void ShelfLayoutManager::CancelGestureDrag() { + gesture_drag_status_ = GESTURE_DRAG_NONE; + ui::ScopedLayerAnimationSettings + launcher_settings(GetLayer(shelf_)->GetAnimator()), + status_settings(GetLayer(shelf_->status_area_widget())->GetAnimator()); + LayoutShelf(); + UpdateVisibilityState(); + UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); +} + +//////////////////////////////////////////////////////////////////////////////// +// ShelfLayoutManager, aura::LayoutManager implementation: + +void ShelfLayoutManager::OnWindowResized() { + LayoutShelf(); +} + +void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) { +} + +void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { +} + +void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { +} + +void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) { +} + +void ShelfLayoutManager::SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) { + SetChildBoundsDirect(child, requested_bounds); + // We may contain other widgets (such as frame maximize bubble) but they don't + // effect the layout in anyway. + if (!in_layout_ && + ((shelf_->GetNativeView() == child) || + (shelf_->status_area_widget()->GetNativeView() == child))) { + LayoutShelf(); + } +} + +void ShelfLayoutManager::OnLockStateChanged(bool locked) { + UpdateVisibilityState(); +} + +void ShelfLayoutManager::OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) { + UpdateAutoHideStateNow(); +} + +bool ShelfLayoutManager::IsHorizontalAlignment() const { + return alignment_ == SHELF_ALIGNMENT_BOTTOM || + alignment_ == SHELF_ALIGNMENT_TOP; +} + +// static +ShelfLayoutManager* ShelfLayoutManager::ForLauncher(aura::Window* window) { + ShelfWidget* shelf = RootWindowController::ForLauncher(window)->shelf(); + return shelf ? shelf->shelf_layout_manager() : NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// ShelfLayoutManager, private: + +ShelfLayoutManager::TargetBounds::TargetBounds() : opacity(0.0f) {} +ShelfLayoutManager::TargetBounds::~TargetBounds() {} + +void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { + ShellDelegate* delegate = Shell::GetInstance()->delegate(); + State state; + state.visibility_state = visibility_state; + state.auto_hide_state = CalculateAutoHideState(visibility_state); + state.is_screen_locked = delegate && delegate->IsScreenLocked(); + + // It's possible for SetState() when a window becomes maximized but the state + // won't have changed value. Do the dimming check before the early exit. + if (workspace_controller_) { + shelf_->SetDimsShelf( + (state.visibility_state == SHELF_VISIBLE) && + workspace_controller_->GetWindowState() == + WORKSPACE_WINDOW_STATE_MAXIMIZED); + } + + if (state_.Equals(state)) + return; // Nothing changed. + + FOR_EACH_OBSERVER(Observer, observers_, + WillChangeVisibilityState(visibility_state)); + + if (state.visibility_state == SHELF_AUTO_HIDE) { + // When state is SHELF_AUTO_HIDE we need to track when the mouse is over the + // launcher to unhide the shelf. AutoHideEventFilter does that for us. + if (!event_filter_.get()) + event_filter_.reset(new AutoHideEventFilter(this)); + } else { + event_filter_.reset(NULL); + } + + auto_hide_timer_.Stop(); + + // Animating the background when transitioning from auto-hide & hidden to + // visible is janky. Update the background immediately in this case. + BackgroundAnimator::ChangeType change_type = + (state_.visibility_state == SHELF_AUTO_HIDE && + state_.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN && + state.visibility_state == SHELF_VISIBLE) ? + BackgroundAnimator::CHANGE_IMMEDIATE : BackgroundAnimator::CHANGE_ANIMATE; + StopAnimating(); + + State old_state = state_; + state_ = state; + TargetBounds target_bounds; + CalculateTargetBounds(state_, &target_bounds); + + ui::ScopedLayerAnimationSettings launcher_animation_setter( + GetLayer(shelf_)->GetAnimator()); + launcher_animation_setter.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS)); + launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT); + GetLayer(shelf_)->SetBounds( + target_bounds.shelf_bounds_in_root); + GetLayer(shelf_)->SetOpacity(target_bounds.opacity); + ui::ScopedLayerAnimationSettings status_animation_setter( + GetLayer(shelf_->status_area_widget())->GetAnimator()); + status_animation_setter.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS)); + status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); + + // Delay updating the background when going from SHELF_AUTO_HIDE_SHOWN to + // SHELF_AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the + // animation you see the background change. + // Also delay the animation when the shelf was hidden, and has just been made + // visible (e.g. using a gesture-drag). + bool delay_shelf_update = + state.visibility_state == SHELF_AUTO_HIDE && + state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN && + old_state.visibility_state == SHELF_AUTO_HIDE; + + if (state.visibility_state == SHELF_VISIBLE && + old_state.visibility_state == SHELF_AUTO_HIDE && + old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) + delay_shelf_update = true; + + if (delay_shelf_update) { + if (update_shelf_observer_) + update_shelf_observer_->Detach(); + // UpdateShelfBackground deletes itself when the animation is done. + update_shelf_observer_ = new UpdateShelfObserver(this); + status_animation_setter.AddObserver(update_shelf_observer_); + } + ui::Layer* layer = GetLayer(shelf_->status_area_widget()); + // TODO(harrym): Remove when status_area is view (crbug.com/180422). + gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf; + status_bounds.set_x(status_bounds.x() + + target_bounds.shelf_bounds_in_root.x()); + status_bounds.set_y(status_bounds.y() + + target_bounds.shelf_bounds_in_root.y()); + layer->SetBounds(status_bounds); + layer->SetOpacity(target_bounds.opacity); + Shell::GetInstance()->SetDisplayWorkAreaInsets( + root_window_, target_bounds.work_area_insets); + UpdateHitTestBounds(); + if (!delay_shelf_update) + UpdateShelfBackground(change_type); +} + +void ShelfLayoutManager::StopAnimating() { + GetLayer(shelf_)->GetAnimator()->StopAnimating(); + GetLayer(shelf_->status_area_widget())->GetAnimator()->StopAnimating(); +} + +void ShelfLayoutManager::GetShelfSize(int* width, int* height) { + *width = *height = 0; + gfx::Size status_size( + shelf_->status_area_widget()->GetWindowBoundsInScreen().size()); + if (IsHorizontalAlignment()) + *height = std::max(kLauncherPreferredSize, status_size.height()); + else + *width = std::max(kLauncherPreferredSize, status_size.width()); +} + +void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset, + gfx::Rect* bounds) const { + bounds->Inset(SelectValueForShelfAlignment( + gfx::Insets(0, 0, inset, 0), + gfx::Insets(0, inset, 0, 0), + gfx::Insets(0, 0, 0, inset), + gfx::Insets(inset, 0, 0, 0))); +} + +void ShelfLayoutManager::CalculateTargetBounds( + const State& state, + TargetBounds* target_bounds) { + const gfx::Rect& available_bounds(root_window_->bounds()); + gfx::Rect status_size( + shelf_->status_area_widget()->GetWindowBoundsInScreen().size()); + int shelf_width = 0, shelf_height = 0; + GetShelfSize(&shelf_width, &shelf_height); + if (IsHorizontalAlignment()) + shelf_width = available_bounds.width(); + else + shelf_height = available_bounds.height(); + + if (state.visibility_state == SHELF_AUTO_HIDE && + state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { + // Keep the launcher to its full height when dragging is in progress. + if (gesture_drag_status_ == GESTURE_DRAG_NONE) { + if (IsHorizontalAlignment()) + shelf_height = kAutoHideSize; + else + shelf_width = kAutoHideSize; + } + } else if (state.visibility_state == SHELF_HIDDEN) { + if (IsHorizontalAlignment()) + shelf_height = 0; + else + shelf_width = 0; + } + target_bounds->shelf_bounds_in_root = SelectValueForShelfAlignment( + gfx::Rect(available_bounds.x(), available_bounds.bottom() - shelf_height, + available_bounds.width(), shelf_height), + gfx::Rect(available_bounds.x(), available_bounds.y(), + shelf_width, available_bounds.height()), + gfx::Rect(available_bounds.right() - shelf_width, available_bounds.y(), + shelf_width, available_bounds.height()), + gfx::Rect(available_bounds.x(), available_bounds.y(), + available_bounds.width(), shelf_height)); + + int status_inset = (kLauncherPreferredSize - + PrimaryAxisValue(status_size.height(), status_size.width())); + + target_bounds->status_bounds_in_shelf = SelectValueForShelfAlignment( + gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(), + status_inset, status_size.width(), status_size.height()), + gfx::Rect(shelf_width - (status_size.width() + status_inset), + shelf_height - status_size.height(), status_size.width(), + status_size.height()), + gfx::Rect(status_inset, shelf_height - status_size.height(), + status_size.width(), status_size.height()), + gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(), + shelf_height - (status_size.height() + status_inset), + status_size.width(), status_size.height())); + + target_bounds->launcher_bounds_in_shelf = SelectValueForShelfAlignment( + gfx::Rect(base::i18n::IsRTL() ? status_size.width() : 0, 0, + shelf_width - status_size.width(), shelf_height), + gfx::Rect(0, 0, shelf_width, shelf_height - status_size.height()), + gfx::Rect(0, 0, shelf_width, shelf_height - status_size.height()), + gfx::Rect(base::i18n::IsRTL() ? status_size.width() : 0, 0, + shelf_width - status_size.width(), shelf_height)); + + target_bounds->work_area_insets = SelectValueForShelfAlignment( + gfx::Insets(0, 0, GetWorkAreaSize(state, shelf_height), 0), + gfx::Insets(0, GetWorkAreaSize(state, shelf_width), 0, 0), + gfx::Insets(0, 0, 0, GetWorkAreaSize(state, shelf_width)), + gfx::Insets(GetWorkAreaSize(state, shelf_height), 0, 0, 0)); + + target_bounds->opacity = + (gesture_drag_status_ != GESTURE_DRAG_NONE || + state.visibility_state == SHELF_VISIBLE || + state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f; + if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS) + UpdateTargetBoundsForGesture(target_bounds); +} + +void ShelfLayoutManager::UpdateTargetBoundsForGesture( + TargetBounds* target_bounds) const { + CHECK_EQ(GESTURE_DRAG_IN_PROGRESS, gesture_drag_status_); + bool horizontal = IsHorizontalAlignment(); + int resistance_free_region = 0; + + if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && + visibility_state() == SHELF_AUTO_HIDE && + auto_hide_state() != SHELF_AUTO_HIDE_SHOWN) { + // If the shelf was hidden when the drag started (and the state hasn't + // changed since then, e.g. because the tray-menu was shown because of the + // drag), then allow the drag some resistance-free region at first to make + // sure the shelf sticks with the finger until the shelf is visible. + resistance_free_region += horizontal ? + target_bounds->shelf_bounds_in_root.height() : + target_bounds->shelf_bounds_in_root.width(); + resistance_free_region -= kAutoHideSize; + } + + bool resist = SelectValueForShelfAlignment( + gesture_drag_amount_ < -resistance_free_region, + gesture_drag_amount_ > resistance_free_region, + gesture_drag_amount_ < -resistance_free_region, + gesture_drag_amount_ > resistance_free_region); + + float translate = 0.f; + if (resist) { + float diff = fabsf(gesture_drag_amount_) - resistance_free_region; + diff = std::min(diff, sqrtf(diff)); + if (gesture_drag_amount_ < 0) + translate = -resistance_free_region - diff; + else + translate = resistance_free_region + diff; + } else { + translate = gesture_drag_amount_; + } + + if (horizontal) { + // Move the launcher with the gesture. + target_bounds->shelf_bounds_in_root.Offset(0, translate); + + if (translate < 0) { + // When dragging up, the launcher height should increase. + float move = std::max(translate, + -static_cast(resistance_free_region)); + target_bounds->shelf_bounds_in_root.set_height( + target_bounds->shelf_bounds_in_root.height() + move - translate); + + // The statusbar should be in the center. + gfx::Rect status_y = target_bounds->shelf_bounds_in_root; + status_y.ClampToCenteredSize( + target_bounds->status_bounds_in_shelf.size()); + target_bounds->status_bounds_in_shelf.set_y(status_y.y()); + } + } else { + // Move the launcher with the gesture. + if (alignment_ == SHELF_ALIGNMENT_RIGHT) + target_bounds->shelf_bounds_in_root.Offset(translate, 0); + + if ((translate > 0 && alignment_ == SHELF_ALIGNMENT_RIGHT) || + (translate < 0 && alignment_ == SHELF_ALIGNMENT_LEFT)) { + // When dragging towards the edge, the statusbar should move. + target_bounds->status_bounds_in_shelf.Offset(translate, 0); + } else { + // When dragging away from the edge, the launcher width should increase. + float move = alignment_ == SHELF_ALIGNMENT_RIGHT ? + std::max(translate, -static_cast(resistance_free_region)) : + std::min(translate, static_cast(resistance_free_region)); + + if (alignment_ == SHELF_ALIGNMENT_RIGHT) { + target_bounds->shelf_bounds_in_root.set_width( + target_bounds->shelf_bounds_in_root.width() + move - translate); + } else { + target_bounds->shelf_bounds_in_root.set_width( + target_bounds->shelf_bounds_in_root.width() - move + translate); + } + + // The statusbar should be in the center. + gfx::Rect status_x = target_bounds->shelf_bounds_in_root; + status_x.ClampToCenteredSize( + target_bounds->status_bounds_in_shelf.size()); + target_bounds->status_bounds_in_shelf.set_x(status_x.x()); + } + } +} + +void ShelfLayoutManager::UpdateShelfBackground( + BackgroundAnimator::ChangeType type) { + bool launcher_paints = GetLauncherPaintsBackground(); + shelf_->SetPaintsBackground(launcher_paints, type); +} + +bool ShelfLayoutManager::GetLauncherPaintsBackground() const { + return gesture_drag_status_ != GESTURE_DRAG_NONE || + (!state_.is_screen_locked && window_overlaps_shelf_) || + (state_.visibility_state == SHELF_AUTO_HIDE) ; +} + +void ShelfLayoutManager::UpdateAutoHideStateNow() { + SetState(state_.visibility_state); +} + +ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( + ShelfVisibilityState visibility_state) const { + if (visibility_state != SHELF_AUTO_HIDE || !shelf_) + return SHELF_AUTO_HIDE_HIDDEN; + + if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) + return gesture_drag_auto_hide_state_; + + Shell* shell = Shell::GetInstance(); + if (shell->GetAppListTargetVisibility()) + return SHELF_AUTO_HIDE_SHOWN; + + if (shelf_->status_area_widget() && + shelf_->status_area_widget()->ShouldShowLauncher()) + return SHELF_AUTO_HIDE_SHOWN; + + if (shelf_->launcher() && shelf_->launcher()->IsShowingMenu()) + return SHELF_AUTO_HIDE_SHOWN; + + if (shelf_->launcher() && shelf_->launcher()->IsShowingOverflowBubble()) + return SHELF_AUTO_HIDE_SHOWN; + + if (shelf_->IsActive() || shelf_->status_area_widget()->IsActive()) + return SHELF_AUTO_HIDE_SHOWN; + + // Don't show if the user is dragging the mouse. + if (event_filter_.get() && event_filter_->in_mouse_drag()) + return SHELF_AUTO_HIDE_HIDDEN; + + gfx::Rect shelf_region = shelf_->GetWindowBoundsInScreen(); + if (shelf_->status_area_widget() && + shelf_->status_area_widget()->IsMessageBubbleShown() && + IsVisible()) { + // Increase the the hit test area to prevent the shelf from disappearing + // when the mouse is over the bubble gap. + shelf_region.Inset(alignment_ == SHELF_ALIGNMENT_RIGHT ? + -kNotificationBubbleGapHeight : 0, + alignment_ == SHELF_ALIGNMENT_BOTTOM ? + -kNotificationBubbleGapHeight : 0, + alignment_ == SHELF_ALIGNMENT_LEFT ? + -kNotificationBubbleGapHeight : 0, + alignment_ == SHELF_ALIGNMENT_TOP ? + -kNotificationBubbleGapHeight : 0); + } + + if (shelf_region.Contains(Shell::GetScreen()->GetCursorScreenPoint())) + return SHELF_AUTO_HIDE_SHOWN; + + const std::vector windows = + ash::WindowCycleController::BuildWindowList(NULL); + + // Process the window list and check if there are any visible windows. + for (size_t i = 0; i < windows.size(); ++i) { + if (windows[i] && windows[i]->IsVisible() && + !ash::wm::IsWindowMinimized(windows[i])) + return SHELF_AUTO_HIDE_HIDDEN; + } + + // If there are no visible windows do not hide the shelf. + return SHELF_AUTO_HIDE_SHOWN; +} + +void ShelfLayoutManager::UpdateHitTestBounds() { + gfx::Insets insets; + // Only modify the hit test when the shelf is visible, so we don't mess with + // hover hit testing in the auto-hide state. + if (state_.visibility_state == SHELF_VISIBLE) { + // Let clicks at the very top of the launcher through so windows can be + // resized with the bottom-right corner and bottom edge. + switch (alignment_) { + case SHELF_ALIGNMENT_BOTTOM: + insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0); + break; + case SHELF_ALIGNMENT_LEFT: + insets.Set(0, 0, 0, kWorkspaceAreaBottomInset); + break; + case SHELF_ALIGNMENT_RIGHT: + insets.Set(0, kWorkspaceAreaBottomInset, 0, 0); + break; + case SHELF_ALIGNMENT_TOP: + insets.Set(0, 0, kWorkspaceAreaBottomInset, 0); + break; + } + } + if (shelf_ && shelf_->GetNativeWindow()) { + shelf_->GetNativeWindow()->SetHitTestBoundsOverrideOuter( + insets, 1); + } + shelf_->status_area_widget()->GetNativeWindow()-> + SetHitTestBoundsOverrideOuter(insets, 1); +} + +bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) { + if (!window) + return false; + return (shelf_ && + shelf_->GetNativeWindow()->Contains(window)) || + (shelf_->status_area_widget()->GetNativeWindow()->Contains(window)); +} + +int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const { + if (state.visibility_state == SHELF_VISIBLE) + return size; + if (state.visibility_state == SHELF_AUTO_HIDE) + return kAutoHideSize; + return 0; +} + +} // namespace internal +} // namespace ash diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h new file mode 100644 index 0000000..40e59a7 --- /dev/null +++ b/ash/shelf/shelf_layout_manager.h @@ -0,0 +1,332 @@ +// 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. + +#ifndef ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ +#define ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ + +#include "ash/ash_export.h" +#include "ash/launcher/launcher.h" +#include "ash/shelf/background_animator.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shell_observer.h" +#include "ash/system/status_area_widget.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/observer_list.h" +#include "base/timer.h" +#include "ui/aura/client/activation_change_observer.h" +#include "ui/aura/layout_manager.h" +#include "ui/gfx/insets.h" +#include "ui/gfx/rect.h" + +namespace aura { +class RootWindow; +} + +namespace ui { +class GestureEvent; +} + +namespace ash { +class ScreenAsh; +class ShelfWidget; +namespace internal { + +class ShelfLayoutManagerTest; +class StatusAreaWidget; +class WorkspaceController; + +// ShelfLayoutManager is the layout manager responsible for the launcher and +// status widgets. The launcher is given the total available width and told the +// width of the status area. This allows the launcher to draw the background and +// layout to the status area. +// To respond to bounds changes in the status area StatusAreaLayoutManager works +// closely with ShelfLayoutManager. +class ASH_EXPORT ShelfLayoutManager : + public aura::LayoutManager, + public ash::ShellObserver, + public aura::client::ActivationChangeObserver { + public: + class ASH_EXPORT Observer { + public: + // Called when the target ShelfLayoutManager will be deleted. + virtual void WillDeleteShelf() {} + + // Called when the visibility change is scheduled. + virtual void WillChangeVisibilityState(ShelfVisibilityState new_state) {} + + // Called when the auto hide state is changed. + virtual void OnAutoHideStateChanged(ShelfAutoHideState new_state) {} + }; + + // We reserve a small area at the bottom of the workspace area to ensure that + // the bottom-of-window resize handle can be hit. + static const int kWorkspaceAreaBottomInset; + + // Size of the shelf when auto-hidden. + static const int kAutoHideSize; + + explicit ShelfLayoutManager(ShelfWidget* shelf); + virtual ~ShelfLayoutManager(); + + // Sets the ShelfAutoHideBehavior. See enum description for details. + void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); + ShelfAutoHideBehavior auto_hide_behavior() const { + return auto_hide_behavior_; + } + + // Sets the alignment. Returns true if the alignment is changed. Otherwise, + // returns false. + bool SetAlignment(ShelfAlignment alignment); + ShelfAlignment GetAlignment() const { return alignment_; } + + void set_workspace_controller(WorkspaceController* controller) { + workspace_controller_ = controller; + } + + bool in_layout() const { return in_layout_; } + + // Returns whether the shelf and its contents (launcher, status) are visible + // on the screen. + bool IsVisible() const; + + // Returns the ideal bounds of the shelf assuming it is visible. + gfx::Rect GetIdealBounds(); + + // Stops any animations and sets the bounds of the launcher and status + // widgets. + void LayoutShelf(); + + // Returns shelf visibility state based on current value of auto hide + // behavior setting. + ShelfVisibilityState CalculateShelfVisibility(); + + // Returns shelf visibility state based on current value of auto hide + // behavior setting. + ShelfVisibilityState CalculateShelfVisibilityWhileDragging(); + + // Updates the visibility state. + void UpdateVisibilityState(); + + // Invoked by the shelf/launcher when the auto-hide state may have changed. + void UpdateAutoHideState(); + + ShelfVisibilityState visibility_state() const { + return state_.visibility_state; + } + ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } + + ShelfWidget* shelf_widget() { return shelf_; } + + // Sets whether any windows overlap the shelf. If a window overlaps the shelf + // the shelf renders slightly differently. + void SetWindowOverlapsShelf(bool value); + bool window_overlaps_shelf() const { return window_overlaps_shelf_; } + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Gesture dragging related functions: + void StartGestureDrag(const ui::GestureEvent& gesture); + enum DragState { + DRAG_SHELF, + DRAG_TRAY + }; + // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf. + // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from + // this point on. + DragState UpdateGestureDrag(const ui::GestureEvent& gesture); + void CompleteGestureDrag(const ui::GestureEvent& gesture); + void CancelGestureDrag(); + + // Overridden from aura::LayoutManager: + virtual void OnWindowResized() OVERRIDE; + virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; + virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; + virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; + virtual void OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) OVERRIDE; + virtual void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) OVERRIDE; + + // Overridden from ash::ShellObserver: + virtual void OnLockStateChanged(bool locked) OVERRIDE; + + // Overriden from aura::client::ActivationChangeObserver: + virtual void OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) OVERRIDE; + + // TODO(harrym|oshima): These templates will be moved to + // new Shelf class. + // A helper function that provides a shortcut for choosing + // values specific to a shelf alignment. + template + T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const { + switch (alignment_) { + case SHELF_ALIGNMENT_BOTTOM: + return bottom; + case SHELF_ALIGNMENT_LEFT: + return left; + case SHELF_ALIGNMENT_RIGHT: + return right; + case SHELF_ALIGNMENT_TOP: + return top; + } + NOTREACHED(); + return right; + } + + template + T PrimaryAxisValue(T horizontal, T vertical) const { + return IsHorizontalAlignment() ? horizontal : vertical; + } + + // Is the shelf's alignment horizontal? + bool IsHorizontalAlignment() const; + + // Returns a ShelfLayoutManager on the display which has a launcher for + // given |window|. See RootWindowController::ForLauncher for more info. + static ShelfLayoutManager* ForLauncher(aura::Window* window); + + private: + class AutoHideEventFilter; + class UpdateShelfObserver; + friend class ash::ScreenAsh; + friend class ShelfLayoutManagerTest; + + struct TargetBounds { + TargetBounds(); + ~TargetBounds(); + + float opacity; + gfx::Rect shelf_bounds_in_root; + gfx::Rect launcher_bounds_in_shelf; + gfx::Rect status_bounds_in_shelf; + gfx::Insets work_area_insets; + }; + + struct State { + State() : visibility_state(SHELF_VISIBLE), + auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), + is_screen_locked(false) {} + + // Returns true if the two states are considered equal. As + // |auto_hide_state| only matters if |visibility_state| is + // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as + // appropriate. + bool Equals(const State& other) const { + return other.visibility_state == visibility_state && + (visibility_state != SHELF_AUTO_HIDE || + other.auto_hide_state == auto_hide_state) && + other.is_screen_locked == is_screen_locked; + } + + ShelfVisibilityState visibility_state; + ShelfAutoHideState auto_hide_state; + bool is_screen_locked; + }; + + // Sets the visibility of the shelf to |state|. + void SetState(ShelfVisibilityState visibility_state); + + // Stops any animations. + void StopAnimating(); + + // Returns the width (if aligned to the side) or height (if aligned to the + // bottom). + void GetShelfSize(int* width, int* height); + + // Insets |bounds| by |inset| on the edge the shelf is aligned to. + void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const; + + // Calculates the target bounds assuming visibility of |visible|. + void CalculateTargetBounds(const State& state, TargetBounds* target_bounds); + + // Updates the target bounds if a gesture-drag is in progress. This is only + // used by |CalculateTargetBounds()|. + void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const; + + // Updates the background of the shelf. + void UpdateShelfBackground(BackgroundAnimator::ChangeType type); + + // Returns whether the launcher should draw a background. + bool GetLauncherPaintsBackground() const; + + // Updates the auto hide state immediately. + void UpdateAutoHideStateNow(); + + // Returns the AutoHideState. This value is determined from the launcher and + // tray. + ShelfAutoHideState CalculateAutoHideState( + ShelfVisibilityState visibility_state) const; + + // Updates the hit test bounds override for launcher and status area. + void UpdateHitTestBounds(); + + // Returns true if |window| is a descendant of the shelf. + bool IsShelfWindow(aura::Window* window); + + int GetWorkAreaSize(const State& state, int size) const; + + // The RootWindow is cached so that we don't invoke Shell::GetInstance() from + // our destructor. We avoid that as at the time we're deleted Shell is being + // deleted too. + aura::RootWindow* root_window_; + + // True when inside LayoutShelf method. Used to prevent calling LayoutShelf + // again from SetChildBounds(). + bool in_layout_; + + // See description above setter. + ShelfAutoHideBehavior auto_hide_behavior_; + + ShelfAlignment alignment_; + + // Current state. + State state_; + + ShelfWidget* shelf_; + + WorkspaceController* workspace_controller_; + + // Do any windows overlap the shelf? This is maintained by WorkspaceManager. + bool window_overlaps_shelf_; + + base::OneShotTimer auto_hide_timer_; + + // EventFilter used to detect when user moves the mouse over the launcher to + // trigger showing the launcher. + scoped_ptr event_filter_; + + ObserverList observers_; + + // The shelf reacts to gesture-drags, and can be set to auto-hide for certain + // gestures. Some shelf behaviour (e.g. visibility state, background color + // etc.) are affected by various stages of the drag. The enum keeps track of + // the present status of the gesture drag. + enum GestureDragStatus { + GESTURE_DRAG_NONE, + GESTURE_DRAG_IN_PROGRESS, + GESTURE_DRAG_COMPLETE_IN_PROGRESS + }; + GestureDragStatus gesture_drag_status_; + + // Tracks the amount of the drag. The value is only valid when + // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS. + float gesture_drag_amount_; + + // Manage the auto-hide state during the gesture. + ShelfAutoHideState gesture_drag_auto_hide_state_; + + // Used to delay updating shelf background. + UpdateShelfObserver* update_shelf_observer_; + + DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc new file mode 100644 index 0000000..fe900a3 --- /dev/null +++ b/ash/shelf/shelf_layout_manager_unittest.cc @@ -0,0 +1,1108 @@ +// 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_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/shelf/shelf_widget.h" +#include "ash/shell.h" +#include "ash/shell_delegate.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_util.h" +#include "base/command_line.h" +#include "base/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/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( + 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 ShelfLayoutObserverTest : public ShelfLayoutManager::Observer { + 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(); + } + private: + DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest); +}; + +// 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(); + + const gfx::Display& display = Shell::GetInstance()->display_manager()-> + GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); + ASSERT_NE(-1, display.id()); + // Bottom inset should be the max of widget heights. + EXPECT_EQ(shelf_height, + display.bounds().bottom() - display.work_area().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()); + EXPECT_EQ(0, + display.bounds().bottom() - display.work_area().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()); + + // 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()); + EXPECT_EQ(shelf_height, + display.bounds().bottom() - display.work_area().bottom()); + + // Make sure the bounds of the two widgets changed. + launcher_bounds = shelf->GetNativeView()->bounds(); + int bottom = + Shell::GetScreen()->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()); + + const gfx::Display& display = Shell::GetInstance()->display_manager()-> + GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); + + // 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()); + EXPECT_EQ(0, display.bounds().bottom() - display.work_area().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()); +} + +// 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()); +} + +// 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()->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()->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()); +} + +// 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 internal::DisplayManager* manager = + Shell::GetInstance()->display_manager(); + gfx::Display display = + manager->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 = manager->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 = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); + launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen(); + display = manager->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 = manager->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 = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); + launcher_bounds = GetShelfWidget()->GetWindowBoundsInScreen(); + display = manager->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 = manager->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(); + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); + shelf->LayoutShelf(); + + 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(); + + gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen(); + gfx::Rect bounds_shelf = window->bounds(); + EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); + + aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + + // Swipe up on the shelf. This should not change any state. + gfx::Point start = GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint(); + gfx::Point end(start.x(), start.y() + 100); + + // Swipe down on the shelf to hide it. + end.set_y(start.y() + 100); + 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()); + 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()); + + gfx::Rect bounds_noshelf = window->bounds(); + gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen(); + + // Swipe up to show the shelf. + generator.GestureScrollSequence(end, start, + base::TimeDelta::FromMilliseconds(10), 1); + 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 up again. The shelf should hide. + end.set_y(start.y() - 100); + 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()); + 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.set_y(start.y() + 100); + generator.GestureScrollSequence(end, start, + base::TimeDelta::FromMilliseconds(10), 1); + + // Swipe down very little. It shouldn't change any state. + end.set_y(start.y() + shelf_shown.height() * 3 / 10); + generator.GestureScrollSequence(start, end, + base::TimeDelta::FromMilliseconds(100), 1); + 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.set_y(start.y() + 100); + 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()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior()); + EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString()); + EXPECT_EQ(shelf_hidden.ToString(), + GetShelfWidget()->GetWindowBoundsInScreen().ToString()); + + // Swipe up yet again to show it. + end.set_y(start.y() + 100); + generator.GestureScrollSequence(end, start, + base::TimeDelta::FromMilliseconds(10), 1); + EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior()); + + // Tap on the shelf itself. This should not change anything. + generator.GestureTapAt(start); + EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior()); + + // Now, tap on the desktop region (above the shelf). This should hide the + // shelf. + gfx::Point tap = start + gfx::Vector2d(0, -90); + generator.GestureTapAt(tap); + 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()); + + // Make the window fullscreen. + widget->SetFullscreen(true); + gfx::Rect bounds_fullscreen = window->bounds(); + EXPECT_TRUE(widget->IsFullscreen()); + EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString()); + EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); + + // Swipe-up. This should not change anything. + generator.GestureScrollSequence(end, start, + base::TimeDelta::FromMilliseconds(10), 1); + 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()); +} + +TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) { + 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(); + shelf->UpdateVisibilityState(); + EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state()); + + // Window closed => auto hide disabled. + dummy->CloseNow(); + shelf->UpdateVisibilityState(); + 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 + shelf->UpdateVisibilityState(); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); + + // either minimzed => normal autohide + window2->Minimize(); + shelf->UpdateVisibilityState(); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); + window2->Restore(); + window1->Minimize(); + shelf->UpdateVisibilityState(); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); + + // both minimzed => disable auto hide + window2->Minimize(); + shelf->UpdateVisibilityState(); + EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state()); +} + +#if defined(OS_WIN) +// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 +#define MAYBE_GestureRevealsTrayBubble DISABLED_GestureRevealsTrayBubble +#else +#define MAYBE_GestureRevealsTrayBubble GestureRevealsTrayBubble +#endif + +TEST_F(ShelfLayoutManagerTest, MAYBE_GestureRevealsTrayBubble) { + 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->CloseBubbleForTest(); + 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()); + + // Now hide the shelf. + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + + // The active maximized window will get resized to the new work area. However, + // the inactive window should not get resized. + EXPECT_NE(widget_one->GetNativeWindow()->bounds().ToString(), + widget_two->GetNativeWindow()->bounds().ToString()); + + // Activate the first window. Now, both windows should be of the same size + // again. + widget_one->Activate(); + EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(), + widget_two->GetNativeWindow()->bounds().ToString()); + + // Now show the shelf. + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); + + // The active maximized window will get resized to the new work area. However, + // the inactive window should not get resized. + EXPECT_NE(widget_one->GetNativeWindow()->bounds().ToString(), + widget_two->GetNativeWindow()->bounds().ToString()); + + // Activate the first window. Now, both windows should be of the same size + // again. + widget_two->Activate(); + EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(), + widget_two->GetNativeWindow()->bounds().ToString()); +} + +// 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 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->CloseBubbleForTest(); + 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()); + } + } +} + +} // namespace internal +} // namespace ash diff --git a/ash/shelf/shelf_types.h b/ash/shelf/shelf_types.h new file mode 100644 index 0000000..82cf630 --- /dev/null +++ b/ash/shelf/shelf_types.h @@ -0,0 +1,46 @@ +// 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. + +#ifndef ASH_SHELF_SHELF_TYPES_H_ +#define ASH_SHELF_SHELF_TYPES_H_ + +namespace ash { + +enum ShelfAlignment { + SHELF_ALIGNMENT_BOTTOM, + SHELF_ALIGNMENT_LEFT, + SHELF_ALIGNMENT_RIGHT, + SHELF_ALIGNMENT_TOP, +}; + +enum ShelfAutoHideBehavior { + // Always auto-hide. + SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + + // Never auto-hide. + SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + + // Always hide. + SHELF_AUTO_HIDE_ALWAYS_HIDDEN, +}; + +enum ShelfVisibilityState { + // Always visible. + SHELF_VISIBLE, + + // A couple of pixels are reserved at the bottom for the shelf. + SHELF_AUTO_HIDE, + + // Nothing is shown. Used for fullscreen windows. + SHELF_HIDDEN, +}; + +enum ShelfAutoHideState { + SHELF_AUTO_HIDE_SHOWN, + SHELF_AUTO_HIDE_HIDDEN, +}; + +} // namespace ash + +#endif // ASH_SHELF_SHELF_TYPES_H_ diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc new file mode 100644 index 0000000..74dfb5c --- /dev/null +++ b/ash/shelf/shelf_widget.cc @@ -0,0 +1,312 @@ +// 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_widget.h" + +#include "ash/focus_cycler.h" +#include "ash/launcher/launcher_delegate.h" +#include "ash/launcher/launcher_model.h" +#include "ash/launcher/launcher_navigator.h" +#include "ash/launcher/launcher_view.h" +#include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "ash/shell_window_ids.h" +#include "ash/wm/property_util.h" +#include "ash/wm/status_area_layout_manager.h" +#include "ash/wm/window_properties.h" +#include "ash/wm/workspace_controller.h" +#include "grit/ash_resources.h" +#include "ui/aura/client/activation_client.h" +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" +#include "ui/aura/window_observer.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/compositor/layer.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/skbitmap_operations.h" +#include "ui/views/accessible_pane_view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +namespace { +// Size of black border at bottom (or side) of launcher. +const int kNumBlackPixels = 3; +// Alpha to paint dimming image with. +const int kDimAlpha = 96; +} + +namespace ash { + +// The contents view of the Shelf. This view contains LauncherView and +// sizes it to the width of the shelf minus the size of the status area. +class ShelfWidget::DelegateView : public views::WidgetDelegate, + public views::AccessiblePaneView, + public internal::BackgroundAnimatorDelegate { + public: + explicit DelegateView(ShelfWidget* shelf); + virtual ~DelegateView(); + + void set_focus_cycler(internal::FocusCycler* focus_cycler) { + focus_cycler_ = focus_cycler; + } + internal::FocusCycler* focus_cycler() { + return focus_cycler_; + } + + // Set if the shelf area is dimmed (eg when a window is maximized). + void SetDimmed(bool dimmed) { + if (dimmed_ != dimmed) { + dimmed_ = dimmed; + SchedulePaint(); + } + } + bool GetDimmed() const { return dimmed_; } + + // views::View overrides: + void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; + + // views::WidgetDelegateView overrides: + views::Widget* GetWidget() OVERRIDE { + return View::GetWidget(); + } + const views::Widget* GetWidget() const OVERRIDE { + return View::GetWidget(); + } + + bool CanActivate() const OVERRIDE; + void Layout() OVERRIDE; + + // BackgroundAnimatorDelegate overrides: + void UpdateBackground(int alpha) OVERRIDE; + + private: + ShelfWidget* shelf_; + internal::FocusCycler* focus_cycler_; + int alpha_; + bool dimmed_; + + DISALLOW_COPY_AND_ASSIGN(DelegateView); +}; + +ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf) + : shelf_(shelf), + focus_cycler_(NULL), + alpha_(0), + dimmed_(false) { +} + +ShelfWidget::DelegateView::~DelegateView() { +} + +void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + gfx::ImageSkia launcher_background = + *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND); + if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment()) + launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage( + launcher_background, + shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( + SkBitmapOperations::ROTATION_90_CW, + SkBitmapOperations::ROTATION_90_CW, + SkBitmapOperations::ROTATION_270_CW, + SkBitmapOperations::ROTATION_180_CW)); + + gfx::Rect black_rect = + shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( + gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels), + gfx::Rect(0, 0, kNumBlackPixels, height()), + gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()), + gfx::Rect(0, 0, width(), kNumBlackPixels)); + + SkPaint paint; + paint.setAlpha(alpha_); + canvas->DrawImageInt( + launcher_background, + 0, 0, launcher_background.width(), launcher_background.height(), + 0, 0, width(), height(), + false, + paint); + canvas->FillRect(black_rect, SK_ColorBLACK); + + if (dimmed_) { + gfx::ImageSkia background_image = + *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_DIMMING); + if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment()) + background_image = gfx::ImageSkiaOperations::CreateRotatedImage( + background_image, + shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( + SkBitmapOperations::ROTATION_90_CW, + SkBitmapOperations::ROTATION_90_CW, + SkBitmapOperations::ROTATION_270_CW, + SkBitmapOperations::ROTATION_180_CW)); + + SkPaint paint; + paint.setAlpha(kDimAlpha); + canvas->DrawImageInt( + background_image, + 0, 0, background_image.width(), background_image.height(), + 0, 0, width(), height(), + false, + paint); + } +} + +bool ShelfWidget::DelegateView::CanActivate() const { + // Allow to activate as fallback. + if (shelf_->activating_as_fallback_) + return true; + // Allow to activate from the focus cycler. + if (focus_cycler_ && focus_cycler_->widget_activating() == GetWidget()) + return true; + // Disallow activating in other cases, especially when using mouse. + return false; +} + +void ShelfWidget::DelegateView::Layout() { + for(int i = 0; i < child_count(); ++i) { + if (shelf_->shelf_layout_manager()->IsHorizontalAlignment()) { + child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(), + child_at(i)->width(), height()); + } else { + child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(), + width(), child_at(i)->height()); + } + } +} + +void ShelfWidget::DelegateView::UpdateBackground(int alpha) { + alpha_ = alpha; + SchedulePaint(); +} + +ShelfWidget::ShelfWidget( + aura::Window* shelf_container, + aura::Window* status_container, + internal::WorkspaceController* workspace_controller) : + launcher_(NULL), + delegate_view_(new DelegateView(this)), + background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha), + activating_as_fallback_(false), + window_container_(shelf_container) { + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.transparent = true; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.parent = shelf_container; + params.delegate = delegate_view_; + Init(params); + + // The shelf should not take focus when initially shown. + set_focus_on_creation(false); + SetContentsView(delegate_view_); + + status_area_widget_ = new internal::StatusAreaWidget(status_container); + status_area_widget_->CreateTrayViews(); + if (Shell::GetInstance()->delegate()->IsSessionStarted()) + status_area_widget_->Show(); + Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_); + + shelf_layout_manager_ = new internal::ShelfLayoutManager(this); + shelf_container->SetLayoutManager(shelf_layout_manager_); + shelf_layout_manager_->set_workspace_controller(workspace_controller); + workspace_controller->SetShelf(shelf_layout_manager_); + + status_container->SetLayoutManager( + new internal::StatusAreaLayoutManager(this)); + + views::Widget::AddObserver(this); +} + +ShelfWidget::~ShelfWidget() { + RemoveObserver(this); +} + +void ShelfWidget::SetPaintsBackground( + bool value, + internal::BackgroundAnimator::ChangeType change_type) { + background_animator_.SetPaintsBackground(value, change_type); +} + +ShelfAlignment ShelfWidget::GetAlignment() const { + return shelf_layout_manager_->GetAlignment(); +} + +void ShelfWidget::SetAlignment(ShelfAlignment alignment) { + shelf_layout_manager_->SetAlignment(alignment); + shelf_layout_manager_->LayoutShelf(); + delegate_view_->SchedulePaint(); +} + +void ShelfWidget::SetDimsShelf(bool dimming) { + delegate_view_->SetDimmed(dimming); +} + +bool ShelfWidget::GetDimsShelf() const { + return delegate_view_->GetDimmed(); +} + +void ShelfWidget::CreateLauncher() { + if (!launcher_.get()) { + Shell* shell = Shell::GetInstance(); + // This needs to be called before launcher_model(). + shell->GetLauncherDelegate(); + launcher_.reset(new Launcher(shell->launcher_model(), + shell->GetLauncherDelegate(), + this)); + + SetFocusCycler(shell->focus_cycler()); + + // Inform the root window controller. + internal::RootWindowController::ForWindow(window_container_)-> + OnLauncherCreated(); + + ShellDelegate* delegate = shell->delegate(); + if (delegate) + launcher_->SetVisible(delegate->IsSessionStarted()); + + Show(); + } +} + +bool ShelfWidget::IsLauncherVisible() const { + return launcher_.get() && launcher_->IsVisible(); +} + +void ShelfWidget::SetLauncherVisibility(bool visible) { + if (launcher_.get()) + launcher_->SetVisible(visible); +} + +void ShelfWidget::SetFocusCycler(internal::FocusCycler* focus_cycler) { + delegate_view_->set_focus_cycler(focus_cycler); + if (focus_cycler) + focus_cycler->AddWidget(this); +} + +internal::FocusCycler* ShelfWidget::GetFocusCycler() { + return delegate_view_->focus_cycler(); +} + +void ShelfWidget::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + activating_as_fallback_ = false; + if (active) + delegate_view_->SetPaneFocusAndFocusDefault(); + else + delegate_view_->GetFocusManager()->ClearFocus(); +} + +void ShelfWidget::ShutdownStatusAreaWidget() { + if (status_area_widget_) + status_area_widget_->Shutdown(); + status_area_widget_ = NULL; +} + +} // namespace ash + diff --git a/ash/shelf/shelf_widget.h b/ash/shelf/shelf_widget.h new file mode 100644 index 0000000..df63ec0 --- /dev/null +++ b/ash/shelf/shelf_widget.h @@ -0,0 +1,104 @@ +// 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. + +#ifndef ASH_SHELF_SHELF_WIDGET_H_ +#define ASH_SHELF_SHELF_WIDGET_H_ + +#include "ash/ash_export.h" +#include "ash/shelf/background_animator.h" +#include "ash/shelf/shelf_types.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" + +namespace aura { +class Window; +} + +namespace ash { +class Launcher; + +namespace internal { +class FocusCycler; +class StatusAreaWidget; +class ShelfLayoutManager; +class WorkspaceController; +} + +class ASH_EXPORT ShelfWidget : public views::Widget, + public views::WidgetObserver { + public: + ShelfWidget( + aura::Window* shelf_container, + aura::Window* status_container, + internal::WorkspaceController* workspace_controller); + virtual ~ShelfWidget(); + + void SetAlignment(ShelfAlignment alignmnet); + ShelfAlignment GetAlignment() const; + + ShelfAutoHideBehavior GetAutoHideBehavior() const; + void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); + + // Sets whether the shelf paints a background. Default is false, but is set + // to true if a window overlaps the shelf. + void SetPaintsBackground( + bool value, + internal::BackgroundAnimator::ChangeType change_type); + bool paints_background() const { + return background_animator_.paints_background(); + } + + // Causes shelf items to be slightly dimmed (eg when a window is maximized). + void SetDimsShelf(bool dimming); + bool GetDimsShelf() const; + + internal::ShelfLayoutManager* shelf_layout_manager() { + return shelf_layout_manager_; + } + Launcher* launcher() const { return launcher_.get(); } + internal::StatusAreaWidget* status_area_widget() const { + return status_area_widget_; + } + + void CreateLauncher(); + + // Set visibility of the launcher component of the shelf. + void SetLauncherVisibility(bool visible); + bool IsLauncherVisible() const; + + // Sets the focus cycler. Also adds the launcher to the cycle. + void SetFocusCycler(internal::FocusCycler* focus_cycler); + internal::FocusCycler* GetFocusCycler(); + + // Called by the activation delegate, before the launcher is activated + // when no other windows are visible. + void WillActivateAsFallback() { activating_as_fallback_ = true; } + + // Overridden from views::WidgetObserver: + virtual void OnWidgetActivationChanged( + views::Widget* widget, bool active) OVERRIDE; + + aura::Window* window_container() { return window_container_; } + + // TODO(harrym): Remove when Status Area Widget is a child view. + void ShutdownStatusAreaWidget(); + + private: + class DelegateView; + + internal::ShelfLayoutManager* shelf_layout_manager_; + scoped_ptr launcher_; + internal::StatusAreaWidget* status_area_widget_; + + // delegate_view_ is attached to window_container_ and is cleaned up + // during CloseChildWindows of the associated RootWindowController. + DelegateView* delegate_view_; + internal::BackgroundAnimator background_animator_; + bool activating_as_fallback_; + aura::Window* window_container_; +}; + +} // namespace ash + +#endif // ASH_SHELF_SHELF_WIDGET_H_ diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc new file mode 100644 index 0000000..bea1c64 --- /dev/null +++ b/ash/shelf/shelf_widget_unittest.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2013 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_widget.h" + +#include "ash/launcher/launcher.h" +#include "ash/launcher/launcher_button.h" +#include "ash/launcher/launcher_model.h" +#include "ash/launcher/launcher_view.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/launcher_view_test_api.h" +#include "ash/wm/window_util.h" +#include "ui/aura/root_window.h" +#include "ui/gfx/display.h" +#include "ui/gfx/screen.h" +#include "ui/views/corewm/corewm_switches.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { +ShelfWidget* GetShelfWidget() { + return Launcher::ForPrimaryDisplay()->shelf_widget(); +} + +internal::ShelfLayoutManager* GetShelfLayoutManager() { + return GetShelfWidget()->shelf_layout_manager(); +} + +} // namespace + +typedef test::AshTestBase ShelfWidgetTest; + +// Launcher can't be activated on mouse click, but it is activable from +// the focus cycler or as fallback. +TEST_F(ShelfWidgetTest, ActivateAsFallback) { + // TODO(mtomasz): make this test work with the FocusController. + if (views::corewm::UseFocusController()) + return; + + Launcher* launcher = Launcher::ForPrimaryDisplay(); + ShelfWidget* shelf_widget = launcher->shelf_widget(); + EXPECT_FALSE(shelf_widget->CanActivate()); + + shelf_widget->WillActivateAsFallback(); + EXPECT_TRUE(shelf_widget->CanActivate()); + + wm::ActivateWindow(shelf_widget->GetNativeWindow()); + EXPECT_FALSE(shelf_widget->CanActivate()); +} + +void TestLauncherAlignment(aura::RootWindow* root, + ShelfAlignment alignment, + const std::string& expected) { + Shell::GetInstance()->SetShelfAlignment(alignment, root); + gfx::Screen* screen = gfx::Screen::GetScreenFor(root); + EXPECT_EQ(expected, + screen->GetDisplayNearestWindow(root).work_area().ToString()); +} + +TEST_F(ShelfWidgetTest, TestAlignment) { + Launcher* launcher = Launcher::ForPrimaryDisplay(); + UpdateDisplay("400x400"); + ASSERT_TRUE(launcher); + { + SCOPED_TRACE("Single Bottom"); + TestLauncherAlignment(Shell::GetPrimaryRootWindow(), + SHELF_ALIGNMENT_BOTTOM, + "0,0 400x352"); + } + { + SCOPED_TRACE("Single Right"); + TestLauncherAlignment(Shell::GetPrimaryRootWindow(), + SHELF_ALIGNMENT_RIGHT, + "0,0 348x400"); + } + { + SCOPED_TRACE("Single Left"); + TestLauncherAlignment(Shell::GetPrimaryRootWindow(), + SHELF_ALIGNMENT_LEFT, + "52,0 348x400"); + } + UpdateDisplay("300x300,500x500"); + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + { + SCOPED_TRACE("Primary Bottom"); + TestLauncherAlignment(root_windows[0], + SHELF_ALIGNMENT_BOTTOM, + "0,0 300x252"); + } + { + SCOPED_TRACE("Primary Right"); + TestLauncherAlignment(root_windows[0], + SHELF_ALIGNMENT_RIGHT, + "0,0 248x300"); + } + { + SCOPED_TRACE("Primary Left"); + TestLauncherAlignment(root_windows[0], + SHELF_ALIGNMENT_LEFT, + "52,0 248x300"); + } + if (Shell::IsLauncherPerDisplayEnabled()) { + { + SCOPED_TRACE("Secondary Bottom"); + TestLauncherAlignment(root_windows[1], + SHELF_ALIGNMENT_BOTTOM, + "300,0 500x452"); + } + { + SCOPED_TRACE("Secondary Right"); + TestLauncherAlignment(root_windows[1], + SHELF_ALIGNMENT_RIGHT, + "300,0 448x500"); + } + { + SCOPED_TRACE("Secondary Left"); + TestLauncherAlignment(root_windows[1], + SHELF_ALIGNMENT_LEFT, + "352,0 448x500"); + } + } +} + +// Makes sure the launcher is initially sized correctly. +TEST_F(ShelfWidgetTest, LauncherInitiallySized) { + ShelfWidget* shelf_widget = GetShelfWidget(); + Launcher* launcher = shelf_widget->launcher(); + ASSERT_TRUE(launcher); + internal::ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManager(); + ASSERT_TRUE(shelf_layout_manager); + ASSERT_TRUE(shelf_widget->status_area_widget()); + int status_width = shelf_widget->status_area_widget()-> + GetWindowBoundsInScreen().width(); + // Test only makes sense if the status is > 0, which it better be. + EXPECT_GT(status_width, 0); + EXPECT_EQ(status_width, shelf_widget->GetContentsView()->width() - + launcher->GetLauncherViewForTest()->width()); +} + +// Verifies when the shell is deleted with a full screen window we don't crash. +TEST_F(ShelfWidgetTest, DontReferenceLauncherAfterDeletion) { + 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->SetFullscreen(true); +} + +} // namespace ash diff --git a/ash/shelf_types.h b/ash/shelf_types.h deleted file mode 100644 index ac35c58..0000000 --- a/ash/shelf_types.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -#ifndef ASH_SHELF_TYPES_H_ -#define ASH_SHELF_TYPES_H_ - -namespace ash { - -enum ShelfAlignment { - SHELF_ALIGNMENT_BOTTOM, - SHELF_ALIGNMENT_LEFT, - SHELF_ALIGNMENT_RIGHT, - SHELF_ALIGNMENT_TOP, -}; - -enum ShelfAutoHideBehavior { - // Always auto-hide. - SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - - // Never auto-hide. - SHELF_AUTO_HIDE_BEHAVIOR_NEVER, - - // Always hide. - SHELF_AUTO_HIDE_ALWAYS_HIDDEN, -}; - -enum ShelfVisibilityState { - // Always visible. - SHELF_VISIBLE, - - // A couple of pixels are reserved at the bottom for the shelf. - SHELF_AUTO_HIDE, - - // Nothing is shown. Used for fullscreen windows. - SHELF_HIDDEN, -}; - -enum ShelfAutoHideState { - SHELF_AUTO_HIDE_SHOWN, - SHELF_AUTO_HIDE_HIDDEN, -}; - -} // namespace ash - -#endif // ASH_SHELF_TYPES_H_ diff --git a/ash/shell.cc b/ash/shell.cc index 77b60f9..5588706 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -28,6 +28,8 @@ #include "ash/magnifier/partial_magnification_controller.h" #include "ash/root_window_controller.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell_delegate.h" #include "ash/shell_factory.h" #include "ash/shell_window_ids.h" @@ -721,9 +723,9 @@ void Shell::CreateLauncher() { RootWindowControllerList controllers = GetAllRootWindowControllers(); for (RootWindowControllerList::iterator iter = controllers.begin(); iter != controllers.end(); ++iter) - (*iter)->CreateLauncher(); + (*iter)->shelf()->CreateLauncher(); } else { - GetPrimaryRootWindowController()->CreateLauncher(); + GetPrimaryRootWindowController()->shelf()->CreateLauncher(); } } @@ -756,24 +758,28 @@ void Shell::UpdateShelfVisibility() { void Shell::SetShelfAutoHideBehavior(ShelfAutoHideBehavior behavior, aura::RootWindow* root_window) { - GetRootWindowController(root_window)->SetShelfAutoHideBehavior(behavior); + ash::internal::ShelfLayoutManager::ForLauncher(root_window)-> + SetAutoHideBehavior(behavior); } ShelfAutoHideBehavior Shell::GetShelfAutoHideBehavior( aura::RootWindow* root_window) const { - return GetRootWindowController(root_window)->GetShelfAutoHideBehavior(); + return ash::internal::ShelfLayoutManager::ForLauncher(root_window)-> + auto_hide_behavior(); } void Shell::SetShelfAlignment(ShelfAlignment alignment, aura::RootWindow* root_window) { - if (GetRootWindowController(root_window)->SetShelfAlignment(alignment)) { + if (ash::internal::ShelfLayoutManager::ForLauncher(root_window)-> + SetAlignment(alignment)) { FOR_EACH_OBSERVER( ShellObserver, observers_, OnShelfAlignmentChanged(root_window)); } } ShelfAlignment Shell::GetShelfAlignment(aura::RootWindow* root_window) { - return GetRootWindowController(root_window)->GetShelfAlignment(); + return GetRootWindowController(root_window)-> + GetShelfLayoutManager()->GetAlignment(); } void Shell::SetDimming(bool should_dim) { @@ -812,12 +818,13 @@ void Shell::OnModalWindowRemoved(aura::Window* removed) { } WebNotificationTray* Shell::GetWebNotificationTray() { - return GetPrimaryRootWindowController()->status_area_widget()-> - web_notification_tray(); + return GetPrimaryRootWindowController()->shelf()-> + status_area_widget()->web_notification_tray(); } bool Shell::HasPrimaryStatusArea() { - return !!GetPrimaryRootWindowController()->status_area_widget(); + ShelfWidget* shelf = GetPrimaryRootWindowController()->shelf(); + return shelf && shelf->status_area_widget(); } SystemTray* Shell::GetPrimarySystemTray() { diff --git a/ash/shell.h b/ash/shell.h index c2cdda6..1b659b8 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -9,7 +9,7 @@ #include #include "ash/ash_export.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/user/login_status.h" #include "ash/wm/system_modal_container_event_filter_delegate.h" #include "base/basictypes.h" @@ -440,6 +440,13 @@ class ASH_EXPORT Shell return root_window_host_factory_.get(); } + LauncherModel* launcher_model() { + return launcher_model_.get(); + } + + // Returns the launcher delegate, creating if necesary. + LauncherDelegate* GetLauncherDelegate(); + private: FRIEND_TEST_ALL_PREFIXES(ExtendedDesktopTest, TestCursor); FRIEND_TEST_ALL_PREFIXES(WindowManagerTest, MouseEventCursors); @@ -455,13 +462,6 @@ class ASH_EXPORT Shell void Init(); - LauncherModel* launcher_model() { - return launcher_model_.get(); - } - - // Returns the launcher delegate, creating if necesary. - LauncherDelegate* GetLauncherDelegate(); - // Initializes the root window and root window controller so that it // can host browser windows. void InitRootWindowController(internal::RootWindowController* root); diff --git a/ash/shell/context_menu.cc b/ash/shell/context_menu.cc index 9cd5f26..04f1dcf 100644 --- a/ash/shell/context_menu.cc +++ b/ash/shell/context_menu.cc @@ -6,7 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/shell.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h" diff --git a/ash/shell/context_menu.h b/ash/shell/context_menu.h index fc83c17..618c75b 100644 --- a/ash/shell/context_menu.h +++ b/ash/shell/context_menu.h @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WM_SHELL_CONTEXT_MENU_H_ -#define ASH_WM_SHELL_CONTEXT_MENU_H_ +#ifndef ASH_SHELL_CONTEXT_MENU_H_ +#define ASH_SHELL_CONTEXT_MENU_H_ #include "ash/launcher/launcher_alignment_menu.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "base/basictypes.h" #include "ui/base/models/simple_menu_model.h" @@ -48,4 +48,4 @@ class ContextMenu : public ui::SimpleMenuModel, } // namespace shell } // namespace ash -#endif // ASH_WM_SHELL_CONTEXT_MENU_H_ +#endif // ASH_SHELL_CONTEXT_MENU_H_ diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc index 4a9b677..1980bf2 100644 --- a/ash/shell/window_type_launcher.cc +++ b/ash/shell/window_type_launcher.cc @@ -6,6 +6,7 @@ #include "ash/root_window_controller.h" #include "ash/screensaver/screensaver_view.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell/example_factory.h" #include "ash/shell/panel_window.h" @@ -358,8 +359,8 @@ void WindowTypeLauncher::ButtonPressed(views::Button* sender, base::TimeDelta::FromSeconds(5)); } else if (sender == show_web_notification_) { - ash::Shell::GetPrimaryRootWindowController()->status_area_widget()-> - web_notification_tray()->message_center()->AddNotification( + ash::Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget() + ->web_notification_tray()->message_center()->AddNotification( message_center::NOTIFICATION_TYPE_SIMPLE, "id0", ASCIIToUTF16("Test Shell Web Notification"), diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc index 0711208..0963eb7 100644 --- a/ash/shell/window_watcher.cc +++ b/ash/shell/window_watcher.cc @@ -7,6 +7,7 @@ #include "ash/display/display_controller.h" #include "ash/launcher/launcher.h" #include "ash/launcher/launcher_model.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ui/aura/root_window.h" @@ -39,7 +40,8 @@ class WindowWatcher::WorkspaceWindowWatcher : public aura::WindowObserver { internal::kShellWindowId_PanelContainer); panel_container->AddObserver(watcher_); - aura::Window* container = Launcher::ForWindow(root)->window_container(); + aura::Window* container = + Launcher::ForWindow(root)->shelf_widget()->window_container(); container->AddObserver(this); for (size_t i = 0; i < container->children().size(); ++i) container->children()[i]->AddObserver(watcher_); @@ -51,7 +53,8 @@ class WindowWatcher::WorkspaceWindowWatcher : public aura::WindowObserver { internal::kShellWindowId_PanelContainer); panel_container->RemoveObserver(watcher_); - aura::Window* container = Launcher::ForWindow(root)->window_container(); + aura::Window* container = + Launcher::ForWindow(root)->shelf_widget()->window_container(); container->RemoveObserver(this); for (size_t i = 0; i < container->children().size(); ++i) container->children()[i]->RemoveObserver(watcher_); diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc index a1851ff..25df2bf 100644 --- a/ash/shell_unittest.cc +++ b/ash/shell_unittest.cc @@ -11,11 +11,12 @@ #include "ash/desktop_background/desktop_background_widget_controller.h" #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/wm/root_window_layout_manager.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_util.h" #include "base/utf_string_conversions.h" #include "ui/aura/client/aura_constants.h" @@ -55,7 +56,7 @@ void ExpectAllContainers() { EXPECT_TRUE(Shell::GetContainer( root_window, internal::kShellWindowId_PanelContainer)); EXPECT_TRUE(Shell::GetContainer( - root_window, internal::kShellWindowId_LauncherContainer)); + root_window, internal::kShellWindowId_ShelfContainer)); EXPECT_TRUE(Shell::GetContainer( root_window, internal::kShellWindowId_SystemModalContainer)); EXPECT_TRUE(Shell::GetContainer( @@ -282,7 +283,7 @@ TEST_F(ShellTest, MAYBE_ManagedWindowModeBasics) { // We start with the usual window containers. ExpectAllContainers(); // Launcher is visible. - views::Widget* launcher_widget = Launcher::ForPrimaryDisplay()->widget(); + ShelfWidget* launcher_widget = Launcher::ForPrimaryDisplay()->shelf_widget(); EXPECT_TRUE(launcher_widget->IsVisible()); // Launcher is at bottom-left of screen. EXPECT_EQ(0, launcher_widget->GetWindowBoundsInScreen().x()); @@ -323,19 +324,22 @@ TEST_F(ShellTest, FullscreenWindowHidesShelf) { // Shelf defaults to visible. EXPECT_EQ( SHELF_VISIBLE, - Shell::GetPrimaryRootWindowController()->shelf()->visibility_state()); + Shell::GetPrimaryRootWindowController()-> + GetShelfLayoutManager()->visibility_state()); // Fullscreen window hides it. widget->SetFullscreen(true); EXPECT_EQ( SHELF_HIDDEN, - Shell::GetPrimaryRootWindowController()->shelf()->visibility_state()); + Shell::GetPrimaryRootWindowController()-> + GetShelfLayoutManager()->visibility_state()); // Restoring the window restores it. widget->Restore(); EXPECT_EQ( SHELF_VISIBLE, - Shell::GetPrimaryRootWindowController()->shelf()->visibility_state()); + Shell::GetPrimaryRootWindowController()-> + GetShelfLayoutManager()->visibility_state()); // Clean up. widget->Close(); diff --git a/ash/shell_window_ids.h b/ash/shell_window_ids.h index 465965e..a64858f 100644 --- a/ash/shell_window_ids.h +++ b/ash/shell_window_ids.h @@ -53,8 +53,8 @@ const int kShellWindowId_AlwaysOnTopContainer = 7; // The container for panel windows. const int kShellWindowId_PanelContainer = 8; -// The container for the launcher. -const int kShellWindowId_LauncherContainer = 9; +// The container for the shelf. +const int kShellWindowId_ShelfContainer = 9; // The container for the app list. const int kShellWindowId_AppListContainer = 10; diff --git a/ash/system/ime/tray_ime.cc b/ash/system/ime/tray_ime.cc index a0460b7..c931f46 100644 --- a/ash/system/ime/tray_ime.cc +++ b/ash/system/ime/tray_ime.cc @@ -7,6 +7,7 @@ #include #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/tray/hover_highlight_view.h" #include "ash/system/tray/system_tray.h" @@ -17,7 +18,6 @@ #include "ash/system/tray/tray_item_more.h" #include "ash/system/tray/tray_item_view.h" #include "ash/system/tray/tray_notification_view.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/logging.h" #include "base/timer.h" #include "base/utf_string_conversions.h" diff --git a/ash/system/session_length_limit/tray_session_length_limit.cc b/ash/system/session_length_limit/tray_session_length_limit.cc index d9c3588..54dbc02 100644 --- a/ash/system/session_length_limit/tray_session_length_limit.cc +++ b/ash/system/session_length_limit/tray_session_length_limit.cc @@ -6,7 +6,7 @@ #include -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/shell.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_delegate.h" diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index 527edf2..0701097 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc @@ -5,6 +5,8 @@ #include "ash/system/status_area_widget.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" @@ -13,7 +15,6 @@ #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/system/web_notification/web_notification_tray.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_properties.h" #include "base/i18n/time_formatting.h" #include "ui/aura/window.h" @@ -108,15 +109,6 @@ void StatusAreaWidget::SetShelfAlignment(ShelfAlignment alignment) { status_area_widget_delegate_->UpdateLayout(); } -void StatusAreaWidget::SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type) { - if (system_tray_) - system_tray_->SetPaintsBackground(value, change_type); - if (web_notification_tray_) - web_notification_tray_->SetPaintsBackground(value, change_type); -} - void StatusAreaWidget::SetHideWebNotifications(bool hide) { if (web_notification_tray_) web_notification_tray_->SetHidePopupBubble(hide); diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index c83a735..03a78a4 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h @@ -6,8 +6,7 @@ #define ASH_SYSTEM_STATUS_AREA_WIDGET_H_ #include "ash/ash_export.h" -#include "ash/launcher/background_animator.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/user/login_status.h" #include "ui/views/widget/widget.h" @@ -36,11 +35,6 @@ class ASH_EXPORT StatusAreaWidget : public views::Widget { // Update the alignment of the widget and tray views. void SetShelfAlignment(ShelfAlignment alignment); - // Update whether to paint a background for each tray view. - void SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type); - // Set the visibility state of web notifications. void SetHideWebNotifications(bool hide); diff --git a/ash/system/status_area_widget_delegate.h b/ash/system/status_area_widget_delegate.h index 84b1c2e..c7820ea 100644 --- a/ash/system/status_area_widget_delegate.h +++ b/ash/system/status_area_widget_delegate.h @@ -6,7 +6,7 @@ #define ASH_SYSTEM_STATUS_AREA_WIDGET_DELEGATE_H_ #include "ash/ash_export.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/wm/gestures/shelf_gesture_handler.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/accessible_pane_view.h" diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index 0b17757..6962514 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc @@ -5,6 +5,7 @@ #include "ash/system/tray/system_tray.h" #include "ash/ash_switches.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell/panel_window.h" #include "ash/shell_window_ids.h" @@ -32,7 +33,6 @@ #include "ash/system/tray_update.h" #include "ash/system/user/login_status.h" #include "ash/system/user/tray_user.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/command_line.h" #include "base/logging.h" #include "base/timer.h" diff --git a/ash/system/tray/system_tray_item.h b/ash/system/tray/system_tray_item.h index d643a94c..29fdf8a 100644 --- a/ash/system/tray/system_tray_item.h +++ b/ash/system/tray/system_tray_item.h @@ -6,7 +6,7 @@ #define ASH_SYSTEM_TRAY_SYSTEM_TRAY_ITEM_H_ #include "ash/ash_export.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/user/login_status.h" #include "base/basictypes.h" #include "base/compiler_specific.h" diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc index ac693e3..ca1db67 100644 --- a/ash/system/tray/system_tray_unittest.cc +++ b/ash/system/tray/system_tray_unittest.cc @@ -7,6 +7,7 @@ #include #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray_item.h" #include "ash/test/ash_test_base.h" @@ -26,8 +27,8 @@ namespace test { namespace { SystemTray* GetSystemTray() { - return Shell::GetPrimaryRootWindowController()->status_area_widget()-> - system_tray(); + return Shell::GetPrimaryRootWindowController()->shelf()-> + status_area_widget()->system_tray(); } // Trivial item implementation that tracks its views for testing. @@ -288,7 +289,7 @@ TEST_F(SystemTrayTest, BubbleCreationTypesTest) { // tray extends to the correct edge of the screen. TEST_F(SystemTrayTest, TrayBoundsInWidget) { internal::StatusAreaWidget* widget = - Shell::GetPrimaryRootWindowController()->status_area_widget(); + Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget(); SystemTray* tray = widget->system_tray(); // Test in bottom alignment. Bottom and right edges of the view should be diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index ebe77cd..68c6b62 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc @@ -4,9 +4,9 @@ #include "ash/system/tray/tray_background_view.h" -#include "ash/launcher/background_animator.h" #include "ash/root_window_controller.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/system/status_area_widget.h" @@ -14,7 +14,6 @@ #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_event_filter.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" @@ -28,7 +27,6 @@ namespace { -const SkColor kTrayBackgroundAlpha = 100; const SkColor kTrayBackgroundHoverAlpha = 150; // Adjust the size of TrayContainer with additional padding. @@ -72,7 +70,7 @@ class TrayBackgroundView::TrayWidgetObserver : public views::WidgetObserver { class TrayBackground : public views::Background { public: - TrayBackground() : alpha_(kTrayBackgroundAlpha) {} + TrayBackground() : alpha_(0) {} virtual ~TrayBackground() {} void set_alpha(int alpha) { alpha_ = alpha; } @@ -167,16 +165,13 @@ TrayBackgroundView::TrayBackgroundView( tray_container_(NULL), shelf_alignment_(SHELF_ALIGNMENT_BOTTOM), background_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_( - this, 0, kTrayBackgroundAlpha)), ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_( - this, 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)), + this, 0, kTrayBackgroundHoverAlpha)), ALLOW_THIS_IN_INITIALIZER_LIST(widget_observer_( new TrayWidgetObserver(this))) { set_notify_enter_exit_on_child(true); // Initially we want to paint the background, but without the hover effect. - SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE); hover_background_animator_.SetPaintsBackground(false, internal::BackgroundAnimator::CHANGE_IMMEDIATE); @@ -235,8 +230,7 @@ bool TrayBackgroundView::PerformAction(const ui::Event& event) { void TrayBackgroundView::UpdateBackground(int alpha) { if (background_) { - background_->set_alpha(hide_background_animator_.alpha() + - hover_background_animator_.alpha()); + background_->set_alpha(hover_background_animator_.alpha()); } SchedulePaint(); } @@ -251,15 +245,8 @@ void TrayBackgroundView::SetContentsBackground() { tray_container_->set_background(background_); } -void TrayBackgroundView::SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type) { - hide_background_animator_.SetPaintsBackground(value, change_type); -} - ShelfLayoutManager* TrayBackgroundView::GetShelfLayoutManager() { - return - RootWindowController::ForLauncher(GetWidget()->GetNativeView())->shelf(); + return ShelfLayoutManager::ForLauncher(GetWidget()->GetNativeView()); } void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) { @@ -387,7 +374,7 @@ void TrayBackgroundView::UpdateBubbleViewArrow( aura::RootWindow* root_window = bubble_view->GetWidget()->GetNativeView()->GetRootWindow(); ash::internal::ShelfLayoutManager* shelf = - ash::GetRootWindowController(root_window)->shelf(); + ShelfLayoutManager::ForLauncher(root_window); bubble_view->SetArrowPaintType( shelf->IsVisible() ? views::BubbleBorder::PAINT_NORMAL : views::BubbleBorder::PAINT_TRANSPARENT); diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h index 8b136655..39f2a4c 100644 --- a/ash/system/tray/tray_background_view.h +++ b/ash/system/tray/tray_background_view.h @@ -6,8 +6,8 @@ #define ASH_SYSTEM_TRAY_TRAY_BACKGROUND_VIEW_H_ #include "ash/ash_export.h" -#include "ash/launcher/background_animator.h" -#include "ash/shelf_types.h" +#include "ash/shelf/background_animator.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/tray/actionable_view.h" #include "ui/views/bubble/tray_bubble_view.h" @@ -100,12 +100,6 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView, // Creates and sets contents background to |background_|. void SetContentsBackground(); - // Sets whether the tray paints a background. Default is true, but is set to - // false if a window overlaps the shelf. - void SetPaintsBackground( - bool value, - internal::BackgroundAnimator::ChangeType change_type); - // Initializes animations for the bubble. void InitializeBubbleAnimations(views::Widget* bubble_widget); @@ -155,7 +149,6 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView, // Owned by the view passed to SetContents(). internal::TrayBackground* background_; - internal::BackgroundAnimator hide_background_animator_; internal::BackgroundAnimator hover_background_animator_; scoped_ptr widget_observer_; scoped_ptr tray_event_filter_; diff --git a/ash/system/tray/tray_event_filter.cc b/ash/system/tray/tray_event_filter.cc index f2192e5..949b2f9 100644 --- a/ash/system/tray/tray_event_filter.cc +++ b/ash/system/tray/tray_event_filter.cc @@ -5,6 +5,7 @@ #include "ash/system/tray/tray_event_filter.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/system/tray/tray_background_view.h" @@ -12,7 +13,6 @@ #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_event_filter.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" diff --git a/ash/system/tray/tray_item_view.cc b/ash/system/tray/tray_item_view.cc index ae778ae..426ff52 100644 --- a/ash/system/tray/tray_item_view.cc +++ b/ash/system/tray/tray_item_view.cc @@ -4,7 +4,7 @@ #include "ash/system/tray/tray_item_view.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" #include "ui/base/animation/slide_animation.h" diff --git a/ash/system/tray/tray_views.h b/ash/system/tray/tray_views.h index 06632ca..d50c946 100644 --- a/ash/system/tray/tray_views.h +++ b/ash/system/tray/tray_views.h @@ -6,7 +6,7 @@ #define ASH_SYSTEM_TRAY_TRAY_VIEWS_H_ #include "ash/ash_export.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" #include "ui/gfx/font.h" #include "ui/gfx/size.h" #include "ui/views/controls/button/custom_button.h" diff --git a/ash/system/tray_update.cc b/ash/system/tray_update.cc index f448e30..e56d8c1 100644 --- a/ash/system/tray_update.cc +++ b/ash/system/tray_update.cc @@ -5,6 +5,8 @@ #include "ash/system/tray_update.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/fixed_sized_image_view.h" @@ -13,7 +15,6 @@ #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_views.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/time.h" #include "base/timer.h" #include "grit/ash_resources.h" @@ -110,7 +111,7 @@ class UpdateNagger : public ui::LayerAnimationObserver { virtual ~UpdateNagger() { internal::StatusAreaWidget* status_area = - Shell::GetPrimaryRootWindowController()->status_area_widget(); + Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget(); if (status_area) { status_area->system_tray()->GetWidget()->GetNativeView()->layer()-> GetAnimator()->RemoveObserver(this); diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc index 98f3770..38ca581 100644 --- a/ash/system/web_notification/web_notification_tray.cc +++ b/ash/system/web_notification/web_notification_tray.cc @@ -5,13 +5,13 @@ #include "ash/system/web_notification/web_notification_tray.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/tray_background_view.h" #include "ash/system/tray/tray_bubble_wrapper.h" #include "ash/system/tray/tray_constants.h" -#include "ash/wm/shelf_layout_manager.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/aura/root_window.h" diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc index 7895d18..a53f970 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/web_notification/web_notification_tray_unittest.cc @@ -7,6 +7,7 @@ #include #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray_item.h" #include "ash/test/ash_test_base.h" @@ -33,8 +34,8 @@ namespace ash { namespace { WebNotificationTray* GetWebNotificationTray() { - return Shell::GetPrimaryRootWindowController()->status_area_widget()-> - web_notification_tray(); + return Shell::GetPrimaryRootWindowController()->shelf()-> + status_area_widget()->web_notification_tray(); } message_center::MessageCenter* get_message_center() { diff --git a/ash/wm/activation_controller.cc b/ash/wm/activation_controller.cc index 0e50f2c..196043ac 100644 --- a/ash/wm/activation_controller.cc +++ b/ash/wm/activation_controller.cc @@ -43,7 +43,7 @@ const int kWindowContainerIds[] = { // containers even though these layers are higher. The user expects their // windows to be focused before these elements. kShellWindowId_PanelContainer, - kShellWindowId_LauncherContainer, + kShellWindowId_ShelfContainer, kShellWindowId_StatusContainer, }; diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc index f23b398..3c34984 100644 --- a/ash/wm/app_list_controller.cc +++ b/ash/wm/app_list_controller.cc @@ -6,11 +6,11 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/views/app_list_view.h" @@ -109,7 +109,8 @@ void AppListController::SetVisible(bool visible, aura::Window* window) { // App list needs to know the new shelf layout in order to calculate its // UI layout when AppListView visibility changes. - Shell::GetPrimaryRootWindowController()->shelf()->UpdateAutoHideState(); + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> + UpdateAutoHideState(); if (view_) { ScheduleAnimation(); diff --git a/ash/wm/ash_activation_controller.cc b/ash/wm/ash_activation_controller.cc index 261bd62..f8c338a 100644 --- a/ash/wm/ash_activation_controller.cc +++ b/ash/wm/ash_activation_controller.cc @@ -6,6 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/wm/activation_controller.h" @@ -94,24 +95,16 @@ aura::Window* AshActivationController::PrepareToActivateLauncher() { // Fallback to a launcher only when Spoken feedback is enabled. if (!Shell::GetInstance()->delegate()->IsSpokenFeedbackEnabled()) return NULL; - Launcher* launcher; - if (Shell::IsLauncherPerDisplayEnabled()) { - launcher = GetRootWindowController( - Shell::GetActiveRootWindow())->launcher(); - } else { - launcher = Launcher::ForPrimaryDisplay(); - } - // Launcher is not always available, eg. not in the login screen. - if (!launcher) - return NULL; - views::Widget* launcher_widget = launcher->widget(); + ShelfWidget* shelf = GetRootWindowController( + Shell::IsLauncherPerDisplayEnabled() ? + Shell::GetActiveRootWindow() : + Shell::GetPrimaryRootWindow())->shelf(); // Launcher's window may be already destroyed in shutting down process. - if (!launcher_widget) + if (!shelf) return NULL; - aura::Window* launcher_window = launcher_widget->GetNativeWindow(); // Notify launcher to allow activation via CanActivate(). - launcher->WillActivateAsFallback(); - return launcher_window; + shelf->WillActivateAsFallback(); + return shelf->GetNativeWindow(); } } // namespace internal diff --git a/ash/wm/ash_activation_controller_unittest.cc b/ash/wm/ash_activation_controller_unittest.cc index b0505c5..e332990 100644 --- a/ash/wm/ash_activation_controller_unittest.cc +++ b/ash/wm/ash_activation_controller_unittest.cc @@ -6,6 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell_delegate.h" #include "ash/test/ash_test_base.h" #include "ash/wm/property_util.h" @@ -30,7 +31,7 @@ class AshActivationControllerTest : public test::AshTestBase { ash_activation_controller_.reset(new internal::AshActivationController()); launcher_ = Launcher::ForPrimaryDisplay(); ASSERT_TRUE(launcher_); - launcher_widget_ = launcher_->widget(); + launcher_widget_ = launcher_->shelf_widget(); ASSERT_TRUE(launcher_widget_); launcher_window_ = launcher_widget_->GetNativeWindow(); ASSERT_TRUE(launcher_window_); diff --git a/ash/wm/ash_focus_rules.cc b/ash/wm/ash_focus_rules.cc index 5e1c605..3382999 100644 --- a/ash/wm/ash_focus_rules.cc +++ b/ash/wm/ash_focus_rules.cc @@ -28,7 +28,7 @@ const int kWindowContainerIds[] = { // containers even though these layers are higher. The user expects their // windows to be focused before these elements. internal::kShellWindowId_PanelContainer, - internal::kShellWindowId_LauncherContainer, + internal::kShellWindowId_ShelfContainer, internal::kShellWindowId_StatusContainer, }; diff --git a/ash/wm/base_layout_manager.cc b/ash/wm/base_layout_manager.cc index 8f4da18..d5bb54f 100644 --- a/ash/wm/base_layout_manager.cc +++ b/ash/wm/base_layout_manager.cc @@ -5,8 +5,8 @@ #include "ash/wm/base_layout_manager.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc index bef092c..f3c9124 100644 --- a/ash/wm/drag_window_resizer_unittest.cc +++ b/ash/wm/drag_window_resizer_unittest.cc @@ -6,12 +6,12 @@ #include "ash/display/mouse_cursor_event_filter.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" #include "ash/wm/drag_window_controller.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/stringprintf.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" @@ -98,7 +98,7 @@ class DragWindowResizerTest : public test::AshTestBase { } internal::ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->shelf(); + return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); } static DragWindowResizer* CreateDragWindowResizer( diff --git a/ash/wm/gestures/shelf_gesture_handler.cc b/ash/wm/gestures/shelf_gesture_handler.cc index 7db6649..d000eb5 100644 --- a/ash/wm/gestures/shelf_gesture_handler.cc +++ b/ash/wm/gestures/shelf_gesture_handler.cc @@ -5,12 +5,13 @@ #include "ash/wm/gestures/shelf_gesture_handler.h" #include "ash/root_window_controller.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/system/status_area_widget.h" #include "ash/wm/gestures/tray_gesture_handler.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_util.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" @@ -45,10 +46,10 @@ class ShelfResetHandler : public ui::EventHandler, bool ShelfIsEventTarget(const ui::Event& event) { aura::Window* target = static_cast(event.target()); - views::Widget* widget = shelf_->launcher_widget(); + views::Widget* widget = shelf_->shelf_widget(); if (widget && widget->GetNativeWindow() == target) return true; - widget = shelf_->status_area_widget(); + widget = shelf_->shelf_widget()->status_area_widget(); if (widget && widget->GetNativeWindow() == target) return true; return false; @@ -57,13 +58,13 @@ class ShelfResetHandler : public ui::EventHandler, void DecideShelfVisibility(const gfx::Point& location) { // For the rest of the mouse events, ignore if the event happens inside the // shelf. - views::Widget* widget = shelf_->launcher_widget(); + views::Widget* widget = shelf_->shelf_widget(); if (widget && widget->GetWindowBoundsInScreen().Contains(location)) { return; } - widget = shelf_->status_area_widget(); + widget = shelf_->shelf_widget()->status_area_widget(); if (widget && widget->GetWindowBoundsInScreen().Contains(location)) { return; @@ -132,7 +133,8 @@ bool ShelfGestureHandler::ProcessGestureEvent(const ui::GestureEvent& event) { return false; // TODO(oshima): Find the root window controller from event's location. - ShelfLayoutManager* shelf = Shell::GetPrimaryRootWindowController()->shelf(); + ShelfLayoutManager* shelf = + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) { drag_in_progress_ = true; shelf->StartGestureDrag(event); diff --git a/ash/wm/gestures/system_pinch_handler.cc b/ash/wm/gestures/system_pinch_handler.cc index 806f4f9..39a733b 100644 --- a/ash/wm/gestures/system_pinch_handler.cc +++ b/ash/wm/gestures/system_pinch_handler.cc @@ -6,6 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/wm/property_util.h" #include "ash/wm/window_util.h" @@ -131,7 +132,7 @@ gfx::Rect SystemPinchHandler::GetPhantomWindowScreenBounds( Launcher* launcher = Launcher::ForWindow(window); gfx::Rect rect = launcher->GetScreenBoundsOfItemIconForWindow(target_); if (rect.IsEmpty()) - rect = launcher->widget()->GetWindowBoundsInScreen(); + rect = launcher->shelf_widget()->GetWindowBoundsInScreen(); else rect.Inset(-8, -8); phantom_state_ = PHANTOM_WINDOW_MINIMIZED; diff --git a/ash/wm/maximize_bubble_controller.cc b/ash/wm/maximize_bubble_controller.cc index e601882..e9fdd85 100644 --- a/ash/wm/maximize_bubble_controller.cc +++ b/ash/wm/maximize_bubble_controller.cc @@ -391,7 +391,7 @@ MaximizeBubbleController::Bubble::Bubble( // cover it upon animation. aura::Window* parent = Shell::GetContainer( Shell::GetActiveRootWindow(), - internal::kShellWindowId_LauncherContainer); + internal::kShellWindowId_ShelfContainer); set_parent_window(parent); set_notify_enter_exit_on_child(true); diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc index cd612e8..433f894 100644 --- a/ash/wm/panels/panel_layout_manager.cc +++ b/ash/wm/panels/panel_layout_manager.cc @@ -9,7 +9,8 @@ #include "ash/launcher/launcher.h" #include "ash/screen_ash.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/wm/frame_painter.h" #include "ash/wm/property_util.h" @@ -218,8 +219,6 @@ PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) PanelLayoutManager::~PanelLayoutManager() { Shutdown(); - if (launcher_) - launcher_->RemoveIconObserver(this); aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> RemoveObserver(this); Shell::GetInstance()->RemoveShellObserver(this); @@ -231,6 +230,9 @@ void PanelLayoutManager::Shutdown() { delete iter->callout_widget; } panel_windows_.clear(); + if (launcher_) + launcher_->RemoveIconObserver(this); + launcher_ = NULL; } void PanelLayoutManager::StartDragging(aura::Window* panel) { @@ -414,17 +416,18 @@ void PanelLayoutManager::RestorePanel(aura::Window* panel) { } void PanelLayoutManager::Relayout() { - if (!launcher_ || !launcher_->widget()) + if (!launcher_ || !launcher_->shelf_widget()) return; if (in_layout_) return; base::AutoReset auto_reset_in_layout(&in_layout_, true); - ShelfAlignment alignment = launcher_->alignment(); + ShelfAlignment alignment = launcher_->shelf_widget()->GetAlignment(); bool horizontal = alignment == SHELF_ALIGNMENT_TOP || alignment == SHELF_ALIGNMENT_BOTTOM; - gfx::Rect launcher_bounds = launcher_->widget()->GetWindowBoundsInScreen(); + gfx::Rect launcher_bounds = launcher_->shelf_widget()-> + GetWindowBoundsInScreen(); int panel_start_bounds = kPanelIdealSpacing; int panel_end_bounds = horizontal ? panel_container_->bounds().width() - kPanelIdealSpacing : diff --git a/ash/wm/panels/panel_layout_manager_unittest.cc b/ash/wm/panels/panel_layout_manager_unittest.cc index a7a7a6e..137b49e 100644 --- a/ash/wm/panels/panel_layout_manager_unittest.cc +++ b/ash/wm/panels/panel_layout_manager_unittest.cc @@ -9,8 +9,10 @@ #include "ash/launcher/launcher_button.h" #include "ash/launcher/launcher_model.h" #include "ash/launcher/launcher_view.h" +#include "ash/root_window_controller.h" #include "ash/screen_ash.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" @@ -119,7 +121,8 @@ class PanelLayoutManagerTest : public test::AshTestBase { ASSERT_FALSE(icon_bounds.IsEmpty()); gfx::Rect window_bounds = panel->GetBoundsInRootWindow(); - gfx::Rect launcher_bounds = launcher->widget()->GetWindowBoundsInScreen(); + gfx::Rect launcher_bounds = launcher->shelf_widget()-> + GetWindowBoundsInScreen(); ShelfAlignment alignment = GetAlignment(); if (IsHorizontal(alignment)) { diff --git a/ash/wm/panels/panel_window_resizer.cc b/ash/wm/panels/panel_window_resizer.cc index 0f82db5..e306f29 100644 --- a/ash/wm/panels/panel_window_resizer.cc +++ b/ash/wm/panels/panel_window_resizer.cc @@ -6,7 +6,8 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" -#include "ash/shelf_types.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/wm/panels/panel_layout_manager.h" @@ -102,8 +103,8 @@ PanelWindowResizer::PanelWindowResizer(const Details& details) bool PanelWindowResizer::AttachToLauncher(gfx::Rect* bounds) { bool should_attach = false; if (panel_layout_manager_) { - gfx::Rect launcher_bounds = panel_layout_manager_->launcher()->widget()-> - GetWindowBoundsInScreen(); + gfx::Rect launcher_bounds = panel_layout_manager_->launcher()-> + shelf_widget()->GetWindowBoundsInScreen(); switch (panel_layout_manager_->launcher()->alignment()) { case SHELF_ALIGNMENT_BOTTOM: if (bounds->bottom() >= (launcher_bounds.y() - diff --git a/ash/wm/panels/panel_window_resizer_unittest.cc b/ash/wm/panels/panel_window_resizer_unittest.cc index 93fe71a..4be4645 100644 --- a/ash/wm/panels/panel_window_resizer_unittest.cc +++ b/ash/wm/panels/panel_window_resizer_unittest.cc @@ -5,7 +5,9 @@ #include "ash/wm/panels/panel_window_resizer.h" #include "ash/launcher/launcher.h" -#include "ash/shelf_types.h" +#include "ash/root_window_controller.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" @@ -34,7 +36,7 @@ class PanelWindowResizerTest : public test::AshTestBase { panel_layout_manager_ = static_cast( GetPanelContainer()->layout_manager()); - launcher_bounds_ = panel_layout_manager_->launcher()->widget()-> + launcher_bounds_ = panel_layout_manager_->launcher()->shelf_widget()-> GetWindowBoundsInScreen(); } diff --git a/ash/wm/session_state_animator.cc b/ash/wm/session_state_animator.cc index 82af8b3..a1ac9ac 100644 --- a/ash/wm/session_state_animator.cc +++ b/ash/wm/session_state_animator.cc @@ -466,7 +466,7 @@ void SessionStateAnimator::GetContainers(int container_mask, if (container_mask & LAUNCHER) { containers->push_back(Shell::GetContainer( root_window, - internal::kShellWindowId_LauncherContainer)); + internal::kShellWindowId_ShelfContainer)); } if (container_mask & NON_LOCK_SCREEN_CONTAINERS) { // TODO(antrim): Figure out a way to eliminate a need to exclude launcher @@ -479,7 +479,7 @@ void SessionStateAnimator::GetContainers(int container_mask, for (aura::Window::Windows::const_iterator it = children.begin(); it != children.end(); ++it) { aura::Window* window = *it; - if (window->id() == internal::kShellWindowId_LauncherContainer) + if (window->id() == internal::kShellWindowId_ShelfContainer) continue; containers->push_back(window); } diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc deleted file mode 100644 index edbd359..0000000 --- a/ash/wm/shelf_layout_manager.cc +++ /dev/null @@ -1,945 +0,0 @@ -// 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/wm/shelf_layout_manager.h" - -#include -#include - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_delegate.h" -#include "ash/shell_window_ids.h" -#include "ash/system/status_area_widget.h" -#include "ash/wm/property_util.h" -#include "ash/wm/window_cycle_controller.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace/workspace_animations.h" -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "base/i18n/rtl.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/root_window.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_handler.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -namespace { - -// Delay before showing the launcher. This is after the mouse stops moving. -const int kAutoHideDelayMS = 200; - -// To avoid hiding the shelf when the mouse transitions from a message bubble -// into the shelf, the hit test area is enlarged by this amount of pixels to -// keep the shelf from hiding. -const int kNotificationBubbleGapHeight = 6; - -ui::Layer* GetLayer(views::Widget* widget) { - return widget->GetNativeView()->layer(); -} - -bool IsDraggingTrayEnabled() { - static bool dragging_tray_allowed = CommandLine::ForCurrentProcess()-> - HasSwitch(ash::switches::kAshEnableTrayDragging); - return dragging_tray_allowed; -} - -} // namespace - -// static -const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; - -// static -const int ShelfLayoutManager::kAutoHideSize = 3; - -// ShelfLayoutManager::AutoHideEventFilter ------------------------------------- - -// Notifies ShelfLayoutManager any time the mouse moves. -class ShelfLayoutManager::AutoHideEventFilter : public ui::EventHandler { - public: - explicit AutoHideEventFilter(ShelfLayoutManager* shelf); - virtual ~AutoHideEventFilter(); - - // Returns true if the last mouse event was a mouse drag. - bool in_mouse_drag() const { return in_mouse_drag_; } - - // Overridden from ui::EventHandler: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - - private: - ShelfLayoutManager* shelf_; - bool in_mouse_drag_; - - DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter); -}; - -ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter( - ShelfLayoutManager* shelf) - : shelf_(shelf), - in_mouse_drag_(false) { - Shell::GetInstance()->AddPreTargetHandler(this); -} - -ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() { - Shell::GetInstance()->RemovePreTargetHandler(this); -} - -void ShelfLayoutManager::AutoHideEventFilter::OnMouseEvent( - ui::MouseEvent* event) { - // This also checks IsShelfWindow() to make sure we don't attempt to hide the - // shelf if the mouse down occurs on the shelf. - in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED || - (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED && - event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) && - !shelf_->IsShelfWindow(static_cast(event->target())); - if (event->type() == ui::ET_MOUSE_MOVED) - shelf_->UpdateAutoHideState(); - return; -} - -// ShelfLayoutManager:UpdateShelfObserver -------------------------------------- - -// UpdateShelfObserver is used to delay updating the background until the -// animation completes. -class ShelfLayoutManager::UpdateShelfObserver - : public ui::ImplicitAnimationObserver { - public: - explicit UpdateShelfObserver(ShelfLayoutManager* shelf) : shelf_(shelf) { - shelf_->update_shelf_observer_ = this; - } - - void Detach() { - shelf_ = NULL; - } - - virtual void OnImplicitAnimationsCompleted() OVERRIDE { - if (shelf_) { - shelf_->UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); - } - delete this; - } - - private: - virtual ~UpdateShelfObserver() { - if (shelf_) - shelf_->update_shelf_observer_ = NULL; - } - - // Shelf we're in. NULL if deleted before we're deleted. - ShelfLayoutManager* shelf_; - - DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); -}; - -// ShelfLayoutManager ---------------------------------------------------------- - -ShelfLayoutManager::ShelfLayoutManager(StatusAreaWidget* status_area_widget) - : root_window_(status_area_widget->GetNativeView()->GetRootWindow()), - in_layout_(false), - auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER), - alignment_(SHELF_ALIGNMENT_BOTTOM), - launcher_(NULL), - status_area_widget_(status_area_widget), - workspace_controller_(NULL), - window_overlaps_shelf_(false), - gesture_drag_status_(GESTURE_DRAG_NONE), - gesture_drag_amount_(0.f), - gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), - update_shelf_observer_(NULL) { - Shell::GetInstance()->AddShellObserver(this); - aura::client::GetActivationClient(root_window_)->AddObserver(this); -} - -ShelfLayoutManager::~ShelfLayoutManager() { - if (update_shelf_observer_) - update_shelf_observer_->Detach(); - - FOR_EACH_OBSERVER(Observer, observers_, WillDeleteShelf()); - Shell::GetInstance()->RemoveShellObserver(this); - aura::client::GetActivationClient(root_window_)->RemoveObserver(this); -} - -void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) { - if (auto_hide_behavior_ == behavior) - return; - auto_hide_behavior_ = behavior; - UpdateVisibilityState(); - FOR_EACH_OBSERVER(Observer, observers_, - OnAutoHideStateChanged(state_.auto_hide_state)); -} - -bool ShelfLayoutManager::IsVisible() const { - return status_area_widget_->IsVisible() && - (state_.visibility_state == SHELF_VISIBLE || - (state_.visibility_state == SHELF_AUTO_HIDE && - state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)); -} - -void ShelfLayoutManager::SetLauncher(Launcher* launcher) { - if (launcher == launcher_) - return; - - launcher_ = launcher; - if (launcher_) - launcher_->SetAlignment(alignment_); - LayoutShelf(); -} - -bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) { - if (alignment_ == alignment) - return false; - - alignment_ = alignment; - if (launcher_) - launcher_->SetAlignment(alignment); - status_area_widget_->SetShelfAlignment(alignment); - LayoutShelf(); - return true; -} - -gfx::Rect ShelfLayoutManager::GetIdealBounds() { - // TODO(oshima): this is wrong. Figure out what display shelf is on - // and everything should be based on it. - gfx::Rect bounds(ScreenAsh::GetDisplayBoundsInParent( - status_area_widget_->GetNativeView())); - int width = 0, height = 0; - GetShelfSize(&width, &height); - return SelectValueForShelfAlignment( - gfx::Rect(bounds.x(), bounds.bottom() - height, bounds.width(), height), - gfx::Rect(bounds.x(), bounds.y(), width, bounds.height()), - gfx::Rect(bounds.right() - width, bounds.y(), width, bounds.height()), - gfx::Rect(bounds.x(), bounds.y(), bounds.width(), height)); -} - -void ShelfLayoutManager::LayoutShelf() { - base::AutoReset auto_reset_in_layout(&in_layout_, true); - StopAnimating(); - TargetBounds target_bounds; - CalculateTargetBounds(state_, &target_bounds); - if (launcher_widget()) { - GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity); - launcher_->SetWidgetBounds( - ScreenAsh::ConvertRectToScreen( - launcher_widget()->GetNativeView()->parent(), - target_bounds.launcher_bounds_in_root)); - launcher_->SetStatusSize(target_bounds.status_bounds_in_root.size()); - } - GetLayer(status_area_widget_)->SetOpacity(target_bounds.opacity); - status_area_widget_->SetBounds( - ScreenAsh::ConvertRectToScreen( - status_area_widget_->GetNativeView()->parent(), - target_bounds.status_bounds_in_root)); - Shell::GetInstance()->SetDisplayWorkAreaInsets( - root_window_, target_bounds.work_area_insets); - UpdateHitTestBounds(); -} - -ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { - switch(auto_hide_behavior_) { - case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: - return SHELF_AUTO_HIDE; - case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: - return SHELF_VISIBLE; - case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: - return SHELF_HIDDEN; - } - return SHELF_VISIBLE; -} - -ShelfVisibilityState -ShelfLayoutManager::CalculateShelfVisibilityWhileDragging() { - switch(auto_hide_behavior_) { - case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: - case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: - return SHELF_AUTO_HIDE; - case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: - return SHELF_HIDDEN; - } - return SHELF_VISIBLE; -} - -void ShelfLayoutManager::UpdateVisibilityState() { - ShellDelegate* delegate = Shell::GetInstance()->delegate(); - if (delegate && delegate->IsScreenLocked()) { - SetState(SHELF_VISIBLE); - } else if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) { - // TODO(zelidrag): Verify shelf drag animation still shows on the device - // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. - SetState(CalculateShelfVisibilityWhileDragging()); - } else if (GetRootWindowController(root_window_)->IsImmersiveMode()) { - // The user choosing immersive mode indicates he or she wants to maximize - // screen real-estate for content, so always auto-hide the shelf. - DCHECK_NE(auto_hide_behavior_, SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - SetState(SHELF_AUTO_HIDE); - } else { - WorkspaceWindowState window_state(workspace_controller_->GetWindowState()); - switch (window_state) { - case WORKSPACE_WINDOW_STATE_FULL_SCREEN: - SetState(SHELF_HIDDEN); - break; - - case WORKSPACE_WINDOW_STATE_MAXIMIZED: - SetState(CalculateShelfVisibility()); - break; - - case WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF: - case WORKSPACE_WINDOW_STATE_DEFAULT: - SetState(CalculateShelfVisibility()); - SetWindowOverlapsShelf(window_state == - WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF); - break; - } - } -} - -void ShelfLayoutManager::UpdateAutoHideState() { - ShelfAutoHideState auto_hide_state = - CalculateAutoHideState(state_.visibility_state); - if (auto_hide_state != state_.auto_hide_state) { - if (auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { - // Hides happen immediately. - SetState(state_.visibility_state); - FOR_EACH_OBSERVER(Observer, observers_, - OnAutoHideStateChanged(auto_hide_state)); - } else { - auto_hide_timer_.Stop(); - auto_hide_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kAutoHideDelayMS), - this, &ShelfLayoutManager::UpdateAutoHideStateNow); - FOR_EACH_OBSERVER(Observer, observers_, OnAutoHideStateChanged( - CalculateAutoHideState(state_.visibility_state))); - } - } else { - auto_hide_timer_.Stop(); - } -} - -void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { - window_overlaps_shelf_ = value; - UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); -} - -void ShelfLayoutManager::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void ShelfLayoutManager::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -//////////////////////////////////////////////////////////////////////////////// -// ShelfLayoutManager, Gesture dragging: - -void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) { - gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS; - gesture_drag_amount_ = 0.f; - gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE ? - auto_hide_state() : SHELF_AUTO_HIDE_SHOWN; - UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); -} - -ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag( - const ui::GestureEvent& gesture) { - bool horizontal = IsHorizontalAlignment(); - gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() : - gesture.details().scroll_x(); - LayoutShelf(); - - // Start reveling the status menu when: - // - dragging up on an already visible shelf - // - dragging up on a hidden shelf, but it is currently completely visible. - if (horizontal && gesture.details().scroll_y() < 0) { - int min_height = 0; - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && - launcher_widget()) - min_height = launcher_widget()->GetContentsView()-> - GetPreferredSize().height(); - - if (min_height < launcher_widget()->GetWindowBoundsInScreen().height() && - gesture.root_location().x() >= - status_area_widget_->GetWindowBoundsInScreen().x() && - IsDraggingTrayEnabled()) - return DRAG_TRAY; - } - - return DRAG_SHELF; -} - -void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { - bool horizontal = IsHorizontalAlignment(); - bool should_change = false; - if (gesture.type() == ui::ET_GESTURE_SCROLL_END) { - // The visibility of the shelf changes only if the shelf was dragged X% - // along the correct axis. If the shelf was already visible, then the - // direction of the drag does not matter. - const float kDragHideThreshold = 0.4f; - gfx::Rect bounds = GetIdealBounds(); - float drag_ratio = fabs(gesture_drag_amount_) / - (horizontal ? bounds.height() : bounds.width()); - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { - should_change = drag_ratio > kDragHideThreshold; - } else { - bool correct_direction = false; - switch (alignment_) { - case SHELF_ALIGNMENT_BOTTOM: - case SHELF_ALIGNMENT_RIGHT: - correct_direction = gesture_drag_amount_ < 0; - break; - case SHELF_ALIGNMENT_LEFT: - case SHELF_ALIGNMENT_TOP: - correct_direction = gesture_drag_amount_ > 0; - break; - } - should_change = correct_direction && drag_ratio > kDragHideThreshold; - } - } else if (gesture.type() == ui::ET_SCROLL_FLING_START) { - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { - should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 : - fabs(gesture.details().velocity_x()) > 0; - } else { - should_change = SelectValueForShelfAlignment( - gesture.details().velocity_y() < 0, - gesture.details().velocity_x() > 0, - gesture.details().velocity_x() < 0, - gesture.details().velocity_y() > 0); - } - } else { - NOTREACHED(); - } - - if (!should_change) { - CancelGestureDrag(); - return; - } - - gesture_drag_auto_hide_state_ = - gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ? - SHELF_AUTO_HIDE_HIDDEN : SHELF_AUTO_HIDE_SHOWN; - if (launcher_widget()) - launcher_widget()->Deactivate(); - status_area_widget_->Deactivate(); - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && - auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) { - gesture_drag_status_ = GESTURE_DRAG_NONE; - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - } else if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN && - auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER) { - gesture_drag_status_ = GESTURE_DRAG_NONE; - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - } else { - gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; - UpdateVisibilityState(); - gesture_drag_status_ = GESTURE_DRAG_NONE; - } -} - -void ShelfLayoutManager::CancelGestureDrag() { - gesture_drag_status_ = GESTURE_DRAG_NONE; - ui::ScopedLayerAnimationSettings - launcher_settings(GetLayer(launcher_widget())->GetAnimator()), - status_settings(GetLayer(status_area_widget_)->GetAnimator()); - LayoutShelf(); - UpdateVisibilityState(); - UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); -} - -//////////////////////////////////////////////////////////////////////////////// -// ShelfLayoutManager, aura::LayoutManager implementation: - -void ShelfLayoutManager::OnWindowResized() { - LayoutShelf(); -} - -void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) { -} - -void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { -} - -void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { -} - -void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) { -} - -void ShelfLayoutManager::SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) { - SetChildBoundsDirect(child, requested_bounds); - // We may contain other widgets (such as frame maximize bubble) but they don't - // effect the layout in anyway. - if (!in_layout_ && - ((launcher_widget() && launcher_widget()->GetNativeView() == child) || - (status_area_widget_->GetNativeView() == child))) { - LayoutShelf(); - } -} - -void ShelfLayoutManager::OnLockStateChanged(bool locked) { - UpdateVisibilityState(); -} - -void ShelfLayoutManager::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - UpdateAutoHideStateNow(); -} - -bool ShelfLayoutManager::IsHorizontalAlignment() const { - return alignment_ == SHELF_ALIGNMENT_BOTTOM || - alignment_ == SHELF_ALIGNMENT_TOP; -} - -// static -ShelfLayoutManager* ShelfLayoutManager::ForLauncher(aura::Window* window) { - return RootWindowController::ForLauncher(window)->shelf(); -} - -//////////////////////////////////////////////////////////////////////////////// -// ShelfLayoutManager, private: - -ShelfLayoutManager::TargetBounds::TargetBounds() : opacity(0.0f) {} - -void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { - ShellDelegate* delegate = Shell::GetInstance()->delegate(); - State state; - state.visibility_state = visibility_state; - state.auto_hide_state = CalculateAutoHideState(visibility_state); - state.is_screen_locked = delegate && delegate->IsScreenLocked(); - - // It's possible for SetState() when a window becomes maximized but the state - // won't have changed value. Do the dimming check before the early exit. - if (launcher_ && workspace_controller_) { - launcher_->SetDimsShelf( - (state.visibility_state == SHELF_VISIBLE) && - workspace_controller_->GetWindowState() == - WORKSPACE_WINDOW_STATE_MAXIMIZED); - } - - if (state_.Equals(state)) - return; // Nothing changed. - - FOR_EACH_OBSERVER(Observer, observers_, - WillChangeVisibilityState(visibility_state)); - - if (state.visibility_state == SHELF_AUTO_HIDE) { - // When state is SHELF_AUTO_HIDE we need to track when the mouse is over the - // launcher to unhide the shelf. AutoHideEventFilter does that for us. - if (!event_filter_.get()) - event_filter_.reset(new AutoHideEventFilter(this)); - } else { - event_filter_.reset(NULL); - } - - auto_hide_timer_.Stop(); - - // Animating the background when transitioning from auto-hide & hidden to - // visible is janky. Update the background immediately in this case. - BackgroundAnimator::ChangeType change_type = - (state_.visibility_state == SHELF_AUTO_HIDE && - state_.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN && - state.visibility_state == SHELF_VISIBLE) ? - BackgroundAnimator::CHANGE_IMMEDIATE : BackgroundAnimator::CHANGE_ANIMATE; - StopAnimating(); - - State old_state = state_; - state_ = state; - TargetBounds target_bounds; - CalculateTargetBounds(state_, &target_bounds); - if (launcher_widget()) { - ui::ScopedLayerAnimationSettings launcher_animation_setter( - GetLayer(launcher_widget())->GetAnimator()); - launcher_animation_setter.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS)); - launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT); - GetLayer(launcher_widget())->SetBounds( - target_bounds.launcher_bounds_in_root); - GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity); - } - ui::ScopedLayerAnimationSettings status_animation_setter( - GetLayer(status_area_widget_)->GetAnimator()); - status_animation_setter.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS)); - status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); - - // Delay updating the background when going from SHELF_AUTO_HIDE_SHOWN to - // SHELF_AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the - // animation you see the background change. - // Also delay the animation when the shelf was hidden, and has just been made - // visible (e.g. using a gesture-drag). - bool delay_shelf_update = - state.visibility_state == SHELF_AUTO_HIDE && - state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN && - old_state.visibility_state == SHELF_AUTO_HIDE; - - if (state.visibility_state == SHELF_VISIBLE && - old_state.visibility_state == SHELF_AUTO_HIDE && - old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) - delay_shelf_update = true; - - if (delay_shelf_update) { - if (update_shelf_observer_) - update_shelf_observer_->Detach(); - // UpdateShelfBackground deletes itself when the animation is done. - update_shelf_observer_ = new UpdateShelfObserver(this); - status_animation_setter.AddObserver(update_shelf_observer_); - } - ui::Layer* layer = GetLayer(status_area_widget_); - layer->SetBounds(target_bounds.status_bounds_in_root); - layer->SetOpacity(target_bounds.opacity); - Shell::GetInstance()->SetDisplayWorkAreaInsets( - root_window_, target_bounds.work_area_insets); - UpdateHitTestBounds(); - if (!delay_shelf_update) - UpdateShelfBackground(change_type); -} - -void ShelfLayoutManager::StopAnimating() { - ui::Layer* layer = GetLayer(status_area_widget_); - if (launcher_widget()) - layer->GetAnimator()->StopAnimating(); - layer->GetAnimator()->StopAnimating(); -} - -void ShelfLayoutManager::GetShelfSize(int* width, int* height) { - *width = *height = 0; - gfx::Size status_size(status_area_widget_->GetWindowBoundsInScreen().size()); - gfx::Size launcher_size = launcher_ ? - launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size(); - if (IsHorizontalAlignment()) - *height = std::max(launcher_size.height(), status_size.height()); - else - *width = std::max(launcher_size.width(), status_size.width()); -} - -void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset, - gfx::Rect* bounds) const { - bounds->Inset(SelectValueForShelfAlignment( - gfx::Insets(0, 0, inset, 0), - gfx::Insets(0, inset, 0, 0), - gfx::Insets(0, 0, 0, inset), - gfx::Insets(inset, 0, 0, 0))); -} - -void ShelfLayoutManager::CalculateTargetBounds( - const State& state, - TargetBounds* target_bounds) { - const gfx::Rect& available_bounds(root_window_->bounds()); - gfx::Rect status_size(status_area_widget_->GetWindowBoundsInScreen().size()); - gfx::Size launcher_size = launcher_ ? - launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size(); - int shelf_size = 0; - int shelf_width = 0, shelf_height = 0; - GetShelfSize(&shelf_width, &shelf_height); - if (state.visibility_state == SHELF_VISIBLE || - (state.visibility_state == SHELF_AUTO_HIDE && - state.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)) { - shelf_size = std::max(shelf_width, shelf_height); - launcher_size.set_width(std::max(shelf_width,launcher_size.width())); - launcher_size.set_height(std::max(shelf_height,launcher_size.height())); - } else if (state.visibility_state == SHELF_AUTO_HIDE && - state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { - shelf_size = kAutoHideSize; - // Keep the launcher to its full height when dragging is in progress. - if (gesture_drag_status_ == GESTURE_DRAG_NONE) { - if (IsHorizontalAlignment()) - launcher_size.set_height(kAutoHideSize); - else - launcher_size.set_width(kAutoHideSize); - } - } - switch(alignment_) { - case SHELF_ALIGNMENT_BOTTOM: - // The status widget should extend to the bottom and right edges. - target_bounds->status_bounds_in_root = gfx::Rect( - base::i18n::IsRTL() ? available_bounds.x() : - available_bounds.right() - status_size.width(), - available_bounds.bottom() - shelf_size + shelf_height - - status_size.height(), - status_size.width(), status_size.height()); - if (launcher_widget()) - target_bounds->launcher_bounds_in_root = gfx::Rect( - available_bounds.x(), - available_bounds.bottom() - shelf_size, - available_bounds.width(), - launcher_size.height()); - target_bounds->work_area_insets.Set( - 0, 0, GetWorkAreaSize(state, shelf_height), 0); - break; - case SHELF_ALIGNMENT_LEFT: - target_bounds->status_bounds_in_root = gfx::Rect( - available_bounds.x() + launcher_size.width() - status_size.width(), - available_bounds.bottom() - status_size.height(), - shelf_width, status_size.height()); - if (launcher_widget()) - target_bounds->launcher_bounds_in_root = gfx::Rect( - available_bounds.x(), available_bounds.y(), - launcher_size.width(), available_bounds.height()); - target_bounds->work_area_insets.Set( - 0, GetWorkAreaSize(state, launcher_size.width()), 0, 0); - break; - case SHELF_ALIGNMENT_RIGHT: - target_bounds->status_bounds_in_root = gfx::Rect( - available_bounds.right()- status_size.width() - - shelf_size + shelf_width, - available_bounds.bottom() - status_size.height(), - shelf_width, status_size.height()); - if (launcher_widget()) - target_bounds->launcher_bounds_in_root = gfx::Rect( - available_bounds.right() - launcher_size.width(), - available_bounds.y(), - launcher_size.width(), available_bounds.height()); - target_bounds->work_area_insets.Set( - 0, 0, 0, GetWorkAreaSize(state, launcher_size.width())); - break; - case SHELF_ALIGNMENT_TOP: - target_bounds->status_bounds_in_root = gfx::Rect( - base::i18n::IsRTL() ? available_bounds.x() : - available_bounds.right() - status_size.width(), - available_bounds.y() + launcher_size.height() - status_size.height(), - status_size.width(), status_size.height()); - if (launcher_widget()) - target_bounds->launcher_bounds_in_root = gfx::Rect( - available_bounds.x(), - available_bounds.y(), - available_bounds.width(), - launcher_size.height()); - target_bounds->work_area_insets.Set( - GetWorkAreaSize(state, shelf_height), 0, 0, 0); - break; - } - target_bounds->opacity = - (gesture_drag_status_ != GESTURE_DRAG_NONE || - state.visibility_state == SHELF_VISIBLE || - state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f; - if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS) - UpdateTargetBoundsForGesture(target_bounds); -} - -void ShelfLayoutManager::UpdateTargetBoundsForGesture( - TargetBounds* target_bounds) const { - CHECK_EQ(GESTURE_DRAG_IN_PROGRESS, gesture_drag_status_); - bool horizontal = IsHorizontalAlignment(); - int resistance_free_region = 0; - - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && - visibility_state() == SHELF_AUTO_HIDE && - auto_hide_state() != SHELF_AUTO_HIDE_SHOWN) { - // If the shelf was hidden when the drag started (and the state hasn't - // changed since then, e.g. because the tray-menu was shown because of the - // drag), then allow the drag some resistance-free region at first to make - // sure the shelf sticks with the finger until the shelf is visible. - resistance_free_region += horizontal ? - target_bounds->launcher_bounds_in_root.height() : - target_bounds->launcher_bounds_in_root.width(); - resistance_free_region -= kAutoHideSize; - } - - bool resist = SelectValueForShelfAlignment( - gesture_drag_amount_ < -resistance_free_region, - gesture_drag_amount_ > resistance_free_region, - gesture_drag_amount_ < -resistance_free_region, - gesture_drag_amount_ > resistance_free_region); - - float translate = 0.f; - if (resist) { - float diff = fabsf(gesture_drag_amount_) - resistance_free_region; - diff = std::min(diff, sqrtf(diff)); - if (gesture_drag_amount_ < 0) - translate = -resistance_free_region - diff; - else - translate = resistance_free_region + diff; - } else { - translate = gesture_drag_amount_; - } - - if (horizontal) { - // Move the launcher with the gesture. - target_bounds->launcher_bounds_in_root.Offset(0, translate); - target_bounds->status_bounds_in_root.Offset(0, translate); - - if (translate < 0) { - // When dragging up, the launcher height should increase. - float move = std::max(translate, - -static_cast(resistance_free_region)); - target_bounds->launcher_bounds_in_root.set_height( - target_bounds->launcher_bounds_in_root.height() + move - translate); - } - } else { - // Move the launcher with the gesture. - if (alignment_ == SHELF_ALIGNMENT_RIGHT) - target_bounds->launcher_bounds_in_root.Offset(translate, 0); - - if ((translate > 0 && alignment_ == SHELF_ALIGNMENT_RIGHT) || - (translate < 0 && alignment_ == SHELF_ALIGNMENT_LEFT)) { - // When dragging towards the edge, the statusbar should move. - target_bounds->status_bounds_in_root.Offset(translate, 0); - } else { - // When dragging away from the edge, the launcher width should increase. - float move = alignment_ == SHELF_ALIGNMENT_RIGHT ? - std::max(translate, -static_cast(resistance_free_region)) : - std::min(translate, static_cast(resistance_free_region)); - - if (alignment_ == SHELF_ALIGNMENT_RIGHT) { - target_bounds->launcher_bounds_in_root.set_width( - target_bounds->launcher_bounds_in_root.width() + move - translate); - } else { - target_bounds->launcher_bounds_in_root.set_width( - target_bounds->launcher_bounds_in_root.width() - move + translate); - } - - // The statusbar should be in the center. - gfx::Rect status_x = target_bounds->launcher_bounds_in_root; - status_x.ClampToCenteredSize( - target_bounds->status_bounds_in_root.size()); - target_bounds->status_bounds_in_root.set_x(status_x.x()); - } - } -} - -void ShelfLayoutManager::UpdateShelfBackground( - BackgroundAnimator::ChangeType type) { - bool launcher_paints = GetLauncherPaintsBackground(); - if (launcher_) - launcher_->SetPaintsBackground(launcher_paints, type); - // The status area normally draws a background, but we don't want it to draw a - // background when the launcher does or when we're at login/lock screen. - ShellDelegate* delegate = Shell::GetInstance()->delegate(); - bool delegate_allows_tray_bg = - delegate->IsUserLoggedIn() && !delegate->IsScreenLocked(); - bool status_area_paints = !launcher_paints && delegate_allows_tray_bg; - status_area_widget_->SetPaintsBackground(status_area_paints, type); -} - -bool ShelfLayoutManager::GetLauncherPaintsBackground() const { - return gesture_drag_status_ != GESTURE_DRAG_NONE || - (!state_.is_screen_locked && window_overlaps_shelf_) || - (state_.visibility_state == SHELF_AUTO_HIDE) ; -} - -void ShelfLayoutManager::UpdateAutoHideStateNow() { - SetState(state_.visibility_state); -} - -ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( - ShelfVisibilityState visibility_state) const { - if (visibility_state != SHELF_AUTO_HIDE || !launcher_widget()) - return SHELF_AUTO_HIDE_HIDDEN; - - if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) - return gesture_drag_auto_hide_state_; - - Shell* shell = Shell::GetInstance(); - if (shell->GetAppListTargetVisibility()) - return SHELF_AUTO_HIDE_SHOWN; - - if (status_area_widget_ && status_area_widget_->ShouldShowLauncher()) - return SHELF_AUTO_HIDE_SHOWN; - - if (launcher_ && launcher_->IsShowingMenu()) - return SHELF_AUTO_HIDE_SHOWN; - - if (launcher_ && launcher_->IsShowingOverflowBubble()) - return SHELF_AUTO_HIDE_SHOWN; - - if (launcher_widget()->IsActive() || status_area_widget_->IsActive()) - return SHELF_AUTO_HIDE_SHOWN; - - // Don't show if the user is dragging the mouse. - if (event_filter_.get() && event_filter_->in_mouse_drag()) - return SHELF_AUTO_HIDE_HIDDEN; - - gfx::Rect shelf_region = launcher_widget()->GetWindowBoundsInScreen(); - if (status_area_widget_ && - status_area_widget_->IsMessageBubbleShown() && - IsVisible()) { - // Increase the the hit test area to prevent the shelf from disappearing - // when the mouse is over the bubble gap. - shelf_region.Inset(alignment_ == SHELF_ALIGNMENT_RIGHT ? - -kNotificationBubbleGapHeight : 0, - alignment_ == SHELF_ALIGNMENT_BOTTOM ? - -kNotificationBubbleGapHeight : 0, - alignment_ == SHELF_ALIGNMENT_LEFT ? - -kNotificationBubbleGapHeight : 0, - alignment_ == SHELF_ALIGNMENT_TOP ? - -kNotificationBubbleGapHeight : 0); - } - - if (shelf_region.Contains(Shell::GetScreen()->GetCursorScreenPoint())) - return SHELF_AUTO_HIDE_SHOWN; - - const std::vector windows = - ash::WindowCycleController::BuildWindowList(NULL); - - // Process the window list and check if there are any visible windows. - for (size_t i = 0; i < windows.size(); ++i) { - if (windows[i] && windows[i]->IsVisible() && - !ash::wm::IsWindowMinimized(windows[i])) - return SHELF_AUTO_HIDE_HIDDEN; - } - - // If there are no visible windows do not hide the shelf. - return SHELF_AUTO_HIDE_SHOWN; -} - -void ShelfLayoutManager::UpdateHitTestBounds() { - gfx::Insets insets; - // Only modify the hit test when the shelf is visible, so we don't mess with - // hover hit testing in the auto-hide state. - if (state_.visibility_state == SHELF_VISIBLE) { - // Let clicks at the very top of the launcher through so windows can be - // resized with the bottom-right corner and bottom edge. - switch (alignment_) { - case SHELF_ALIGNMENT_BOTTOM: - insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0); - break; - case SHELF_ALIGNMENT_LEFT: - insets.Set(0, 0, 0, kWorkspaceAreaBottomInset); - break; - case SHELF_ALIGNMENT_RIGHT: - insets.Set(0, kWorkspaceAreaBottomInset, 0, 0); - break; - case SHELF_ALIGNMENT_TOP: - insets.Set(0, 0, kWorkspaceAreaBottomInset, 0); - break; - } - } - if (launcher_widget() && launcher_widget()->GetNativeWindow()) { - launcher_widget()->GetNativeWindow()->SetHitTestBoundsOverrideOuter( - insets, 1); - } - status_area_widget_->GetNativeWindow()-> - SetHitTestBoundsOverrideOuter(insets, 1); -} - -bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) { - if (!window) - return false; - return (launcher_widget() && - launcher_widget()->GetNativeWindow()->Contains(window)) || - (status_area_widget_->GetNativeWindow()->Contains(window)); -} - -int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const { - if (state.visibility_state == SHELF_VISIBLE) - return size; - if (state.visibility_state == SHELF_AUTO_HIDE) - return kAutoHideSize; - return 0; -} - -} // namespace internal -} // namespace ash diff --git a/ash/wm/shelf_layout_manager.h b/ash/wm/shelf_layout_manager.h deleted file mode 100644 index 01775bb..0000000 --- a/ash/wm/shelf_layout_manager.h +++ /dev/null @@ -1,338 +0,0 @@ -// 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. - -#ifndef ASH_WM_SHELF_LAYOUT_MANAGER_H_ -#define ASH_WM_SHELF_LAYOUT_MANAGER_H_ - -#include "ash/ash_export.h" -#include "ash/launcher/launcher.h" -#include "ash/shelf_types.h" -#include "ash/shell_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/observer_list.h" -#include "base/timer.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/layout_manager.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/rect.h" - -namespace aura { -class RootWindow; -} - -namespace ui { -class GestureEvent; -} - -namespace ash { -class ScreenAsh; -namespace internal { - -class ShelfLayoutManagerTest; -class StatusAreaWidget; -class WorkspaceController; - -// ShelfLayoutManager is the layout manager responsible for the launcher and -// status widgets. The launcher is given the total available width and told the -// width of the status area. This allows the launcher to draw the background and -// layout to the status area. -// To respond to bounds changes in the status area StatusAreaLayoutManager works -// closely with ShelfLayoutManager. -class ASH_EXPORT ShelfLayoutManager : - public aura::LayoutManager, - public ash::ShellObserver, - public aura::client::ActivationChangeObserver { - public: - class ASH_EXPORT Observer { - public: - // Called when the target ShelfLayoutManager will be deleted. - virtual void WillDeleteShelf() {} - - // Called when the visibility change is scheduled. - virtual void WillChangeVisibilityState(ShelfVisibilityState new_state) {} - - // Called when the auto hide state is changed. - virtual void OnAutoHideStateChanged(ShelfAutoHideState new_state) {} - }; - - // We reserve a small area at the bottom of the workspace area to ensure that - // the bottom-of-window resize handle can be hit. - static const int kWorkspaceAreaBottomInset; - - // Size of the shelf when auto-hidden. - static const int kAutoHideSize; - - explicit ShelfLayoutManager(StatusAreaWidget* status); - virtual ~ShelfLayoutManager(); - - // Sets the ShelfAutoHideBehavior. See enum description for details. - void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); - ShelfAutoHideBehavior auto_hide_behavior() const { - return auto_hide_behavior_; - } - - // Sets the alignment. Returns true if the alignment is changed. Otherwise, - // returns false. - bool SetAlignment(ShelfAlignment alignment); - ShelfAlignment GetAlignment() const { return alignment_; } - - void set_workspace_controller(WorkspaceController* controller) { - workspace_controller_ = controller; - } - - views::Widget* launcher_widget() { - return launcher_ ? launcher_->widget() : NULL; - } - const views::Widget* launcher_widget() const { - return launcher_ ? launcher_->widget() : NULL; - } - StatusAreaWidget* status_area_widget() { return status_area_widget_; } - - bool in_layout() const { return in_layout_; } - - // Returns whether the shelf and its contents (launcher, status) are visible - // on the screen. - bool IsVisible() const; - - // The launcher is typically created after the layout manager. - void SetLauncher(Launcher* launcher); - Launcher* launcher() { return launcher_; } - - // Returns the ideal bounds of the shelf assuming it is visible. - gfx::Rect GetIdealBounds(); - - // Stops any animations and sets the bounds of the launcher and status - // widgets. - void LayoutShelf(); - - // Returns shelf visibility state based on current value of auto hide - // behavior setting. - ShelfVisibilityState CalculateShelfVisibility(); - - // Returns shelf visibility state based on current value of auto hide - // behavior setting. - ShelfVisibilityState CalculateShelfVisibilityWhileDragging(); - - // Updates the visibility state. - void UpdateVisibilityState(); - - // Invoked by the shelf/launcher when the auto-hide state may have changed. - void UpdateAutoHideState(); - - ShelfVisibilityState visibility_state() const { - return state_.visibility_state; - } - ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } - - // Sets whether any windows overlap the shelf. If a window overlaps the shelf - // the shelf renders slightly differently. - void SetWindowOverlapsShelf(bool value); - bool window_overlaps_shelf() const { return window_overlaps_shelf_; } - - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - // Gesture dragging related functions: - void StartGestureDrag(const ui::GestureEvent& gesture); - enum DragState { - DRAG_SHELF, - DRAG_TRAY - }; - // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf. - // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from - // this point on. - DragState UpdateGestureDrag(const ui::GestureEvent& gesture); - void CompleteGestureDrag(const ui::GestureEvent& gesture); - void CancelGestureDrag(); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // Overridden from ash::ShellObserver: - virtual void OnLockStateChanged(bool locked) OVERRIDE; - - // Overriden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - // TODO(harrym|oshima): These templates will be moved to - // new Shelf class. - // A helper function that provides a shortcut for choosing - // values specific to a shelf alignment. - template - T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const { - switch (alignment_) { - case SHELF_ALIGNMENT_BOTTOM: - return bottom; - case SHELF_ALIGNMENT_LEFT: - return left; - case SHELF_ALIGNMENT_RIGHT: - return right; - case SHELF_ALIGNMENT_TOP: - return top; - } - NOTREACHED(); - return right; - } - - template - T PrimaryAxisValue(T horizontal, T vertical) const { - return IsHorizontalAlignment() ? horizontal : vertical; - } - - // Is the shelf's alignment horizontal? - bool IsHorizontalAlignment() const; - - // Returns a ShelfLayoutManager on the display which has a launcher for - // given |window|. See RootWindowController::ForLauncher for more info. - static ShelfLayoutManager* ForLauncher(aura::Window* window); - - private: - class AutoHideEventFilter; - class UpdateShelfObserver; - friend class ash::ScreenAsh; - friend class ShelfLayoutManagerTest; - - struct TargetBounds { - TargetBounds(); - - float opacity; - gfx::Rect launcher_bounds_in_root; - gfx::Rect status_bounds_in_root; - gfx::Insets work_area_insets; - }; - - struct State { - State() : visibility_state(SHELF_VISIBLE), - auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), - is_screen_locked(false) {} - - // Returns true if the two states are considered equal. As - // |auto_hide_state| only matters if |visibility_state| is - // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as - // appropriate. - bool Equals(const State& other) const { - return other.visibility_state == visibility_state && - (visibility_state != SHELF_AUTO_HIDE || - other.auto_hide_state == auto_hide_state) && - other.is_screen_locked == is_screen_locked; - } - - ShelfVisibilityState visibility_state; - ShelfAutoHideState auto_hide_state; - bool is_screen_locked; - }; - - // Sets the visibility of the shelf to |state|. - void SetState(ShelfVisibilityState visibility_state); - - // Stops any animations. - void StopAnimating(); - - // Returns the width (if aligned to the side) or height (if aligned to the - // bottom). - void GetShelfSize(int* width, int* height); - - // Insets |bounds| by |inset| on the edge the shelf is aligned to. - void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const; - - // Calculates the target bounds assuming visibility of |visible|. - void CalculateTargetBounds(const State& state, TargetBounds* target_bounds); - - // Updates the target bounds if a gesture-drag is in progress. This is only - // used by |CalculateTargetBounds()|. - void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const; - - // Updates the background of the shelf. - void UpdateShelfBackground(BackgroundAnimator::ChangeType type); - - // Returns whether the launcher should draw a background. - bool GetLauncherPaintsBackground() const; - - // Updates the auto hide state immediately. - void UpdateAutoHideStateNow(); - - // Returns the AutoHideState. This value is determined from the launcher and - // tray. - ShelfAutoHideState CalculateAutoHideState( - ShelfVisibilityState visibility_state) const; - - // Updates the hit test bounds override for launcher and status area. - void UpdateHitTestBounds(); - - // Returns true if |window| is a descendant of the shelf. - bool IsShelfWindow(aura::Window* window); - - int GetWorkAreaSize(const State& state, int size) const; - - // The RootWindow is cached so that we don't invoke Shell::GetInstance() from - // our destructor. We avoid that as at the time we're deleted Shell is being - // deleted too. - aura::RootWindow* root_window_; - - // True when inside LayoutShelf method. Used to prevent calling LayoutShelf - // again from SetChildBounds(). - bool in_layout_; - - // See description above setter. - ShelfAutoHideBehavior auto_hide_behavior_; - - ShelfAlignment alignment_; - - // Current state. - State state_; - - Launcher* launcher_; - StatusAreaWidget* status_area_widget_; - - WorkspaceController* workspace_controller_; - - // Do any windows overlap the shelf? This is maintained by WorkspaceManager. - bool window_overlaps_shelf_; - - base::OneShotTimer auto_hide_timer_; - - // EventFilter used to detect when user moves the mouse over the launcher to - // trigger showing the launcher. - scoped_ptr event_filter_; - - ObserverList observers_; - - // The shelf reacts to gesture-drags, and can be set to auto-hide for certain - // gestures. Some shelf behaviour (e.g. visibility state, background color - // etc.) are affected by various stages of the drag. The enum keeps track of - // the present status of the gesture drag. - enum GestureDragStatus { - GESTURE_DRAG_NONE, - GESTURE_DRAG_IN_PROGRESS, - GESTURE_DRAG_COMPLETE_IN_PROGRESS - }; - GestureDragStatus gesture_drag_status_; - - // Tracks the amount of the drag. The value is only valid when - // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS. - float gesture_drag_amount_; - - // Manage the auto-hide state during the gesture. - ShelfAutoHideState gesture_drag_auto_hide_state_; - - // Used to delay updating shelf background. - UpdateShelfObserver* update_shelf_observer_; - - DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SHELF_LAYOUT_MANAGER_H_ diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc deleted file mode 100644 index 2de43a5..0000000 --- a/ash/wm/shelf_layout_manager_unittest.cc +++ /dev/null @@ -1,1132 +0,0 @@ -// 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/wm/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_manager.h" -#include "ash/focus_cycler.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_delegate.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_util.h" -#include "base/command_line.h" -#include "base/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/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( - widget->GetNativeView()->layer()->GetAnimator()); - element->Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1)); -} - -ShelfLayoutManager* GetShelfLayoutManager() { - return Shell::GetPrimaryRootWindowController()->shelf(); -} - -SystemTray* GetSystemTray() { - return Shell::GetPrimaryRootWindowController()->GetSystemTray(); -} - -class ShelfLayoutObserverTest : public ShelfLayoutManager::Observer { - 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(); - } - private: - DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest); -}; - -// 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) { - ShelfLayoutManager* shelf = GetShelfLayoutManager(); - // Force an initial layout. - shelf->LayoutShelf(); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - - gfx::Rect status_bounds( - shelf->status_area_widget()->GetWindowBoundsInScreen()); - gfx::Rect launcher_bounds( - shelf->launcher_widget()->GetWindowBoundsInScreen()); - int shelf_height = shelf->GetIdealBounds().height(); - - const gfx::Display& display = Shell::GetInstance()->display_manager()-> - GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - ASSERT_NE(-1, display.id()); - // Bottom inset should be the max of widget heights. - EXPECT_EQ(shelf_height, - display.bounds().bottom() - display.work_area().bottom()); - - // Hide the shelf. - SetState(shelf, SHELF_HIDDEN); - // Run the animation to completion. - StepWidgetLayerAnimatorToEnd(shelf->launcher_widget()); - StepWidgetLayerAnimatorToEnd(shelf->status_area_widget()); - EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); - EXPECT_EQ(0, - display.bounds().bottom() - display.work_area().bottom()); - - // Make sure the bounds of the two widgets changed. - EXPECT_GE(shelf->launcher_widget()->GetNativeView()->bounds().y(), - Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom()); - EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(), - Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom()); - - // And show it again. - SetState(shelf, SHELF_VISIBLE); - // Run the animation to completion. - StepWidgetLayerAnimatorToEnd(shelf->launcher_widget()); - StepWidgetLayerAnimatorToEnd(shelf->status_area_widget()); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - EXPECT_EQ(shelf_height, - display.bounds().bottom() - display.work_area().bottom()); - - // Make sure the bounds of the two widgets changed. - launcher_bounds = shelf->launcher_widget()->GetNativeView()->bounds(); - int bottom = - Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom() - shelf_height; - EXPECT_EQ(launcher_bounds.y(), - bottom + (shelf->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) { - ShelfLayoutManager* shelf = GetShelfLayoutManager(); - // Force an initial layout. - shelf->LayoutShelf(); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - - const gfx::Display& display = Shell::GetInstance()->display_manager()-> - GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - - // Hide the shelf. - SetState(shelf, SHELF_HIDDEN); - shelf->LayoutShelf(); - EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); - EXPECT_EQ(0, display.bounds().bottom() - display.work_area().bottom()); - - // Make sure the bounds of the two widgets changed. - EXPECT_GE(shelf->launcher_widget()->GetNativeView()->bounds().y(), - Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom()); - EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(), - Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom()); -} - -// Makes sure the launcher is initially sized correctly. -TEST_F(ShelfLayoutManagerTest, LauncherInitiallySized) { - Launcher* launcher = Launcher::ForPrimaryDisplay(); - ASSERT_TRUE(launcher); - ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManager(); - ASSERT_TRUE(shelf_layout_manager); - ASSERT_TRUE(shelf_layout_manager->status_area_widget()); - int status_width = shelf_layout_manager->status_area_widget()-> - GetWindowBoundsInScreen().width(); - // Test only makes sense if the status is > 0, which is better be. - EXPECT_GT(status_width, 0); - EXPECT_EQ(status_width, launcher->status_size().width()); -} - -// Makes sure the launcher is sized when the status area changes size. -TEST_F(ShelfLayoutManagerTest, LauncherUpdatedWhenStatusAreaChangesSize) { - Launcher* launcher = Launcher::ForPrimaryDisplay(); - ASSERT_TRUE(launcher); - ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManager(); - ASSERT_TRUE(shelf_layout_manager); - ASSERT_TRUE(shelf_layout_manager->status_area_widget()); - shelf_layout_manager->status_area_widget()->SetBounds( - gfx::Rect(0, 0, 200, 200)); - EXPECT_EQ(200, launcher->status_size().width()); -} - -// Verifies when the shell is deleted with a full screen window we don't -// crash. This test is here as originally the crash was in ShelfLayoutManager. -TEST_F(ShelfLayoutManagerTest, DontReferenceLauncherAfterDeletion) { - 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->SetFullscreen(true); -} - -#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, - shelf->launcher_widget()->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(), - shelf->launcher_widget()->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, - shelf->launcher_widget()->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()); -} - -// 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, - shelf->launcher_widget()->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()->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()->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()); -} - -// 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. - shelf->launcher()->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). - shelf->status_area_widget()->Activate(); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - - shelf->launcher()->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(); - internal::RootWindowController* controller = - Shell::GetPrimaryRootWindowController(); - ShelfLayoutManager* shelf = GetShelfLayoutManager(); - shelf->LayoutShelf(); - controller->SetShelfAutoHideBehavior(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(); - internal::RootWindowController* controller = - Shell::GetPrimaryRootWindowController(); - shelf->LayoutShelf(); - controller->SetShelfAutoHideBehavior(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( - shelf->launcher_widget()->GetWindowBoundsInScreen()); - const internal::DisplayManager* manager = - Shell::GetInstance()->display_manager(); - gfx::Display display = - manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - ASSERT_NE(-1, display.id()); - EXPECT_EQ(shelf->GetIdealBounds().width(), - display.GetWorkAreaInsets().left()); - EXPECT_GE( - launcher_bounds.width(), - shelf->launcher_widget()->GetContentsView()->GetPreferredSize().width()); - EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment()); - StatusAreaWidget* status_area_widget = shelf->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 = manager->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 = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - launcher_bounds = shelf->launcher_widget()->GetWindowBoundsInScreen(); - display = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - ASSERT_NE(-1, display.id()); - EXPECT_EQ(shelf->GetIdealBounds().width(), - display.GetWorkAreaInsets().right()); - EXPECT_GE(launcher_bounds.width(), - shelf->launcher_widget()->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 = manager->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 = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - launcher_bounds = shelf->launcher_widget()->GetWindowBoundsInScreen(); - display = manager->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow()); - ASSERT_NE(-1, display.id()); - EXPECT_EQ(shelf->GetIdealBounds().height(), - display.GetWorkAreaInsets().top()); - EXPECT_GE(launcher_bounds.height(), - shelf->launcher_widget()->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 = manager->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(); - internal::RootWindowController* controller = - Shell::GetPrimaryRootWindowController(); - controller->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - shelf->LayoutShelf(); - - 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(); - - gfx::Rect shelf_shown = shelf->launcher_widget()->GetWindowBoundsInScreen(); - gfx::Rect bounds_shelf = window->bounds(); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - - // Swipe up on the shelf. This should not change any state. - gfx::Point start = - shelf->launcher_widget()->GetWindowBoundsInScreen().CenterPoint(); - gfx::Point end(start.x(), start.y() + 100); - - // Swipe down on the shelf to hide it. - end.set_y(start.y() + 100); - 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()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior()); - EXPECT_NE(bounds_shelf.ToString(), window->bounds().ToString()); - EXPECT_NE(shelf_shown.ToString(), - shelf->launcher_widget()->GetWindowBoundsInScreen().ToString()); - - gfx::Rect bounds_noshelf = window->bounds(); - gfx::Rect shelf_hidden = shelf->launcher_widget()->GetWindowBoundsInScreen(); - - // Swipe up to show the shelf. - generator.GestureScrollSequence(end, start, - base::TimeDelta::FromMilliseconds(10), 1); - 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(), - shelf->launcher_widget()->GetWindowBoundsInScreen().ToString()); - - // Swipe up again. The shelf should hide. - end.set_y(start.y() - 100); - 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()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior()); - EXPECT_EQ(shelf_hidden.ToString(), - shelf->launcher_widget()->GetWindowBoundsInScreen().ToString()); - - // Swipe up yet again to show it. - end.set_y(start.y() + 100); - generator.GestureScrollSequence(end, start, - base::TimeDelta::FromMilliseconds(10), 1); - - // Swipe down very little. It shouldn't change any state. - end.set_y(start.y() + shelf_shown.height() * 3 / 10); - generator.GestureScrollSequence(start, end, - base::TimeDelta::FromMilliseconds(100), 1); - 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(), - shelf->launcher_widget()->GetWindowBoundsInScreen().ToString()); - - // Swipe down again to hide. - end.set_y(start.y() + 100); - 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()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior()); - EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString()); - EXPECT_EQ(shelf_hidden.ToString(), - shelf->launcher_widget()->GetWindowBoundsInScreen().ToString()); - - // Swipe up yet again to show it. - end.set_y(start.y() + 100); - generator.GestureScrollSequence(end, start, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior()); - - // Tap on the shelf itself. This should not change anything. - generator.GestureTapAt(start); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior()); - - // Now, tap on the desktop region (above the shelf). This should hide the - // shelf. - gfx::Point tap = start + gfx::Vector2d(0, -90); - generator.GestureTapAt(tap); - 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()); - - // Make the window fullscreen. - widget->SetFullscreen(true); - gfx::Rect bounds_fullscreen = window->bounds(); - EXPECT_TRUE(widget->IsFullscreen()); - EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString()); - EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); - - // Swipe-up. This should not change anything. - generator.GestureScrollSequence(end, start, - base::TimeDelta::FromMilliseconds(10), 1); - 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()); -} - -TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) { - 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(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state()); - - // Window closed => auto hide disabled. - dummy->CloseNow(); - shelf->UpdateVisibilityState(); - 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 - shelf->UpdateVisibilityState(); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - - // either minimzed => normal autohide - window2->Minimize(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - window2->Restore(); - window1->Minimize(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - - // both minimzed => disable auto hide - window2->Minimize(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_GestureRevealsTrayBubble DISABLED_GestureRevealsTrayBubble -#else -#define MAYBE_GestureRevealsTrayBubble GestureRevealsTrayBubble -#endif - -TEST_F(ShelfLayoutManagerTest, MAYBE_GestureRevealsTrayBubble) { - 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 = - shelf->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->CloseBubbleForTest(); - 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()); - - // Now hide the shelf. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - - // The active maximized window will get resized to the new work area. However, - // the inactive window should not get resized. - EXPECT_NE(widget_one->GetNativeWindow()->bounds().ToString(), - widget_two->GetNativeWindow()->bounds().ToString()); - - // Activate the first window. Now, both windows should be of the same size - // again. - widget_one->Activate(); - EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(), - widget_two->GetNativeWindow()->bounds().ToString()); - - // Now show the shelf. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - - // The active maximized window will get resized to the new work area. However, - // the inactive window should not get resized. - EXPECT_NE(widget_one->GetNativeWindow()->bounds().ToString(), - widget_two->GetNativeWindow()->bounds().ToString()); - - // Activate the first window. Now, both windows should be of the same size - // again. - widget_two->Activate(); - EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(), - widget_two->GetNativeWindow()->bounds().ToString()); -} - -// 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 w1(CreateTestWindow()); - w1->Show(); - wm::ActivateWindow(w1.get()); - - // Normal window doesn't dim shelf. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - Launcher* launcher = Launcher::ForPrimaryDisplay(); - EXPECT_FALSE(launcher->GetDimsShelf()); - - // Maximized window does. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_TRUE(launcher->GetDimsShelf()); - - // Change back to normal stops dimming. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_FALSE(launcher->GetDimsShelf()); - - // Changing back to maximized dims again. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_TRUE(launcher->GetDimsShelf()); - - // Changing shelf to autohide stops dimming. - GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - EXPECT_FALSE(launcher->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()->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->CloseBubbleForTest(); - 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()); - } - } -} - -} // namespace internal -} // namespace ash diff --git a/ash/wm/stacking_controller_unittest.cc b/ash/wm/stacking_controller_unittest.cc index bf4d1fd..6f5d1f8 100644 --- a/ash/wm/stacking_controller_unittest.cc +++ b/ash/wm/stacking_controller_unittest.cc @@ -41,7 +41,7 @@ TEST_F(StackingControllerTest, TransientParent) { scoped_ptr w2(CreateTestWindow()); w2->SetBounds(gfx::Rect(10, 11, 250, 251)); aura::Window* launcher = Shell::GetContainer(Shell::GetPrimaryRootWindow(), - kShellWindowId_LauncherContainer); + kShellWindowId_ShelfContainer); launcher->AddChild(w2.get()); w2->Show(); diff --git a/ash/wm/status_area_layout_manager.cc b/ash/wm/status_area_layout_manager.cc index df37969..e17d84e 100644 --- a/ash/wm/status_area_layout_manager.cc +++ b/ash/wm/status_area_layout_manager.cc @@ -4,8 +4,9 @@ #include "ash/wm/status_area_layout_manager.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/system/status_area_widget.h" -#include "ash/wm/shelf_layout_manager.h" #include "base/auto_reset.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h" @@ -16,7 +17,7 @@ namespace internal { //////////////////////////////////////////////////////////////////////////////// // StatusAreaLayoutManager, public: -StatusAreaLayoutManager::StatusAreaLayoutManager(ShelfLayoutManager* shelf) +StatusAreaLayoutManager::StatusAreaLayoutManager(ShelfWidget* shelf) : in_layout_(false), shelf_(shelf) { } @@ -69,11 +70,11 @@ void StatusAreaLayoutManager::SetChildBounds( void StatusAreaLayoutManager::LayoutStatusArea() { // Shelf layout manager may be already doing layout. - if (shelf_->in_layout()) + if (shelf_->shelf_layout_manager()->in_layout()) return; base::AutoReset auto_reset_in_layout(&in_layout_, true); - shelf_->LayoutShelf(); + shelf_->shelf_layout_manager()->LayoutShelf(); } } // namespace internal diff --git a/ash/wm/status_area_layout_manager.h b/ash/wm/status_area_layout_manager.h index cd12fe1..8e6944d 100644 --- a/ash/wm/status_area_layout_manager.h +++ b/ash/wm/status_area_layout_manager.h @@ -10,16 +10,15 @@ #include "ui/aura/layout_manager.h" namespace ash { +class ShelfWidget; namespace internal { -class ShelfLayoutManager; - // StatusAreaLayoutManager is a layout manager responsible for the status area. // In any case when status area needs relayout it redirects this call to // ShelfLayoutManager. class StatusAreaLayoutManager : public aura::LayoutManager { public: - explicit StatusAreaLayoutManager(ShelfLayoutManager* shelf); + explicit StatusAreaLayoutManager(ShelfWidget* shelf); virtual ~StatusAreaLayoutManager(); // Overridden from aura::LayoutManager: @@ -41,7 +40,7 @@ class StatusAreaLayoutManager : public aura::LayoutManager { // Used to prevent calling itself again from SetChildBounds(). bool in_layout_; - ShelfLayoutManager* shelf_; + ShelfWidget* shelf_; DISALLOW_COPY_AND_ASSIGN(StatusAreaLayoutManager); }; diff --git a/ash/wm/workspace/frame_maximize_button.cc b/ash/wm/workspace/frame_maximize_button.cc index 751b5c6..9cf663e 100644 --- a/ash/wm/workspace/frame_maximize_button.cc +++ b/ash/wm/workspace/frame_maximize_button.cc @@ -6,6 +6,7 @@ #include "ash/launcher/launcher.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/wm/maximize_bubble_controller.h" @@ -471,7 +472,7 @@ gfx::Rect FrameMaximizeButton::ScreenBoundsForType( item_rect.Inset(-8, -8); return item_rect; } - return launcher->widget()->GetWindowBoundsInScreen(); + return launcher->shelf_widget()->GetWindowBoundsInScreen(); } case SNAP_RESTORE: { const gfx::Rect* restore = GetRestoreBoundsInScreen(window); diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc index 2a60434..0127966 100644 --- a/ash/wm/workspace/phantom_window_controller.cc +++ b/ash/wm/workspace/phantom_window_controller.cc @@ -127,7 +127,7 @@ void PhantomWindowController::CreatePhantomWidget(const gfx::Rect& bounds) { // launcher button. Put the phantom in the same window as the launcher so that // the phantom is visible. params.parent = Shell::GetContainer(wm::GetRootWindowMatching(bounds), - kShellWindowId_LauncherContainer); + kShellWindowId_ShelfContainer); params.can_activate = false; params.keep_on_top = true; phantom_widget_->set_focus_on_creation(false); diff --git a/ash/wm/workspace/workspace_cycler_animator.cc b/ash/wm/workspace/workspace_cycler_animator.cc index 0575c02..b02aa8b 100644 --- a/ash/wm/workspace/workspace_cycler_animator.cc +++ b/ash/wm/workspace/workspace_cycler_animator.cc @@ -10,9 +10,10 @@ #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell_window_ids.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_properties.h" #include "ash/wm/workspace/colored_window_controller.h" #include "ash/wm/workspace/workspace.h" @@ -671,17 +672,16 @@ void WorkspaceCyclerAnimator::CreateLauncherBackground() { if (screen_bounds_ == maximized_bounds_) return; - aura::Window* random_workspace_window = workspaces_[0]->window(); - ash::Launcher* launcher = ash::Launcher::ForWindow(random_workspace_window); - aura::Window* launcher_window = launcher->widget()->GetNativeWindow(); - // TODO(pkotwicz): Figure out what to do when the launcher visible state is // SHELF_AUTO_HIDE. ShelfLayoutManager* shelf_layout_manager = - ShelfLayoutManager::ForLauncher(launcher_window); + ShelfLayoutManager::ForLauncher(workspaces_[0]->window()); if (!shelf_layout_manager->IsVisible()) return; + aura::Window* launcher_window = shelf_layout_manager->shelf_widget()-> + GetNativeWindow(); + gfx::Rect shelf_bounds = shelf_layout_manager->GetIdealBounds(); launcher_background_controller_.reset(new ColoredWindowController( diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index 93f0f16..8026f20 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc @@ -5,10 +5,11 @@ #include "ash/wm/workspace/workspace_layout_manager.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_util.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" @@ -57,8 +58,8 @@ class DontClobberRestoreBoundsWindowObserver : public aura::WindowObserver { aura::Window* w = window_; window_ = NULL; - gfx::Rect shelf_bounds( - Shell::GetPrimaryRootWindowController()->shelf()->GetIdealBounds()); + gfx::Rect shelf_bounds(Shell::GetPrimaryRootWindowController()-> + GetShelfLayoutManager()->GetIdealBounds()); const gfx::Rect& window_bounds(w->bounds()); w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1, window_bounds.width(), window_bounds.height())); diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc index e1302e7..951adf5 100644 --- a/ash/wm/workspace/workspace_manager.cc +++ b/ash/wm/workspace/workspace_manager.cc @@ -8,12 +8,12 @@ #include #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/wm/base_layout_manager.h" #include "ash/wm/frame_painter.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" diff --git a/ash/wm/workspace/workspace_manager_unittest.cc b/ash/wm/workspace/workspace_manager_unittest.cc index 1ce1abf..d15bde4 100644 --- a/ash/wm/workspace/workspace_manager_unittest.cc +++ b/ash/wm/workspace/workspace_manager_unittest.cc @@ -7,6 +7,8 @@ #include "ash/ash_switches.h" #include "ash/root_window_controller.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/system/status_area_widget.h" @@ -14,7 +16,6 @@ #include "ash/test/shell_test_api.h" #include "ash/wm/activation_controller.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace/workspace.h" @@ -76,10 +77,14 @@ class WorkspaceManagerTest : public test::AshTestBase { return manager_->active_workspace_; } - ShelfLayoutManager* shelf_layout_manager() { + ShelfWidget* shelf_widget() { return Shell::GetPrimaryRootWindowController()->shelf(); } + ShelfLayoutManager* shelf_layout_manager() { + return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); + } + bool GetWindowOverlapsShelf() { return shelf_layout_manager()->window_overlaps_shelf(); } @@ -815,7 +820,7 @@ TEST_F(WorkspaceManagerTest, MinimizeResetsVisibility) { w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); EXPECT_EQ(SHELF_VISIBLE, shelf_layout_manager()->visibility_state()); - EXPECT_FALSE(Launcher::ForPrimaryDisplay()->paints_background()); + EXPECT_FALSE(shelf_widget()->paints_background()); } // Verifies transients are moved when maximizing. @@ -960,9 +965,10 @@ TEST_F(WorkspaceManagerTest, MoveOnSwitch) { // Increase the size of the shelf. This would make |w1| fall completely out of // the display work area. - gfx::Size size(shelf->status_area_widget()->GetWindowBoundsInScreen().size()); + gfx::Size size(shelf_widget()->status_area_widget()-> + GetWindowBoundsInScreen().size()); size.Enlarge(0, 30); - shelf->status_area_widget()->SetSize(size); + shelf_widget()->status_area_widget()->SetSize(size); // Switch to w1. The window should have moved. wm::ActivateWindow(w1.get()); diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc index 87184e9..d3cf8be 100644 --- a/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc @@ -7,11 +7,11 @@ #include "ash/display/display_controller.h" #include "ash/root_window_controller.h" #include "ash/screen_ash.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/wm/property_util.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace/phantom_window_controller.h" #include "ash/wm/workspace/snap_sizer.h" @@ -146,7 +146,7 @@ class WorkspaceWindowResizerTest : public test::AshTestBase { } internal::ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->shelf(); + return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); } TestWindowDelegate delegate_; @@ -802,8 +802,8 @@ TEST_F(WorkspaceWindowResizerTest, // Verifies snapping to edges works. TEST_F(WorkspaceWindowResizerTest, SnapToEdge) { - Shell::GetPrimaryRootWindowController()-> - SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> + SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); window_->SetBounds(gfx::Rect(96, 112, 320, 160)); scoped_ptr resizer(WorkspaceWindowResizer::Create( window_.get(), gfx::Point(), HTCAPTION, empty_windows())); -- cgit v1.1