diff options
author | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-21 00:07:33 +0000 |
---|---|---|
committer | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-21 00:07:33 +0000 |
commit | 1eb18d93bae4e4d346da0a91acc62b1761a84b38 (patch) | |
tree | 78e4bd4b736fd060cd1f1ce6dd45412ae0bb0307 /ash | |
parent | 77f93a0fee5d33d31c4a28443f576f38b845194a (diff) | |
download | chromium_src-1eb18d93bae4e4d346da0a91acc62b1761a84b38.zip chromium_src-1eb18d93bae4e4d346da0a91acc62b1761a84b38.tar.gz chromium_src-1eb18d93bae4e4d346da0a91acc62b1761a84b38.tar.bz2 |
Draw panels above their launcher icons.
Note that this patch doesn't handle dragging panels to rearrange them (if we want that at all) and panels with no launcher icon because they are in overflow.
BUG=124115
TEST=aura_shell_unittests --gtest_filter=*Panel* --aura-panels
Review URL: https://chromiumcodereview.appspot.com/10091017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133309 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/shell.cc | 31 | ||||
-rw-r--r-- | ash/shell.h | 4 | ||||
-rw-r--r-- | ash/shell/window_watcher.cc | 9 | ||||
-rw-r--r-- | ash/shell/window_watcher.h | 2 | ||||
-rw-r--r-- | ash/wm/panel_layout_manager.cc | 69 | ||||
-rw-r--r-- | ash/wm/panel_layout_manager.h | 13 | ||||
-rw-r--r-- | ash/wm/panel_layout_manager_unittest.cc | 68 |
7 files changed, 128 insertions, 68 deletions
diff --git a/ash/shell.cc b/ash/shell.cc index 8f4b072..4fbc9ef 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -162,18 +162,9 @@ void CreateSpecialContainers(aura::RootWindow* root_window) { new ToplevelWindowEventFilter(always_on_top_container)); SetChildWindowVisibilityChangesAnimated(always_on_top_container); - aura::Window* panel_container = CreateContainer( - internal::kShellWindowId_PanelContainer, - "PanelContainer", - non_lock_screen_containers); - if (CommandLine::ForCurrentProcess()-> - HasSwitch(switches::kAuraPanelManager)) { - internal::PanelLayoutManager* layout_manager = - new internal::PanelLayoutManager(panel_container); - panel_container->SetEventFilter( - new internal::PanelWindowEventFilter(panel_container, layout_manager)); - panel_container->SetLayoutManager(layout_manager); - } + CreateContainer(internal::kShellWindowId_PanelContainer, + "PanelContainer", + non_lock_screen_containers); CreateContainer(internal::kShellWindowId_AppListContainer, "AppListContainer", @@ -538,6 +529,7 @@ Shell::Shell(ShellDelegate* delegate) root_filter_(NULL), delegate_(delegate), shelf_(NULL), + panel_layout_manager_(NULL), root_window_layout_(NULL), status_widget_(NULL) { gfx::Screen::SetInstance(screen_); @@ -884,6 +876,8 @@ void Shell::CreateLauncher() { launcher_->SetFocusCycler(focus_cycler_.get()); shelf_->SetLauncher(launcher_.get()); + if (panel_layout_manager_) + panel_layout_manager_->SetLauncher(launcher_.get()); launcher_->widget()->Show(); } @@ -951,6 +945,19 @@ void Shell::InitLayoutManagers() { // Create desktop background widget. desktop_background_controller_->SetDesktopBackgroundImageMode(); + + // Create Panel layout manager + if (CommandLine::ForCurrentProcess()-> + HasSwitch(switches::kAuraPanelManager)) { + aura::Window* panel_container = GetContainer( + internal::kShellWindowId_PanelContainer); + panel_layout_manager_ = + new internal::PanelLayoutManager(panel_container); + panel_container->SetEventFilter( + new internal::PanelWindowEventFilter( + panel_container, panel_layout_manager_)); + panel_container->SetLayoutManager(panel_layout_manager_); + } } void Shell::DisableWorkspaceGridLayout() { diff --git a/ash/shell.h b/ash/shell.h index be8a058..56a12c3 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -71,6 +71,7 @@ class FocusCycler; class InputMethodEventFilter; class KeyRewriterEventFilter; class MonitorController; +class PanelLayoutManager; class PartialScreenshotEventFilter; class ResizeShadowController; class RootWindowEventFilter; @@ -356,6 +357,9 @@ class ASH_EXPORT Shell { // the status area. internal::ShelfLayoutManager* shelf_; + // Manages layout of panels. Owned by PanelContainer. + internal::PanelLayoutManager* panel_layout_manager_; + ObserverList<ShellObserver> observers_; // Owned by aura::RootWindow, cached here for type safety. diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc index ec14e1b..5398a8a 100644 --- a/ash/shell/window_watcher.cc +++ b/ash/shell/window_watcher.cc @@ -7,14 +7,18 @@ #include "ash/launcher/launcher.h" #include "ash/launcher/launcher_model.h" #include "ash/shell.h" +#include "ash/shell_window_ids.h" #include "ui/aura/window.h" namespace ash { namespace shell { WindowWatcher::WindowWatcher() - : window_(ash::Shell::GetInstance()->launcher()->window_container()) { + : window_(ash::Shell::GetInstance()->launcher()->window_container()), + panel_container_(ash::Shell::GetInstance()->GetContainer( + ash::internal::kShellWindowId_PanelContainer)) { window_->AddObserver(this); + panel_container_->AddObserver(this); } WindowWatcher::~WindowWatcher() { @@ -37,7 +41,8 @@ ash::LauncherID WindowWatcher::GetIDByWindow(aura::Window* window) const { // aura::WindowObserver overrides: void WindowWatcher::OnWindowAdded(aura::Window* new_window) { - if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL) + if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL && + new_window->type() != aura::client::WINDOW_TYPE_PANEL) return; static int image_count = 0; diff --git a/ash/shell/window_watcher.h b/ash/shell/window_watcher.h index d36a4c8..f31fb07 100644 --- a/ash/shell/window_watcher.h +++ b/ash/shell/window_watcher.h @@ -40,6 +40,8 @@ class WindowWatcher : public aura::WindowObserver { // Window watching for newly created windows to be added to. aura::Window* window_; + aura::Window* panel_container_; + // Maps from window to the id we gave it. IDToWindow id_to_window_; diff --git a/ash/wm/panel_layout_manager.cc b/ash/wm/panel_layout_manager.cc index 3c8a522..f741154 100644 --- a/ash/wm/panel_layout_manager.cc +++ b/ash/wm/panel_layout_manager.cc @@ -36,25 +36,32 @@ namespace internal { PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) : panel_container_(panel_container), in_layout_(false), - dragged_panel_(NULL) { + dragged_panel_(NULL), + launcher_(NULL) { DCHECK(panel_container); } PanelLayoutManager::~PanelLayoutManager() { + if (launcher_) + launcher_->RemoveIconObserver(this); } void PanelLayoutManager::StartDragging(aura::Window* panel) { - DCHECK(dragged_panel_ == NULL); + DCHECK(!dragged_panel_); DCHECK(panel->parent() == panel_container_); dragged_panel_ = panel; } void PanelLayoutManager::FinishDragging() { - DCHECK(dragged_panel_ != NULL); + DCHECK(dragged_panel_); dragged_panel_ = NULL; Relayout(); } +void PanelLayoutManager::SetLauncher(ash::Launcher* launcher) { + launcher->AddIconObserver(this); +} + void PanelLayoutManager::ToggleMinimize(aura::Window* panel) { DCHECK(panel->parent() == panel_container_); if (panel->GetProperty(aura::client::kShowStateKey) == @@ -64,7 +71,7 @@ void PanelLayoutManager::ToggleMinimize(aura::Window* panel) { gfx::Rect new_bounds(old_bounds); const gfx::Rect* restore_bounds = GetRestoreBounds(panel); - if (restore_bounds != NULL) { + if (restore_bounds) { new_bounds.set_height(restore_bounds->height()); new_bounds.set_y(old_bounds.bottom() - restore_bounds->height()); SetChildBounds(panel, new_bounds); @@ -149,46 +156,46 @@ void PanelLayoutManager::SetChildBounds(aura::Window* child, } //////////////////////////////////////////////////////////////////////////////// +// PanelLayoutManager, aura::LauncherIconObserver implementation: + +void PanelLayoutManager::OnLauncherIconPositionsChanged() { + Relayout(); +} + +//////////////////////////////////////////////////////////////////////////////// // PanelLayoutManager private implementation: -// This is a rough outline of a simple panel layout manager. void PanelLayoutManager::Relayout() { if (in_layout_) return; AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - // Panels are currently laid out just above the launcher (if it exists), - // otherwise at the bottom of the root window. - int right, bottom; ash::Shell* shell = ash::Shell::GetInstance(); - if (shell->launcher() && shell->launcher()->widget()->IsVisible()) { - const gfx::Rect& bounds = - shell->launcher()->widget()->GetWindowScreenBounds(); - right = bounds.width() - 1 - kPanelMarginEdge; - bottom = bounds.y() - 1; - } else { - const gfx::Rect& bounds = panel_container_->GetRootWindow()->bounds(); - right = bounds.width() - 1 - kPanelMarginEdge; - bottom = bounds.bottom() - 1; - } - // Layout the panel windows right to left. for (PanelList::iterator iter = panel_windows_.begin(); iter != panel_windows_.end(); ++iter) { aura::Window* panel_win = *iter; - if (!panel_win->IsVisible()) + if (!panel_win->IsVisible() || panel_win == dragged_panel_) continue; - int x = right - panel_win->bounds().width(); - int y = bottom - panel_win->bounds().height(); - - // Do not relayout dragged panel, but pretend it is in place - if (panel_win != dragged_panel_) { - gfx::Rect bounds(x, y, - panel_win->bounds().width(), - panel_win->bounds().height()); - SetChildBoundsDirect(panel_win, bounds); - } - right = x - kPanelMarginMiddle; + + gfx::Rect icon_bounds = + shell->launcher()->GetScreenBoundsOfItemIconForWindow(panel_win); + + // An empty rect indicates that there is no icon for the panel in the + // launcher. Just use the current bounds, as there's no icon to draw the + // panel above. + if (icon_bounds.IsEmpty()) + continue; + + gfx::Point icon_origin = icon_bounds.origin(); + aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), + panel_container_, &icon_origin); + + gfx::Rect bounds = panel_win->bounds(); + bounds.set_x( + icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); + bounds.set_y(icon_origin.y() - bounds.height()); + SetChildBoundsDirect(panel_win, bounds); } } diff --git a/ash/wm/panel_layout_manager.h b/ash/wm/panel_layout_manager.h index 07ffd0e..8ec53d5 100644 --- a/ash/wm/panel_layout_manager.h +++ b/ash/wm/panel_layout_manager.h @@ -9,6 +9,7 @@ #include <list> #include "ash/ash_export.h" +#include "ash/launcher/launcher_icon_observer.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ui/aura/layout_manager.h" @@ -22,6 +23,8 @@ class Rect; } namespace ash { +class Launcher; + namespace internal { // PanelLayoutManager is responsible for organizing panels within the @@ -33,7 +36,8 @@ namespace internal { // its layout manager to this instance, e.g.: // panel_container->SetLayoutManager(new PanelLayoutManager(panel_container)); -class ASH_EXPORT PanelLayoutManager : public aura::LayoutManager { +class ASH_EXPORT PanelLayoutManager : public aura::LayoutManager, + public ash::LauncherIconObserver { public: explicit PanelLayoutManager(aura::Window* panel_container); virtual ~PanelLayoutManager(); @@ -43,6 +47,8 @@ class ASH_EXPORT PanelLayoutManager : public aura::LayoutManager { void ToggleMinimize(aura::Window* panel); + void SetLauncher(ash::Launcher* launcher); + // Overridden from aura::LayoutManager: virtual void OnWindowResized() OVERRIDE; virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; @@ -53,6 +59,9 @@ class ASH_EXPORT PanelLayoutManager : public aura::LayoutManager { virtual void SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE; + // Overriden from ash::LauncherIconObserver + virtual void OnLauncherIconPositionsChanged() OVERRIDE; + private: typedef std::list<aura::Window*> PanelList; @@ -68,6 +77,8 @@ class ASH_EXPORT PanelLayoutManager : public aura::LayoutManager { aura::Window* dragged_panel_; + Launcher* launcher_; + DISALLOW_COPY_AND_ASSIGN(PanelLayoutManager); }; diff --git a/ash/wm/panel_layout_manager_unittest.cc b/ash/wm/panel_layout_manager_unittest.cc index 4ee864c..17c6035 100644 --- a/ash/wm/panel_layout_manager_unittest.cc +++ b/ash/wm/panel_layout_manager_unittest.cc @@ -5,9 +5,11 @@ #include "ash/wm/panel_layout_manager.h" #include "ash/ash_switches.h" +#include "ash/launcher/launcher.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" +#include "ash/test/test_launcher_delegate.h" #include "base/basictypes.h" #include "base/command_line.h" #include "base/compiler_specific.h" @@ -21,9 +23,15 @@ namespace { views::Widget* CreatePanelWindow(const gfx::Rect& rect) { views::Widget::InitParams params(views::Widget::InitParams::TYPE_PANEL); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.bounds = rect; + params.child = true; views::Widget* widget = new views::Widget(); widget->Init(params); + ash::test::TestLauncherDelegate* launcher_delegate = + ash::test::TestLauncherDelegate::instance(); + CHECK(launcher_delegate); + launcher_delegate->AddLauncherItem(widget->GetNativeWindow()); widget->Show(); return widget; } @@ -42,29 +50,49 @@ class PanelLayoutManagerTest : public ash::test::AshTestBase { DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTest); }; +void IsPanelAboveLauncherIcon(views::Widget* panel) { + Launcher* launcher = Shell::GetInstance()->launcher(); + aura::Window* window = panel->GetNativeWindow(); + gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(window); + ASSERT_FALSE(icon_bounds.IsEmpty()); + + gfx::Rect window_bounds = panel->GetWindowScreenBounds(); + + // 1-pixel tolerance--since we center panels over their icons, panels with odd + // pixel widths won't be perfectly lined up with even pixel width launcher + // icons. + EXPECT_NEAR( + window_bounds.CenterPoint().x(), icon_bounds.CenterPoint().x(), 1); + EXPECT_EQ(window_bounds.bottom(), icon_bounds.y()); +} + } // namespace // Tests that a created panel window is successfully added to the panel // layout manager. TEST_F(PanelLayoutManagerTest, AddOnePanel) { - gfx::Rect bounds(1, 1, 200, 200); - views::Widget* w1 = CreatePanelWindow(bounds); - EXPECT_EQ(GetPanelContainer(), w1->GetNativeWindow()->parent()); + gfx::Rect bounds(0, 0, 201, 201); + scoped_ptr<views::Widget> window(CreatePanelWindow(bounds)); + EXPECT_EQ(GetPanelContainer(), window->GetNativeWindow()->parent()); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get())); } // Tests that panels are ordered right-to-left. -TEST_F(PanelLayoutManagerTest, PanelOrderRightToLeft) { +TEST_F(PanelLayoutManagerTest, PanelAboveLauncherIcons) { if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kAuraPanelManager)) return; - gfx::Rect bounds(1, 1, 200, 200); - views::Widget* w1 = CreatePanelWindow(bounds); - views::Widget* w2 = CreatePanelWindow(bounds); - EXPECT_LT(w2->GetWindowScreenBounds().x(), w1->GetWindowScreenBounds().x()); - - views::Widget* w3 = CreatePanelWindow(bounds); - EXPECT_LT(w3->GetWindowScreenBounds().x(), w2->GetWindowScreenBounds().x()); - EXPECT_LT(w2->GetWindowScreenBounds().x(), w1->GetWindowScreenBounds().x()); + + gfx::Rect bounds(0, 0, 201, 201); + scoped_ptr<views::Widget> w1(CreatePanelWindow(bounds)); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); + scoped_ptr<views::Widget> w2(CreatePanelWindow(bounds)); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); + scoped_ptr<views::Widget> w3(CreatePanelWindow(bounds)); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); } // Tests removing a panel. @@ -73,19 +101,15 @@ TEST_F(PanelLayoutManagerTest, RemovePanel) { switches::kAuraPanelManager)) return; - gfx::Rect bounds(1, 1, 200, 200); - views::Widget* w1 = CreatePanelWindow(bounds); - views::Widget* w2 = CreatePanelWindow(bounds); - views::Widget* w3 = CreatePanelWindow(bounds); - - gfx::Rect w3bounds = w3->GetWindowScreenBounds(); + gfx::Rect bounds(0, 0, 201, 201); + scoped_ptr<views::Widget> w1(CreatePanelWindow(bounds)); + scoped_ptr<views::Widget> w2(CreatePanelWindow(bounds)); + scoped_ptr<views::Widget> w3(CreatePanelWindow(bounds)); GetPanelContainer()->RemoveChild(w2->GetNativeWindow()); - // Verify that w3 has moved. - EXPECT_NE(w3->GetWindowScreenBounds(), w3bounds); - // Verify that w3 is still left of w1. - EXPECT_LT(w3->GetWindowScreenBounds().x(), w1->GetWindowScreenBounds().x()); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); + EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); } } // namespace ash |