diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-18 23:57:05 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-18 23:57:05 +0000 |
commit | fc7b744c639fb4a9c25b1dbf5f7553166fdc1801 (patch) | |
tree | e3f486d62831674fddc60d6f05689dad8fba3a55 /ash | |
parent | ae6c59c831e325ea8cd45340e27acd75d5ddc4e5 (diff) | |
download | chromium_src-fc7b744c639fb4a9c25b1dbf5f7553166fdc1801.zip chromium_src-fc7b744c639fb4a9c25b1dbf5f7553166fdc1801.tar.gz chromium_src-fc7b744c639fb4a9c25b1dbf5f7553166fdc1801.tar.bz2 |
Aura: Split out CompactLayoutManager from ToplevelLayoutManager
Move the shared code to BaseLayoutManager. Adjust the unit tests. Alice needs this for some compact mode work she's doing right now.
BUG=110648
TEST=Run Aura in both --aura-window-mode=normal and --aura-window-mode=compact, both still start correctly. Also unit test coverage from CompactLayoutManagerTest and ToplevelLayoutManagerTest
Review URL: https://chromiumcodereview.appspot.com/9255024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118186 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash.gyp | 6 | ||||
-rw-r--r-- | ash/shell.cc | 9 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.cc | 128 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.h | 71 | ||||
-rw-r--r-- | ash/wm/base_layout_manager_unittest.cc | 135 | ||||
-rw-r--r-- | ash/wm/compact_layout_manager.cc | 68 | ||||
-rw-r--r-- | ash/wm/compact_layout_manager.h | 60 | ||||
-rw-r--r-- | ash/wm/compact_layout_manager_unittest.cc | 87 | ||||
-rw-r--r-- | ash/wm/toplevel_layout_manager.cc | 110 | ||||
-rw-r--r-- | ash/wm/toplevel_layout_manager.h | 51 | ||||
-rw-r--r-- | ash/wm/toplevel_layout_manager_unittest.cc | 26 |
11 files changed, 585 insertions, 166 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index c03b884..67460cf 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -104,6 +104,10 @@ 'wm/activation_controller.h', 'wm/always_on_top_controller.cc', 'wm/always_on_top_controller.h', + 'wm/base_layout_manager.cc', + 'wm/base_layout_manager.h', + 'wm/compact_layout_manager.cc', + 'wm/compact_layout_manager.h', 'wm/compact_status_area_layout_manager.cc', 'wm/compact_status_area_layout_manager.h', 'wm/default_container_event_filter.cc', @@ -214,6 +218,8 @@ 'test/test_suite.h', 'tooltips/tooltip_controller_unittest.cc', 'wm/activation_controller_unittest.cc', + 'wm/base_layout_manager_unittest.cc', + 'wm/compact_layout_manager_unittest.cc', 'wm/default_container_layout_manager_unittest.cc', 'wm/image_grid_unittest.cc', 'wm/system_modal_container_layout_manager_unittest.cc', diff --git a/ash/shell.cc b/ash/shell.cc index 3f5e218..40df7c9 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -18,6 +18,7 @@ #include "ash/shell_window_ids.h" #include "ash/tooltips/tooltip_controller.h" #include "ash/wm/activation_controller.h" +#include "ash/wm/compact_layout_manager.h" #include "ash/wm/compact_status_area_layout_manager.h" #include "ash/wm/default_container_event_filter.h" #include "ash/wm/default_container_layout_manager.h" @@ -315,10 +316,10 @@ void Shell::InitLayoutManagers(aura::RootWindow* root_window) { // desktop background, etc. The launcher still exists so we can use its // data model and list of open windows, but we hide the UI to save space. if (IsWindowModeCompact()) { - internal::ToplevelLayoutManager* toplevel_layout_manager = - new internal::ToplevelLayoutManager(); - default_container->SetLayoutManager(toplevel_layout_manager); - toplevel_layout_manager->set_status_area_widget(status_widget); + internal::CompactLayoutManager* compact_layout_manager = + new internal::CompactLayoutManager(); + default_container->SetLayoutManager(compact_layout_manager); + compact_layout_manager->set_status_area_widget(status_widget); internal::CompactStatusAreaLayoutManager* status_area_layout_manager = new internal::CompactStatusAreaLayoutManager(status_widget); GetContainer(internal::kShellWindowId_StatusContainer)-> diff --git a/ash/wm/base_layout_manager.cc b/ash/wm/base_layout_manager.cc new file mode 100644 index 0000000..7c78ec0 --- /dev/null +++ b/ash/wm/base_layout_manager.cc @@ -0,0 +1,128 @@ +// 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/base_layout_manager.h" + +#include "ash/wm/property_util.h" +#include "ash/wm/window_util.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" +#include "ui/base/ui_base_types.h" +#include "ui/gfx/screen.h" + +namespace ash { +namespace internal { + +///////////////////////////////////////////////////////////////////////////// +// BaseLayoutManager, public: + +BaseLayoutManager::BaseLayoutManager() { + aura::RootWindow::GetInstance()->AddRootWindowObserver(this); +} + +BaseLayoutManager::~BaseLayoutManager() { + for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) + (*i)->RemoveObserver(this); + aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this); +} + +///////////////////////////////////////////////////////////////////////////// +// BaseLayoutManager, LayoutManager overrides: + +void BaseLayoutManager::OnWindowResized() { +} + +void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) { + windows_.insert(child); + child->AddObserver(this); + if (child->GetProperty(aura::client::kShowStateKey)) { + UpdateBoundsFromShowState(child); + } +} + +void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { + windows_.erase(child); + child->RemoveObserver(this); +} + +void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, + bool visibile) { +} + +void BaseLayoutManager::SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) { + gfx::Rect child_bounds(requested_bounds); + // Avoid a janky resize on startup by ensuring the initial bounds fill the + // screen. + if (window_util::IsWindowMaximized(child)) + child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child); + else if (window_util::IsWindowFullscreen(child)) + child_bounds = gfx::Screen::GetMonitorAreaNearestWindow(child); + SetChildBoundsDirect(child, child_bounds); +} + +///////////////////////////////////////////////////////////////////////////// +// BaseLayoutManager, RootWindowObserver overrides: + +void BaseLayoutManager::OnRootWindowResized(const gfx::Size& new_size) { + // If a user plugs an external monitor into a laptop running Aura the + // monitor size will change. Maximized windows need to resize to match. + // We also do this when developers running Aura on a desktop manually resize + // the host window. + for (WindowSet::const_iterator it = windows_.begin(); + it != windows_.end(); + ++it) { + aura::Window* window = *it; + // The work area may be smaller than the full screen. + gfx::Rect monitor_rect = window_util::IsWindowFullscreen(window) ? + gfx::Screen::GetMonitorAreaNearestWindow(window) : + gfx::Screen::GetMonitorWorkAreaNearestWindow(window); + // Put as much of the window as possible within the monitor area. + window->SetBounds(window->bounds().AdjustToFit(monitor_rect)); + } +} + +///////////////////////////////////////////////////////////////////////////// +// BaseLayoutManager, WindowObserver overrides: + +void BaseLayoutManager::OnWindowPropertyChanged(aura::Window* window, + const char* name, + void* old) { + if (name == aura::client::kShowStateKey) { + UpdateBoundsFromShowState(window); + } +} + +////////////////////////////////////////////////////////////////////////////// +// BaseLayoutManager, private: + +void BaseLayoutManager::UpdateBoundsFromShowState(aura::Window* window) { + switch (window->GetIntProperty(aura::client::kShowStateKey)) { + case ui::SHOW_STATE_NORMAL: { + const gfx::Rect* restore = GetRestoreBounds(window); + window->SetProperty(aura::client::kRestoreBoundsKey, NULL); + if (restore) + window->SetBounds(*restore); + delete restore; + break; + } + + case ui::SHOW_STATE_MAXIMIZED: + SetRestoreBoundsIfNotSet(window); + window->SetBounds(gfx::Screen::GetMonitorWorkAreaNearestWindow(window)); + break; + + case ui::SHOW_STATE_FULLSCREEN: + SetRestoreBoundsIfNotSet(window); + window->SetBounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); + break; + + default: + break; + } +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/base_layout_manager.h b/ash/wm/base_layout_manager.h new file mode 100644 index 0000000..4ceb82e --- /dev/null +++ b/ash/wm/base_layout_manager.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_WM_BASE_LAYOUT_MANAGER_H_ +#define ASH_WM_BASE_LAYOUT_MANAGER_H_ +#pragma once + +#include <set> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/layout_manager.h" +#include "ui/aura/root_window_observer.h" +#include "ui/aura/window_observer.h" +#include "ash/ash_export.h" + +namespace aura { +class Window; +} + +namespace ash { +namespace internal { + +// BaseLayoutManager is the simplest possible implementation for a window +// layout manager. It listens for changes to kShowStateKey and resizes the +// window appropriately. Subclasses should be sure to invoke the base class +// for adding and removing windows, otherwise show state will not be tracked +// properly. +class ASH_EXPORT BaseLayoutManager : public aura::LayoutManager, + public aura::RootWindowObserver, + public aura::WindowObserver { + public: + typedef std::set<aura::Window*> WindowSet; + + BaseLayoutManager(); + virtual ~BaseLayoutManager(); + + const WindowSet& windows() const { return windows_; } + + // LayoutManager overrides: + virtual void OnWindowResized() OVERRIDE; + virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; + virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; + virtual void OnChildWindowVisibilityChanged(aura::Window* child, + bool visibile) OVERRIDE; + virtual void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) OVERRIDE; + + // RootWindowObserver overrides: + virtual void OnRootWindowResized(const gfx::Size& new_size) OVERRIDE; + + // WindowObserver overrides: + virtual void OnWindowPropertyChanged(aura::Window* window, + const char* name, + void* old) OVERRIDE; + + private: + // Update window bounds based on a change in show state. + void UpdateBoundsFromShowState(aura::Window* window); + + // Set of windows we're listening to. + WindowSet windows_; + + DISALLOW_COPY_AND_ASSIGN(BaseLayoutManager); +}; + +} // namespace ash +} // namespace internal + +#endif // ASH_WM_BASE_LAYOUT_MANAGER_H_ diff --git a/ash/wm/base_layout_manager_unittest.cc b/ash/wm/base_layout_manager_unittest.cc new file mode 100644 index 0000000..6e16543 --- /dev/null +++ b/ash/wm/base_layout_manager_unittest.cc @@ -0,0 +1,135 @@ +// 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/base_layout_manager.h" + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/root_window.h" +#include "ui/aura/screen_aura.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_windows.h" +#include "ui/base/ui_base_types.h" +#include "ui/aura/window.h" + +namespace ash { + +namespace { + +class BaseLayoutManagerTest : public aura::test::AuraTestBase { + public: + BaseLayoutManagerTest() : layout_manager_(NULL) {} + virtual ~BaseLayoutManagerTest() {} + + virtual void SetUp() OVERRIDE { + aura::test::AuraTestBase::SetUp(); + aura::RootWindow::GetInstance()->screen()->set_work_area_insets( + gfx::Insets(1, 2, 3, 4)); + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(800, 600)); + container_.reset(new aura::Window(NULL)); + container_->Init(ui::Layer::LAYER_HAS_NO_TEXTURE); + container_->SetBounds(gfx::Rect(0, 0, 500, 500)); + layout_manager_ = new internal::BaseLayoutManager(); + container_->SetLayoutManager(layout_manager_); + } + + aura::Window* CreateTestWindow(const gfx::Rect& bounds) { + return aura::test::CreateTestWindowWithBounds(bounds, container_.get()); + } + + private: + // Owned by |container_|. + internal::BaseLayoutManager* layout_manager_; + + scoped_ptr<aura::Window> container_; + + DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest); +}; + +} // namespace + +// Tests normal->maximize->normal. +TEST_F(BaseLayoutManagerTest, Maximize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + // Maximized window fills the work area, not the whole monitor. + EXPECT_EQ(gfx::Screen::GetMonitorWorkAreaNearestWindow(window.get()), + window->bounds()); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(bounds, window->bounds()); +} + +// Tests maximized window size during root window resize. +TEST_F(BaseLayoutManagerTest, MaximizeRootWindowResize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + EXPECT_EQ(gfx::Screen::GetMonitorWorkAreaNearestWindow(window.get()), + window->bounds()); + // Enlarge the root window. We should still match the work area size. + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(800, 600)); + EXPECT_EQ(gfx::Screen::GetMonitorWorkAreaNearestWindow(window.get()), + window->bounds()); +} + +// Tests normal->fullscreen->normal. +TEST_F(BaseLayoutManagerTest, Fullscreen) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetIntProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + // Fullscreen window fills the whole monitor. + EXPECT_EQ(gfx::Screen::GetMonitorAreaNearestWindow(window.get()), + window->bounds()); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(bounds, window->bounds()); +} + +// Tests fullscreen window size during root window resize. +TEST_F(BaseLayoutManagerTest, FullscreenRootWindowResize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + // Fullscreen window fills the whole monitor. + window->SetIntProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + EXPECT_EQ(gfx::Screen::GetMonitorAreaNearestWindow(window.get()), + window->bounds()); + // Enlarge the root window. We should still match the monitor size. + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(800, 600)); + EXPECT_EQ(gfx::Screen::GetMonitorAreaNearestWindow(window.get()), + window->bounds()); +} + +// Tests that when the screen gets smaller the windows aren't bigger than +// the screen. +TEST_F(BaseLayoutManagerTest, RootWindowResizeShrinksWindows) { + scoped_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(10, 20, 500, 400))); + gfx::Rect work_area = gfx::Screen::GetMonitorAreaNearestWindow(window.get()); + // Invariant: Window is smaller than work area. + EXPECT_LE(window->bounds().width(), work_area.width()); + EXPECT_LE(window->bounds().height(), work_area.height()); + + // Make the root window narrower than our window. + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(300, 400)); + work_area = gfx::Screen::GetMonitorAreaNearestWindow(window.get()); + EXPECT_LE(window->bounds().width(), work_area.width()); + EXPECT_LE(window->bounds().height(), work_area.height()); + + // Make the root window shorter than our window. + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(300, 200)); + work_area = gfx::Screen::GetMonitorAreaNearestWindow(window.get()); + EXPECT_LE(window->bounds().width(), work_area.width()); + EXPECT_LE(window->bounds().height(), work_area.height()); + + // Enlarging the root window does not change the window bounds. + gfx::Rect old_bounds = window->bounds(); + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(800, 600)); + EXPECT_EQ(old_bounds.width(), window->bounds().width()); + EXPECT_EQ(old_bounds.height(), window->bounds().height()); +} + +} // namespace ash diff --git a/ash/wm/compact_layout_manager.cc b/ash/wm/compact_layout_manager.cc new file mode 100644 index 0000000..867cd30 --- /dev/null +++ b/ash/wm/compact_layout_manager.cc @@ -0,0 +1,68 @@ +// 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/compact_layout_manager.h" + +#include "ash/wm/window_util.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/views/widget/widget.h" + +namespace ash { +namespace internal { + +///////////////////////////////////////////////////////////////////////////// +// CompactLayoutManager, public: + +CompactLayoutManager::CompactLayoutManager() + : status_area_widget_(NULL) { +} + +CompactLayoutManager::~CompactLayoutManager() { +} + +///////////////////////////////////////////////////////////////////////////// +// CompactLayoutManager, LayoutManager overrides: + +void CompactLayoutManager::OnWindowAddedToLayout(aura::Window* child) { + BaseLayoutManager::OnWindowAddedToLayout(child); + UpdateStatusAreaVisibility(); +} + +void CompactLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { + BaseLayoutManager::OnWillRemoveWindowFromLayout(child); + UpdateStatusAreaVisibility(); +} + +void CompactLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) { + BaseLayoutManager::OnChildWindowVisibilityChanged(child, visible); + UpdateStatusAreaVisibility(); +} + +///////////////////////////////////////////////////////////////////////////// +// CompactLayoutManager, WindowObserver overrides: + +void CompactLayoutManager::OnWindowPropertyChanged(aura::Window* window, + const char* name, + void* old) { + BaseLayoutManager::OnWindowPropertyChanged(window, name, old); + if (name == aura::client::kShowStateKey) + UpdateStatusAreaVisibility(); +} + +////////////////////////////////////////////////////////////////////////////// +// CompactLayoutManager, private: + +void CompactLayoutManager::UpdateStatusAreaVisibility() { + if (!status_area_widget_) + return; + // Full screen windows should hide the status area widget. + if (window_util::HasFullscreenWindow(windows())) + status_area_widget_->Hide(); + else + status_area_widget_->Show(); +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/compact_layout_manager.h b/ash/wm/compact_layout_manager.h new file mode 100644 index 0000000..7ce87dd --- /dev/null +++ b/ash/wm/compact_layout_manager.h @@ -0,0 +1,60 @@ +// 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_COMPACT_LAYOUT_MANAGER_H_ +#define ASH_WM_COMPACT_LAYOUT_MANAGER_H_ +#pragma once + +#include "ash/ash_export.h" +#include "ash/wm/base_layout_manager.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" + +namespace views { +class Widget; +} + +namespace ash { +namespace internal { + +// CompactLayoutManager is the LayoutManager used in compact window mode, +// which emulates the traditional Chrome OS window manager. Windows are always +// maximized, fill the screen, and only one tabbed browser window is visible at +// a time. The status area appears in the top-right corner of the screen. +class ASH_EXPORT CompactLayoutManager : public BaseLayoutManager { + public: + CompactLayoutManager(); + virtual ~CompactLayoutManager(); + + void set_status_area_widget(views::Widget* widget) { + status_area_widget_ = widget; + } + + // LayoutManager overrides: + virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; + virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; + virtual void OnChildWindowVisibilityChanged(aura::Window* child, + bool visibile) OVERRIDE; + + // WindowObserver overrides: + virtual void OnWindowPropertyChanged(aura::Window* window, + const char* name, + void* old) OVERRIDE; + + private: + // Hides the status area if we are managing it and full screen windows are + // visible. + void UpdateStatusAreaVisibility(); + + // Status area with clock, network, battery, etc. icons. May be NULL if the + // shelf is managing the status area. + views::Widget* status_area_widget_; + + DISALLOW_COPY_AND_ASSIGN(CompactLayoutManager); +}; + +} // namespace ash +} // namespace internal + +#endif // ASH_WM_COMPACT_LAYOUT_MANAGER_H_ diff --git a/ash/wm/compact_layout_manager_unittest.cc b/ash/wm/compact_layout_manager_unittest.cc new file mode 100644 index 0000000..46d596e --- /dev/null +++ b/ash/wm/compact_layout_manager_unittest.cc @@ -0,0 +1,87 @@ +// 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/compact_layout_manager.h" + +#include "ash/wm/shelf_layout_manager.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/root_window.h" +#include "ui/aura/screen_aura.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_windows.h" +#include "ui/aura/window.h" +#include "ui/base/ui_base_types.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { + +class CompactLayoutManagerTest : public aura::test::AuraTestBase { + public: + CompactLayoutManagerTest() : layout_manager_(NULL) {} + virtual ~CompactLayoutManagerTest() {} + + internal::CompactLayoutManager* layout_manager() { + return layout_manager_; + } + + virtual void SetUp() OVERRIDE { + aura::test::AuraTestBase::SetUp(); + aura::RootWindow::GetInstance()->screen()->set_work_area_insets( + gfx::Insets(1, 2, 3, 4)); + aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(800, 600)); + container_.reset(new aura::Window(NULL)); + container_->Init(ui::Layer::LAYER_HAS_NO_TEXTURE); + container_->SetBounds(gfx::Rect(0, 0, 500, 500)); + layout_manager_ = new internal::CompactLayoutManager(); + container_->SetLayoutManager(layout_manager_); + } + + aura::Window* CreateTestWindow(const gfx::Rect& bounds) { + return aura::test::CreateTestWindowWithBounds(bounds, container_.get()); + } + + // Returns widget owned by its parent, so doesn't need scoped_ptr<>. + views::Widget* CreateTestWidget() { + views::Widget* widget = new views::Widget; + views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); + params.bounds = gfx::Rect(11, 22, 33, 44); + widget->Init(params); + widget->Show(); + return widget; + } + + private: + // Owned by |container_|. + internal::CompactLayoutManager* layout_manager_; + + scoped_ptr<aura::Window> container_; + + DISALLOW_COPY_AND_ASSIGN(CompactLayoutManagerTest); +}; + +} // namespace + +// Tests status area visibility during window maximize and fullscreen. +TEST_F(CompactLayoutManagerTest, StatusAreaVisibility) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + views::Widget* widget = CreateTestWidget(); + layout_manager()->set_status_area_widget(widget); + EXPECT_TRUE(widget->IsVisible()); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + EXPECT_TRUE(widget->IsVisible()); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_TRUE(widget->IsVisible()); + window->SetIntProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + EXPECT_FALSE(widget->IsVisible()); + window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_TRUE(widget->IsVisible()); +} + +} // namespace ash diff --git a/ash/wm/toplevel_layout_manager.cc b/ash/wm/toplevel_layout_manager.cc index 83a8552..c1de9b9 100644 --- a/ash/wm/toplevel_layout_manager.cc +++ b/ash/wm/toplevel_layout_manager.cc @@ -4,15 +4,11 @@ #include "ash/wm/toplevel_layout_manager.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" #include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" #include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" namespace { @@ -41,81 +37,41 @@ namespace internal { // ToplevelLayoutManager, public: ToplevelLayoutManager::ToplevelLayoutManager() - : shelf_(NULL), - status_area_widget_(NULL) { - aura::RootWindow::GetInstance()->AddRootWindowObserver(this); + : shelf_(NULL) { } ToplevelLayoutManager::~ToplevelLayoutManager() { - for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) - (*i)->RemoveObserver(this); - aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this); } ///////////////////////////////////////////////////////////////////////////// // ToplevelLayoutManager, LayoutManager overrides: -void ToplevelLayoutManager::OnWindowResized() { -} - void ToplevelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - windows_.insert(child); - child->AddObserver(this); - if (child->GetProperty(aura::client::kShowStateKey)) { - UpdateBoundsFromShowState(child); - UpdateShelfVisibility(); - UpdateStatusAreaVisibility(); - } + BaseLayoutManager::OnWindowAddedToLayout(child); + UpdateShelfVisibility(); } -void ToplevelLayoutManager::OnWillRemoveWindowFromLayout( - aura::Window* child) { - windows_.erase(child); - child->RemoveObserver(this); +void ToplevelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { + BaseLayoutManager::OnWillRemoveWindowFromLayout(child); UpdateShelfVisibility(); - UpdateStatusAreaVisibility(); } void ToplevelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) { + bool visible) { + BaseLayoutManager::OnChildWindowVisibilityChanged(child, visible); UpdateShelfVisibility(); - UpdateStatusAreaVisibility(); } void ToplevelLayoutManager::SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) { gfx::Rect child_bounds(requested_bounds); - // Avoid a janky resize on startup by ensuring the initial bounds fill the - // screen. - if (window_util::IsWindowMaximized(child)) - child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child); - else if (window_util::IsWindowFullscreen(child)) - child_bounds = gfx::Screen::GetMonitorAreaNearestWindow(child); - else + // Ensure normal windows have the title bar at least partly visible. + if (!window_util::IsWindowMaximized(child) && + !window_util::IsWindowFullscreen(child)) { child_bounds = BoundsWithTitleBarVisible( child_bounds, gfx::Screen::GetMonitorWorkAreaNearestWindow(child)); - SetChildBoundsDirect(child, child_bounds); -} - -///////////////////////////////////////////////////////////////////////////// -// ToplevelLayoutManager, RootWindowObserver overrides: - -void ToplevelLayoutManager::OnRootWindowResized(const gfx::Size& new_size) { - // If a user plugs an external monitor into a laptop running Aura the - // monitor size will change. Maximized windows need to resize to match. - // We also do this when developers running Aura on a desktop manually resize - // the host window. - for (WindowSet::const_iterator it = windows_.begin(); - it != windows_.end(); - ++it) { - aura::Window* window = *it; - // The work area may be smaller than the full screen. - gfx::Rect monitor_rect = window_util::IsWindowFullscreen(window) ? - gfx::Screen::GetMonitorAreaNearestWindow(window) : - gfx::Screen::GetMonitorWorkAreaNearestWindow(window); - // Put as much of the window as possible within the monitor area. - window->SetBounds(window->bounds().AdjustToFit(monitor_rect)); } + BaseLayoutManager::SetChildBounds(child, child_bounds); } ///////////////////////////////////////////////////////////////////////////// @@ -124,56 +80,18 @@ void ToplevelLayoutManager::OnRootWindowResized(const gfx::Size& new_size) { void ToplevelLayoutManager::OnWindowPropertyChanged(aura::Window* window, const char* name, void* old) { - if (name == aura::client::kShowStateKey) { - UpdateBoundsFromShowState(window); + BaseLayoutManager::OnWindowPropertyChanged(window, name, old); + if (name == aura::client::kShowStateKey) UpdateShelfVisibility(); - UpdateStatusAreaVisibility(); - } } ////////////////////////////////////////////////////////////////////////////// // ToplevelLayoutManager, private: -void ToplevelLayoutManager::UpdateBoundsFromShowState(aura::Window* window) { - switch (window->GetIntProperty(aura::client::kShowStateKey)) { - case ui::SHOW_STATE_NORMAL: { - const gfx::Rect* restore = GetRestoreBounds(window); - window->SetProperty(aura::client::kRestoreBoundsKey, NULL); - if (restore) - window->SetBounds(*restore); - delete restore; - break; - } - - case ui::SHOW_STATE_MAXIMIZED: - SetRestoreBoundsIfNotSet(window); - window->SetBounds(gfx::Screen::GetMonitorWorkAreaNearestWindow(window)); - break; - - case ui::SHOW_STATE_FULLSCREEN: - SetRestoreBoundsIfNotSet(window); - window->SetBounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); - break; - - default: - break; - } -} - void ToplevelLayoutManager::UpdateShelfVisibility() { if (!shelf_) return; - shelf_->SetVisible(!window_util::HasFullscreenWindow(windows_)); -} - -void ToplevelLayoutManager::UpdateStatusAreaVisibility() { - if (!status_area_widget_) - return; - // Full screen windows should hide the status area widget. - if (window_util::HasFullscreenWindow(windows_)) - status_area_widget_->Hide(); - else - status_area_widget_->Show(); + shelf_->SetVisible(!window_util::HasFullscreenWindow(windows())); } } // namespace internal diff --git a/ash/wm/toplevel_layout_manager.h b/ash/wm/toplevel_layout_manager.h index 4d9412b..fd12958 100644 --- a/ash/wm/toplevel_layout_manager.h +++ b/ash/wm/toplevel_layout_manager.h @@ -6,21 +6,10 @@ #define ASH_WM_TOPLEVEL_LAYOUT_MANAGER_H_ #pragma once -#include <set> - +#include "ash/ash_export.h" +#include "ash/wm/base_layout_manager.h" #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/root_window_observer.h" -#include "ui/aura/window_observer.h" -#include "ash/ash_export.h" - -namespace aura { -class Window; -} -namespace views { -class Widget; -} namespace ash { namespace internal { @@ -28,23 +17,20 @@ namespace internal { class ShelfLayoutManager; // ToplevelLayoutManager is the LayoutManager installed on a container that -// hosts what the shell considers to be top-level windows. It is used if the -// WorkspaceManager is not enabled. ToplevelLayoutManager listens for changes to -// kShowStateKey and resizes the window appropriately. -class ASH_EXPORT ToplevelLayoutManager : public aura::LayoutManager, - public aura::RootWindowObserver, - public aura::WindowObserver { +// hosts what the shell considers to be top-level windows. +// +// ToplevelLayoutManager is used if the WorkspaceManager is not enabled and +// compact window mode is not enabled. It is intended to implement the simplest +// possible window management code. If you have a more complex window mode +// please implement a new LayoutManager for it. +class ASH_EXPORT ToplevelLayoutManager : public BaseLayoutManager { public: ToplevelLayoutManager(); virtual ~ToplevelLayoutManager(); void set_shelf(ShelfLayoutManager* shelf) { shelf_ = shelf; } - void set_status_area_widget(views::Widget* widget) { - status_area_widget_ = widget; - } // LayoutManager overrides: - virtual void OnWindowResized() OVERRIDE; virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; virtual void OnChildWindowVisibilityChanged(aura::Window* child, @@ -52,39 +38,20 @@ class ASH_EXPORT ToplevelLayoutManager : public aura::LayoutManager, virtual void SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE; - // RootWindowObserver overrides: - virtual void OnRootWindowResized(const gfx::Size& new_size) OVERRIDE; - // WindowObserver overrides: virtual void OnWindowPropertyChanged(aura::Window* window, const char* name, void* old) OVERRIDE; private: - typedef std::set<aura::Window*> WindowSet; - - // Update window bounds based on a change in show state. - void UpdateBoundsFromShowState(aura::Window* window); - // Updates the visibility of the shelf based on if there are any full screen // windows. void UpdateShelfVisibility(); - // Hides the status area if we are managing it and full screen windows are - // visible. - void UpdateStatusAreaVisibility(); - - // Set of windows we're listening to. - WindowSet windows_; - // Owned by the Shell container window LauncherContainer. May be NULL if // we're not using a shelf. ShelfLayoutManager* shelf_; - // Status area with clock, network, battery, etc. icons. May be NULL if the - // shelf is managing the status area. - views::Widget* status_area_widget_; - DISALLOW_COPY_AND_ASSIGN(ToplevelLayoutManager); }; diff --git a/ash/wm/toplevel_layout_manager_unittest.cc b/ash/wm/toplevel_layout_manager_unittest.cc index 05bc69c..abbbb2b 100644 --- a/ash/wm/toplevel_layout_manager_unittest.cc +++ b/ash/wm/toplevel_layout_manager_unittest.cc @@ -11,6 +11,7 @@ #include "ui/aura/root_window.h" #include "ui/aura/screen_aura.h" #include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_windows.h" #include "ui/base/ui_base_types.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h" @@ -41,12 +42,7 @@ class ToplevelLayoutManagerTest : public aura::test::AuraTestBase { } aura::Window* CreateTestWindow(const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(NULL); - window->Init(ui::Layer::LAYER_HAS_NO_TEXTURE); - window->SetBounds(bounds); - window->Show(); - window->SetParent(container_.get()); - return window; + return aura::test::CreateTestWindowWithBounds(bounds, container_.get()); } // Returns widget owned by its parent, so doesn't need scoped_ptr<>. @@ -182,24 +178,6 @@ TEST_F(ToplevelLayoutManagerTest, WindowStaysOnScreen) { EXPECT_LT(window->bounds().x(), work_area.right()); } -// Tests status area visibility during window maximize and fullscreen. -TEST_F(ToplevelLayoutManagerTest, StatusAreaVisibility) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - views::Widget* widget = CreateTestWidget(); - layout_manager()->set_status_area_widget(widget); - EXPECT_TRUE(widget->IsVisible()); - window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_TRUE(widget->IsVisible()); - window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_TRUE(widget->IsVisible()); - window->SetIntProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - EXPECT_FALSE(widget->IsVisible()); - window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_TRUE(widget->IsVisible()); -} - // Tests shelf visibility during window maximize and fullscreen. TEST_F(ToplevelLayoutManagerTest, ShelfVisibility) { gfx::Rect bounds(100, 100, 200, 200); |