summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-17 19:12:04 +0000
committerjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-17 19:12:04 +0000
commitb52a3f33699d38c121e59b4f01338e4c8e592f02 (patch)
treed8cab18142cc9750850826593066369972f710b2 /ash
parentf308e5b14148b7311867f19f80b35dda10f11589 (diff)
downloadchromium_src-b52a3f33699d38c121e59b4f01338e4c8e592f02.zip
chromium_src-b52a3f33699d38c121e59b4f01338e4c8e592f02.tar.gz
chromium_src-b52a3f33699d38c121e59b4f01338e4c8e592f02.tar.bz2
Aura: Resize windows when screen/host window size changes
* Monitor root window for size changes and resize maximized windows when it changes. This also ensures windows in compact window mode continue to fill the screen. * Merged CompactLayoutManager and ToplevelLayoutManager. I expected them to diverge, but they ended up being nearly identical. * Expanded unit test coverage of ToplevelLayoutManager. * Put a few window_util functions into a namespace. I didn't do them all because the patch would be too big. BUG=109952 TEST=Run Aura, maximize an Aura window, change the size of the host window (or plug an external monitor into your ChromeOS device). Window should still fill the screen. Run Aura in compact window mode (default on small screen laptops). Plug in an external monitor. Windows should still fill the screen. Review URL: https://chromiumcodereview.appspot.com/9214009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117931 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp2
-rw-r--r--ash/shell.cc7
-rw-r--r--ash/wm/compact_layout_manager.cc85
-rw-r--r--ash/wm/compact_layout_manager.h66
-rw-r--r--ash/wm/toplevel_layout_manager.cc123
-rw-r--r--ash/wm/toplevel_layout_manager.h37
-rw-r--r--ash/wm/toplevel_layout_manager_unittest.cc154
-rw-r--r--ash/wm/toplevel_window_event_filter.cc2
-rw-r--r--ash/wm/toplevel_window_event_filter_unittest.cc6
-rw-r--r--ash/wm/window_util.cc39
-rw-r--r--ash/wm/window_util.h15
-rw-r--r--ash/wm/workspace_controller.h6
12 files changed, 327 insertions, 215 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index a2f6a33..5e7a95a 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -100,8 +100,6 @@
'wm/activation_controller.h',
'wm/always_on_top_controller.cc',
'wm/always_on_top_controller.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',
diff --git a/ash/shell.cc b/ash/shell.cc
index c2a4130..54d9887 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -18,7 +18,6 @@
#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"
@@ -313,8 +312,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()) {
- default_container->SetLayoutManager(
- new internal::CompactLayoutManager(status_widget));
+ internal::ToplevelLayoutManager* toplevel_layout_manager =
+ new internal::ToplevelLayoutManager();
+ default_container->SetLayoutManager(toplevel_layout_manager);
+ toplevel_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/compact_layout_manager.cc b/ash/wm/compact_layout_manager.cc
deleted file mode 100644
index a4a2847..0000000
--- a/ash/wm/compact_layout_manager.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2011 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/aura/window.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/gfx/screen.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-namespace internal {
-
-CompactLayoutManager::CompactLayoutManager(views::Widget* status_area_widget)
- : status_area_widget_(status_area_widget) {
-}
-
-CompactLayoutManager::~CompactLayoutManager() {
- for (Windows::const_iterator i = windows_.begin(); i != windows_.end(); ++i)
- (*i)->RemoveObserver(this);
-}
-
-void CompactLayoutManager::OnWindowResized() {
-}
-
-void CompactLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
- windows_.insert(child);
- child->AddObserver(this);
- if (child->GetProperty(aura::client::kShowStateKey)) {
- UpdateBoundsFromShowState(child);
- UpdateStatusAreaVisibility();
- }
-}
-
-void CompactLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
- windows_.erase(child);
- child->RemoveObserver(this);
-}
-
-void CompactLayoutManager::OnChildWindowVisibilityChanged(
- aura::Window* child,
- bool visibile) {
- UpdateStatusAreaVisibility();
-}
-
-void CompactLayoutManager::SetChildBounds(
- aura::Window* child,
- const gfx::Rect& requested_bounds) {
- gfx::Rect bounds = requested_bounds;
- // Avoid a janky resize on startup by ensuring the initial bounds fill the
- // screen.
- if (IsWindowMaximized(child))
- bounds = gfx::Screen::GetPrimaryMonitorBounds();
- SetChildBoundsDirect(child, bounds);
-}
-
-void CompactLayoutManager::OnWindowPropertyChanged(aura::Window* window,
- const char* name,
- void* old) {
- if (name == aura::client::kShowStateKey) {
- UpdateBoundsFromShowState(window);
- UpdateStatusAreaVisibility();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// CompactLayoutManager, private:
-
-void CompactLayoutManager::UpdateStatusAreaVisibility() {
- if (!status_area_widget_)
- return;
- // Full screen windows should hide the status area widget.
- bool fullscreen_window = HasFullscreenWindow(windows_);
- bool widget_visible = status_area_widget_->IsVisible();
- if (fullscreen_window && widget_visible)
- status_area_widget_->Hide();
- else if (!fullscreen_window && !widget_visible)
- status_area_widget_->Show();
-}
-
-} // namespace internal
-} // namespace ash
diff --git a/ash/wm/compact_layout_manager.h b/ash/wm/compact_layout_manager.h
deleted file mode 100644
index 8785903..0000000
--- a/ash/wm/compact_layout_manager.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2011 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 <set>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ui/aura/layout_manager.h"
-#include "ui/aura/window_observer.h"
-#include "ash/ash_export.h"
-
-namespace views {
-class Widget;
-}
-
-namespace ash {
-namespace internal {
-
-// CompactLayoutManager is an alternate LayoutManager for the container that
-// hosts what the shell considers to be top-level windows. It is used for low
-// resolution screens and keeps the main browser window maximized.
-// It listens for changes to kShowStateKey and resizes the window appropriately.
-class ASH_EXPORT CompactLayoutManager : public aura::LayoutManager,
- public aura::WindowObserver {
- public:
- explicit CompactLayoutManager(views::Widget* status_area_widget);
- virtual ~CompactLayoutManager();
-
- // 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;
-
- // WindowObserver overrides:
- virtual void OnWindowPropertyChanged(aura::Window* window,
- const char* name,
- void* old) OVERRIDE;
-
- private:
- typedef std::set<aura::Window*> Windows;
-
- // Hides the status area when full screen windows cover it.
- void UpdateStatusAreaVisibility();
-
- // Set of windows we're listening to.
- Windows windows_;
-
- // Weak pointer to status area with clock, network, battery, etc. icons.
- 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/toplevel_layout_manager.cc b/ash/wm/toplevel_layout_manager.cc
index 09a5ae1..83a8552 100644
--- a/ash/wm/toplevel_layout_manager.cc
+++ b/ash/wm/toplevel_layout_manager.cc
@@ -1,27 +1,60 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/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 {
+
+// Minimum number of pixels at the window top to keep visible on screen.
+const int kMinimumWindowTopVisible = 12;
+
+// Returns a bounds rectangle with at least a few pixels of the window's
+// title bar visible.
+gfx::Rect BoundsWithTitleBarVisible(const gfx::Rect& window_bounds,
+ const gfx::Rect& work_area) {
+ gfx::Rect bounds(window_bounds);
+ // Ensure title bar is vertically on screen.
+ if (bounds.y() < work_area.y())
+ bounds.set_y(work_area.y());
+ else if (bounds.y() + kMinimumWindowTopVisible > work_area.bottom())
+ bounds.set_y(work_area.bottom() - kMinimumWindowTopVisible);
+ return bounds;
+}
+
+} // namespace
namespace ash {
namespace internal {
-ToplevelLayoutManager::ToplevelLayoutManager() : shelf_(NULL) {
+/////////////////////////////////////////////////////////////////////////////
+// ToplevelLayoutManager, public:
+
+ToplevelLayoutManager::ToplevelLayoutManager()
+ : shelf_(NULL),
+ status_area_widget_(NULL) {
+ aura::RootWindow::GetInstance()->AddRootWindowObserver(this);
}
ToplevelLayoutManager::~ToplevelLayoutManager() {
- for (Windows::const_iterator i = windows_.begin(); i != windows_.end(); ++i)
+ 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() {
}
@@ -31,6 +64,7 @@ void ToplevelLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
if (child->GetProperty(aura::client::kShowStateKey)) {
UpdateBoundsFromShowState(child);
UpdateShelfVisibility();
+ UpdateStatusAreaVisibility();
}
}
@@ -39,38 +73,107 @@ void ToplevelLayoutManager::OnWillRemoveWindowFromLayout(
windows_.erase(child);
child->RemoveObserver(this);
UpdateShelfVisibility();
+ UpdateStatusAreaVisibility();
}
void ToplevelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
bool visibile) {
UpdateShelfVisibility();
+ UpdateStatusAreaVisibility();
}
void ToplevelLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
- const static int kTitleHeight = 12;
gfx::Rect child_bounds(requested_bounds);
- gfx::Rect work_area = gfx::Screen::GetMonitorWorkAreaNearestWindow(child);
- if (child_bounds.y() < 0)
- child_bounds.set_y(0);
- else if (child_bounds.y() + kTitleHeight > work_area.bottom())
- child_bounds.set_y(work_area.bottom() - kTitleHeight);
+ // 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
+ 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));
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// ToplevelLayoutManager, WindowObserver overrides:
+
void ToplevelLayoutManager::OnWindowPropertyChanged(aura::Window* window,
const char* name,
void* old) {
if (name == aura::client::kShowStateKey) {
UpdateBoundsFromShowState(window);
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(!HasFullscreenWindow(windows_));
+ 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();
}
} // namespace internal
diff --git a/ash/wm/toplevel_layout_manager.h b/ash/wm/toplevel_layout_manager.h
index 27aa7ac..4d9412b 100644
--- a/ash/wm/toplevel_layout_manager.h
+++ b/ash/wm/toplevel_layout_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -11,9 +11,17 @@
#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 {
@@ -24,12 +32,16 @@ class ShelfLayoutManager;
// WorkspaceManager is not enabled. ToplevelLayoutManager listens for changes to
// kShowStateKey and resizes the window appropriately.
class ASH_EXPORT ToplevelLayoutManager : public aura::LayoutManager,
- public aura::WindowObserver {
+ public aura::RootWindowObserver,
+ public aura::WindowObserver {
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;
@@ -40,24 +52,39 @@ 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*> Windows;
+ 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.
- Windows windows_;
+ WindowSet windows_;
- // May be NULL if we're not using a shelf.
+ // 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 8f150ff..05bc69c 100644
--- a/ash/wm/toplevel_layout_manager_unittest.cc
+++ b/ash/wm/toplevel_layout_manager_unittest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/toplevel_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"
@@ -12,6 +13,7 @@
#include "ui/aura/test/aura_test_base.h"
#include "ui/base/ui_base_types.h"
#include "ui/aura/window.h"
+#include "ui/views/widget/widget.h"
namespace ash {
@@ -22,11 +24,15 @@ class ToplevelLayoutManagerTest : public aura::test::AuraTestBase {
ToplevelLayoutManagerTest() : layout_manager_(NULL) {}
virtual ~ToplevelLayoutManagerTest() {}
+ internal::ToplevelLayoutManager* 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(500, 400));
+ 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));
@@ -43,6 +49,16 @@ class ToplevelLayoutManagerTest : public aura::test::AuraTestBase {
return window;
}
+ // 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::ToplevelLayoutManager* layout_manager_;
@@ -59,22 +75,156 @@ TEST_F(ToplevelLayoutManagerTest, 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(ToplevelLayoutManagerTest, 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(ToplevelLayoutManagerTest, 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(ToplevelLayoutManagerTest, 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(ToplevelLayoutManagerTest, 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());
+}
+
+// Test that window stays on screen despite attempts to move it off.
+TEST_F(ToplevelLayoutManagerTest, WindowStaysOnScreen) {
+ scoped_ptr<aura::Window> window(
+ CreateTestWindow(gfx::Rect(10, 20, 300, 200)));
+ gfx::Rect work_area = gfx::Screen::GetMonitorAreaNearestWindow(window.get());
+ // Invariant: The top edge of the window is inside the work area and at least
+ // one pixel is visible horizontally.
+ // and horizontal dimensions.
+ EXPECT_GE(window->bounds().y(), 0);
+ EXPECT_LT(window->bounds().y(), work_area.bottom());
+ EXPECT_GE(window->bounds().right(), 0);
+ EXPECT_LT(window->bounds().x(), work_area.right());
+
+ // Try to move window above the top of screen.
+ window->SetBounds(gfx::Rect(10, -1, 300, 200));
+ EXPECT_GE(window->bounds().y(), 0);
+
+ // Try to move window below the bottom.
+ window->SetBounds(gfx::Rect(10, work_area.bottom(), 300, 200));
+ EXPECT_LT(window->bounds().y(), work_area.bottom());
+
+ // Put the screen near the right edge, then shrink the host window.
+ window->SetBounds(gfx::Rect(work_area.right() - 15, 20, 300, 200));
+ aura::RootWindow::GetInstance()->SetHostSize(gfx::Size(350, 250));
+ EXPECT_GE(window->bounds().y(), 0);
+ EXPECT_LT(window->bounds().y(), work_area.bottom());
+ EXPECT_GE(window->bounds().right(), 0);
+ 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);
+ scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
+ views::Widget* launcher = CreateTestWidget();
+ views::Widget* status = CreateTestWidget();
+ scoped_ptr<internal::ShelfLayoutManager> shelf_layout_manager(
+ new internal::ShelfLayoutManager(launcher, status));
+ layout_manager()->set_shelf(shelf_layout_manager.get());
+ EXPECT_TRUE(shelf_layout_manager.get()->visible());
+ window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ EXPECT_TRUE(shelf_layout_manager.get()->visible());
+ window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ EXPECT_TRUE(shelf_layout_manager.get()->visible());
+ window->SetIntProperty(aura::client::kShowStateKey,
+ ui::SHOW_STATE_FULLSCREEN);
+ EXPECT_FALSE(shelf_layout_manager.get()->visible());
+ window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ EXPECT_TRUE(shelf_layout_manager.get()->visible());
+ // Window depends on layout manager for cleanup.
+ window.reset();
+ // shelf_layout_manager is observing these animations so clean them up first.
+ launcher->GetNativeView()->layer()->GetAnimator()->StopAnimating();
+ status->GetNativeView()->layer()->GetAnimator()->StopAnimating();
+ shelf_layout_manager.reset();
+}
+
} // namespace ash
diff --git a/ash/wm/toplevel_window_event_filter.cc b/ash/wm/toplevel_window_event_filter.cc
index ccc7a4e..3396eed 100644
--- a/ash/wm/toplevel_window_event_filter.cc
+++ b/ash/wm/toplevel_window_event_filter.cc
@@ -129,7 +129,7 @@ bool IsBottomEdge(int window_component) {
void ToggleMaximizedState(aura::Window* window) {
window->SetIntProperty(aura::client::kShowStateKey,
- IsWindowMaximized(window) ?
+ window_util::IsWindowMaximized(window) ?
ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_MAXIMIZED);
}
diff --git a/ash/wm/toplevel_window_event_filter_unittest.cc b/ash/wm/toplevel_window_event_filter_unittest.cc
index 0fef59d..db13f51 100644
--- a/ash/wm/toplevel_window_event_filter_unittest.cc
+++ b/ash/wm/toplevel_window_event_filter_unittest.cc
@@ -309,15 +309,15 @@ TEST_F(ToplevelWindowEventFilterTest, BottomRightPastMinimum) {
TEST_F(ToplevelWindowEventFilterTest, DoubleClickCaptionTogglesMaximize) {
scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
- EXPECT_FALSE(IsWindowMaximized(w1.get()));
+ EXPECT_FALSE(window_util::IsWindowMaximized(w1.get()));
aura::test::EventGenerator generator(w1.get());
generator.DoubleClickLeftButton();
- EXPECT_TRUE(IsWindowMaximized(w1.get()));
+ EXPECT_TRUE(window_util::IsWindowMaximized(w1.get()));
generator.DoubleClickLeftButton();
- EXPECT_FALSE(IsWindowMaximized(w1.get()));
+ EXPECT_FALSE(window_util::IsWindowMaximized(w1.get()));
}
TEST_F(ToplevelWindowEventFilterTest, BottomRightWorkArea) {
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc
index 37104d7..c402ef2 100644
--- a/ash/wm/window_util.cc
+++ b/ash/wm/window_util.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/window_util.h"
#include "ash/wm/activation_controller.h"
-#include "ash/wm/property_util.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/root_window.h"
@@ -15,11 +14,6 @@
namespace ash {
-bool IsWindowMaximized(aura::Window* window) {
- return window->GetIntProperty(aura::client::kShowStateKey) ==
- ui::SHOW_STATE_MAXIMIZED;
-}
-
void ActivateWindow(aura::Window* window) {
aura::client::GetActivationClient()->ActivateWindow(window);
}
@@ -40,30 +34,16 @@ aura::Window* GetActivatableWindow(aura::Window* window) {
return internal::ActivationController::GetActivatableWindow(window);
}
-void 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;
+namespace window_util {
- case ui::SHOW_STATE_FULLSCREEN:
- SetRestoreBoundsIfNotSet(window);
- window->SetBounds(gfx::Screen::GetMonitorAreaNearestWindow(window));
- break;
+bool IsWindowMaximized(aura::Window* window) {
+ return window->GetIntProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_MAXIMIZED;
+}
- default:
- break;
- }
+bool IsWindowFullscreen(aura::Window* window) {
+ return window->GetIntProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_FULLSCREEN;
}
bool HasFullscreenWindow(const WindowSet& windows) {
@@ -76,4 +56,5 @@ bool HasFullscreenWindow(const WindowSet& windows) {
return false;
}
+} // namespace window_util
} // namespace ash
diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h
index e96591f..dbafb5b 100644
--- a/ash/wm/window_util.h
+++ b/ash/wm/window_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -18,9 +18,6 @@ namespace ash {
// TODO(jamescook): Put all these functions in namespace window_util.
-// Returns true if |window| is in the maximized state.
-ASH_EXPORT bool IsWindowMaximized(aura::Window* window);
-
// Convenience setters/getters for |aura::client::kRootWindowActiveWindow|.
ASH_EXPORT void ActivateWindow(aura::Window* window);
ASH_EXPORT void DeactivateWindow(aura::Window* window);
@@ -34,13 +31,19 @@ ASH_EXPORT aura::Window* GetActiveWindow();
// this is probably what you're looking for.
ASH_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
-// Update window bounds based on a change in show state.
-ASH_EXPORT void UpdateBoundsFromShowState(aura::Window* window);
+namespace window_util {
+
+// Returns true if |window| is in the maximized state.
+ASH_EXPORT bool IsWindowMaximized(aura::Window* window);
+
+// Returns true if |window| is in the fullscreen state.
+ASH_EXPORT bool IsWindowFullscreen(aura::Window* window);
// Returns true if the set of |windows| contains a full-screen window.
typedef std::set<aura::Window*> WindowSet;
ASH_EXPORT bool HasFullscreenWindow(const WindowSet& windows);
+} // namespace window_util
} // namespace ash
#endif // ASH_WM_WINDOW_UTIL_H_
diff --git a/ash/wm/workspace_controller.h b/ash/wm/workspace_controller.h
index f17a395..4e20a43 100644
--- a/ash/wm/workspace_controller.h
+++ b/ash/wm/workspace_controller.h
@@ -29,9 +29,9 @@ namespace internal {
class WorkspaceManager;
-// WorkspaceControlls owns a WorkspaceManager. WorkspaceControlls bridges
-// events From RootWindowObserver translating them to WorkspaceManager, and
-// a move event between Laucher and Workspace.
+// WorkspaceController owns a WorkspaceManager. WorkspaceController bridges
+// events from RootWindowObserver translating them to WorkspaceManager, and
+// a move event between Launcher and Workspace.
class ASH_EXPORT WorkspaceController :
public aura::RootWindowObserver,
public aura::WindowObserver,