diff options
-rw-r--r-- | ash/focus_cycler_unittest.cc | 25 | ||||
-rw-r--r-- | ash/launcher/launcher.cc | 11 | ||||
-rw-r--r-- | ash/launcher/launcher.h | 1 | ||||
-rw-r--r-- | ash/status_area/status_area_view.cc | 11 | ||||
-rw-r--r-- | ash/system/tray/system_tray.cc | 4 | ||||
-rw-r--r-- | ash/wm/shelf_layout_manager.cc | 16 | ||||
-rw-r--r-- | ash/wm/shelf_layout_manager.h | 19 | ||||
-rw-r--r-- | ash/wm/shelf_layout_manager_unittest.cc | 32 |
8 files changed, 106 insertions, 13 deletions
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc index 9bc23b9..7a5bec9 100644 --- a/ash/focus_cycler_unittest.cc +++ b/ash/focus_cycler_unittest.cc @@ -23,6 +23,15 @@ using aura::test::CreateTestWindowWithId; using aura::Window; using internal::FocusCycler; +namespace { + +internal::StatusAreaView* GetStatusAreaView(views::Widget* widget) { + return static_cast<internal::StatusAreaView*>( + widget->GetContentsView()->child_at(0)); +} + +} // namespace + typedef AshTestBase FocusCyclerTest; TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) { @@ -48,8 +57,8 @@ TEST_F(FocusCyclerTest, CycleFocusForward) { views::Widget* status_widget = internal::CreateStatusArea(NULL); ASSERT_TRUE(status_widget); focus_cycler->AddWidget(status_widget); - static_cast<internal::StatusAreaView*>(status_widget->GetContentsView())-> - SetFocusCyclerForTesting(focus_cycler.get()); + GetStatusAreaView(status_widget)->SetFocusCyclerForTesting( + focus_cycler.get()); // Add a mock button to the status area. status_widget->GetContentsView()->AddChildView( @@ -90,8 +99,8 @@ TEST_F(FocusCyclerTest, CycleFocusBackward) { views::Widget* status_widget = internal::CreateStatusArea(NULL); ASSERT_TRUE(status_widget); focus_cycler->AddWidget(status_widget); - static_cast<internal::StatusAreaView*>(status_widget->GetContentsView())-> - SetFocusCyclerForTesting(focus_cycler.get()); + GetStatusAreaView(status_widget)->SetFocusCyclerForTesting( + focus_cycler.get()); // Add a mock button to the status area. status_widget->GetContentsView()->AddChildView( @@ -163,8 +172,8 @@ TEST_F(FocusCyclerLauncherTest, CycleFocusForwardInvisible) { views::Widget* status_widget = internal::CreateStatusArea(NULL); ASSERT_TRUE(status_widget); focus_cycler->AddWidget(status_widget); - static_cast<internal::StatusAreaView*>(status_widget->GetContentsView())-> - SetFocusCyclerForTesting(focus_cycler.get()); + GetStatusAreaView(status_widget)->SetFocusCyclerForTesting( + focus_cycler.get()); // Add a mock button to the status area. status_widget->GetContentsView()->AddChildView( @@ -201,8 +210,8 @@ TEST_F(FocusCyclerLauncherTest, CycleFocusBackwardInvisible) { views::Widget* status_widget = internal::CreateStatusArea(NULL); ASSERT_TRUE(status_widget); focus_cycler->AddWidget(status_widget); - static_cast<internal::StatusAreaView*>(status_widget->GetContentsView())-> - SetFocusCyclerForTesting(focus_cycler.get()); + GetStatusAreaView(status_widget)->SetFocusCyclerForTesting( + focus_cycler.get()); // Add a mock button to the status area. status_widget->GetContentsView()->AddChildView( diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc index 782365c..5516442 100644 --- a/ash/launcher/launcher.cc +++ b/ash/launcher/launcher.cc @@ -40,9 +40,12 @@ class Launcher::DelegateView : public views::WidgetDelegate, void SetStatusWidth(int width); int status_width() const { return status_width_; } - void set_focus_cycler(const internal::FocusCycler* focus_cycler) { + 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; @@ -67,7 +70,7 @@ class Launcher::DelegateView : public views::WidgetDelegate, // Width of the status area. int status_width_; - const internal::FocusCycler* focus_cycler_; + internal::FocusCycler* focus_cycler_; DISALLOW_COPY_AND_ASSIGN(DelegateView); }; @@ -148,6 +151,10 @@ void Launcher::SetFocusCycler(internal::FocusCycler* focus_cycler) { focus_cycler->AddWidget(widget_.get()); } +internal::FocusCycler* Launcher::GetFocusCycler() { + return delegate_view_->focus_cycler(); +} + void Launcher::SetPaintsBackground( bool value, internal::BackgroundAnimator::ChangeType change_type) { diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h index 8578b95..ebc56b8 100644 --- a/ash/launcher/launcher.h +++ b/ash/launcher/launcher.h @@ -40,6 +40,7 @@ class ASH_EXPORT Launcher : public internal::BackgroundAnimatorDelegate { // Sets the focus cycler. Also adds the launcher to the cycle. void SetFocusCycler(internal::FocusCycler* focus_cycler); + internal::FocusCycler* GetFocusCycler(); // Sets whether the launcher paints a background. Default is false, but is set // to true if a window overlaps the shelf. diff --git a/ash/status_area/status_area_view.cc b/ash/status_area/status_area_view.cc index 472a6f4..53ae934 100644 --- a/ash/status_area/status_area_view.cc +++ b/ash/status_area/status_area_view.cc @@ -14,6 +14,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" +#include "ui/views/accessible_pane_view.h" #include "ui/views/widget/widget.h" namespace ash { @@ -77,8 +78,16 @@ ASH_EXPORT views::Widget* CreateStatusArea(views::View* contents) { ash::internal::kShellWindowId_StatusContainer); params.transparent = true; widget->Init(params); + // TODO(sky): We need the contents to be an AccessiblePaneView for + // FocusCycler. SystemTray isn't an AccessiblePaneView, so we wrap it in + // one. This is a bit of a hack, but at this point this code path is only used + // for tests. Once the migration to SystemTray is done this method should no + // longer be needed and we can nuke this. + views::AccessiblePaneView* accessible_pane = + new views::AccessiblePaneView; + accessible_pane->AddChildView(contents); widget->set_focus_on_creation(false); - widget->SetContentsView(contents); + widget->SetContentsView(accessible_pane); widget->Show(); widget->GetNativeView()->SetName("StatusAreaView"); return widget; diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index c33fe5a..e4b1e04 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc @@ -553,6 +553,10 @@ void SystemTray::ShowItems(std::vector<SystemTrayItem*>& items, bubble_ = new internal::SystemTrayBubble(this, container_, items, detailed); bubble_->set_can_activate(activate); popup_ = views::BubbleDelegateView::CreateBubble(bubble_); + // If we have focus the shelf should be visible and we need to continue + // showing the shelf when the popup is shown. + if (GetWidget()->IsActive()) + should_show_launcher_ = true; bubble_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); popup_->non_client_view()->frame_view()->set_background(NULL); popup_->non_client_view()->frame_view()->set_border( diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc index 2e17bbf..275624e 100644 --- a/ash/wm/shelf_layout_manager.cc +++ b/ash/wm/shelf_layout_manager.cc @@ -12,6 +12,7 @@ #include "ash/system/tray/system_tray.h" #include "ash/wm/workspace/workspace_manager.h" #include "base/auto_reset.h" +#include "ui/aura/client/activation_client.h" #include "ui/aura/event.h" #include "ui/aura/event_filter.h" #include "ui/aura/root_window.h" @@ -105,16 +106,19 @@ ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent( // ShelfLayoutManager, public: ShelfLayoutManager::ShelfLayoutManager(views::Widget* status) - : in_layout_(false), + : root_window_(Shell::GetInstance()->GetRootWindow()), + in_layout_(false), auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT), shelf_height_(status->GetWindowScreenBounds().height()), launcher_(NULL), status_(status), workspace_manager_(NULL), window_overlaps_shelf_(false) { + root_window_->AddObserver(this); } ShelfLayoutManager::~ShelfLayoutManager() { + root_window_->RemoveObserver(this); } void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) { @@ -256,6 +260,13 @@ void ShelfLayoutManager::SetChildBounds(aura::Window* child, LayoutShelf(); } +void ShelfLayoutManager::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + if (key == aura::client::kRootWindowActiveWindowKey) + UpdateAutoHideStateNow(); +} + //////////////////////////////////////////////////////////////////////////////// // ShelfLayoutManager, private: @@ -391,6 +402,9 @@ ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState( if (launcher_ && launcher_->IsShowingMenu()) return AUTO_HIDE_SHOWN; + if (launcher_widget()->IsActive() || status_->IsActive()) + return AUTO_HIDE_SHOWN; + aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow(); bool mouse_over_launcher = launcher_widget()->GetWindowScreenBounds().Contains( diff --git a/ash/wm/shelf_layout_manager.h b/ash/wm/shelf_layout_manager.h index fe38d57..91d03e3 100644 --- a/ash/wm/shelf_layout_manager.h +++ b/ash/wm/shelf_layout_manager.h @@ -13,9 +13,14 @@ #include "base/compiler_specific.h" #include "base/timer.h" #include "ui/aura/layout_manager.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/insets.h" #include "ui/gfx/rect.h" +namespace aura { +class RootWindow; +} + namespace views { class Widget; } @@ -32,7 +37,8 @@ class WorkspaceManager; // 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 { +class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager, + public aura::WindowObserver { public: enum VisibilityState { // Completely visible. @@ -97,6 +103,7 @@ class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager { // The launcher is typically created after the layout manager. void SetLauncher(Launcher* launcher); + Launcher* launcher() { return launcher_; } // Stops any animations and sets the bounds of the launcher and status // widgets. @@ -124,6 +131,11 @@ class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager { virtual void SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE; + // Overriden from aura::WindowObserver: + virtual void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) OVERRIDE; + private: class AutoHideEventFilter; friend class ShelfLayoutManagerTest; @@ -179,6 +191,11 @@ class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager { // Updates the hit test bounds override for launcher and status area. void UpdateHitTestBounds(); + // 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_; diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc index 8f69a0b..cfe606c 100644 --- a/ash/wm/shelf_layout_manager_unittest.cc +++ b/ash/wm/shelf_layout_manager_unittest.cc @@ -4,6 +4,7 @@ #include "ash/wm/shelf_layout_manager.h" +#include "ash/focus_cycler.h" #include "ash/launcher/launcher.h" #include "ash/screen_ash.h" #include "ash/shell.h" @@ -319,5 +320,36 @@ TEST_F(ShelfLayoutManagerTest, SetAutoHideBehavior) { widget->GetWorkAreaBoundsInScreen().bottom()); } +// Verifies the shelf is visible when status/launcher is focused. +TEST_F(ShelfLayoutManagerTest, VisibileWhenStatusOrLauncherFocused) { + // Since ShelfLayoutManager queries for mouse location, move the mouse so + // it isn't over the shelf. + aura::test::EventGenerator generator( + Shell::GetInstance()->GetRootWindow(), 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); + // Widget is now owned by the parent window. + widget->Init(params); + widget->Show(); + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + EXPECT_EQ(ShelfLayoutManager::AUTO_HIDE, shelf->visibility_state()); + EXPECT_EQ(ShelfLayoutManager::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(ShelfLayoutManager::AUTO_HIDE_SHOWN, shelf->auto_hide_state()); + + widget->Activate(); + EXPECT_EQ(ShelfLayoutManager::AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); + + shelf->status()->Activate(); + EXPECT_EQ(ShelfLayoutManager::AUTO_HIDE_SHOWN, shelf->auto_hide_state()); +} + } // namespace internal } // namespace ash |