summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/focus_cycler_unittest.cc25
-rw-r--r--ash/launcher/launcher.cc11
-rw-r--r--ash/launcher/launcher.h1
-rw-r--r--ash/status_area/status_area_view.cc11
-rw-r--r--ash/system/tray/system_tray.cc4
-rw-r--r--ash/wm/shelf_layout_manager.cc16
-rw-r--r--ash/wm/shelf_layout_manager.h19
-rw-r--r--ash/wm/shelf_layout_manager_unittest.cc32
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