diff options
author | oshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 23:19:12 +0000 |
---|---|---|
committer | oshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 23:19:12 +0000 |
commit | 37974ad4ffcf30f18c25c28e9dccd098ab5e71d8 (patch) | |
tree | 808da500f37170706e695c9a029a1b649a1a87bc /ui/aura_shell | |
parent | e8ba615ab61359130553c7dd6419c331be5c49ad (diff) | |
download | chromium_src-37974ad4ffcf30f18c25c28e9dccd098ab5e71d8.zip chromium_src-37974ad4ffcf30f18c25c28e9dccd098ab5e71d8.tar.gz chromium_src-37974ad4ffcf30f18c25c28e9dccd098ab5e71d8.tar.bz2 |
Move maximize/fullscreen/restore to shell
With this CL, window is now correctly maximized/fullscreen'ed on aura desktop.
* Added OnPropertyChanged to WindowObserver
* Added Get/Set IntProperty to simplify handling int value properties.
* Remove IsOrContainsFullscreen. Added Workspace::ContainsFullscreen instead. We need this to autohide launcher.
BUG=97257,97259
TEST=new test for property change notification. existing tests are updated, except maximized/fullscreen drag test. I'll add it to new set of tests that verifies window dragging within workspace.
Review URL: http://codereview.chromium.org/8400063
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108192 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura_shell')
-rw-r--r-- | ui/aura_shell/aura_shell.gyp | 4 | ||||
-rw-r--r-- | ui/aura_shell/default_container_layout_manager.cc | 71 | ||||
-rw-r--r-- | ui/aura_shell/default_container_layout_manager.h | 18 | ||||
-rw-r--r-- | ui/aura_shell/default_container_layout_manager_unittest.cc | 191 | ||||
-rw-r--r-- | ui/aura_shell/desktop_layout_manager.cc | 5 | ||||
-rw-r--r-- | ui/aura_shell/desktop_layout_manager.h | 4 | ||||
-rw-r--r-- | ui/aura_shell/property_util.cc | 29 | ||||
-rw-r--r-- | ui/aura_shell/property_util.h | 33 | ||||
-rw-r--r-- | ui/aura_shell/show_state_controller.cc | 50 | ||||
-rw-r--r-- | ui/aura_shell/show_state_controller.h | 44 | ||||
-rw-r--r-- | ui/aura_shell/workspace/workspace.cc | 69 | ||||
-rw-r--r-- | ui/aura_shell/workspace/workspace.h | 3 | ||||
-rw-r--r-- | ui/aura_shell/workspace/workspace_manager_unittest.cc | 39 |
13 files changed, 508 insertions, 52 deletions
diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp index 743b832..4bf31bf 100644 --- a/ui/aura_shell/aura_shell.gyp +++ b/ui/aura_shell/aura_shell.gyp @@ -57,11 +57,15 @@ 'launcher/view_model.h', 'launcher/view_model_utils.cc', 'launcher/view_model_utils.h', + 'property_util.cc', + 'property_util.h', 'shell.cc', 'shell.h', 'shell_delegate.h', 'shell_factory.h', 'shell_window_ids.h', + 'show_state_controller.h', + 'show_state_controller.cc', 'status_area_view.cc', 'status_area_view.h', 'toplevel_frame_view.cc', diff --git a/ui/aura_shell/default_container_layout_manager.cc b/ui/aura_shell/default_container_layout_manager.cc index 54b6f53..d9658e0 100644 --- a/ui/aura_shell/default_container_layout_manager.cc +++ b/ui/aura_shell/default_container_layout_manager.cc @@ -5,13 +5,18 @@ #include "ui/aura_shell/default_container_layout_manager.h" #include "base/auto_reset.h" +#include "ui/aura/aura_constants.h" #include "ui/aura/desktop.h" #include "ui/aura/event.h" #include "ui/aura/window.h" #include "ui/aura/screen_aura.h" #include "ui/aura/window_types.h" +#include "ui/aura/window_observer.h" +#include "ui/aura_shell/property_util.h" +#include "ui/aura_shell/show_state_controller.h" #include "ui/aura_shell/workspace/workspace.h" #include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/rect.h" #include "views/widget/native_widget_aura.h" @@ -27,7 +32,8 @@ DefaultContainerLayoutManager::DefaultContainerLayoutManager( : owner_(owner), workspace_manager_(workspace_manager), drag_window_(NULL), - ignore_calculate_bounds_(false) { + ignore_calculate_bounds_(false), + show_state_controller_(new ShowStateController(this)) { } DefaultContainerLayoutManager::~DefaultContainerLayoutManager() {} @@ -102,6 +108,11 @@ void DefaultContainerLayoutManager::OnWindowAdded(aura::Window* child) { if (child->type() != aura::WINDOW_TYPE_NORMAL || child->transient_parent()) return; + if (!child->GetProperty(aura::kShowStateKey)) + child->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); + + child->AddObserver(show_state_controller_.get()); + AutoReset<bool> reset(&ignore_calculate_bounds_, true); Workspace* workspace = workspace_manager_->GetActiveWorkspace(); @@ -121,6 +132,9 @@ void DefaultContainerLayoutManager::OnWindowAdded(aura::Window* child) { void DefaultContainerLayoutManager::OnWillRemoveWindow(aura::Window* child) { AutoReset<bool> reset(&ignore_calculate_bounds_, true); + child->RemoveObserver(show_state_controller_.get()); + ClearRestoreBounds(child); + Workspace* workspace = workspace_manager_->FindBy(child); if (!workspace) return; @@ -135,28 +149,51 @@ void DefaultContainerLayoutManager::OnChildWindowVisibilityChanged( NOTIMPLEMENTED(); } -void DefaultContainerLayoutManager::CalculateBoundsForChild( +void DefaultContainerLayoutManager::SetChildBounds( aura::Window* child, - gfx::Rect* requested_bounds) { + const gfx::Rect& requested_bounds) { + gfx::Rect adjusted_bounds = requested_bounds; + + // First, calculate the adjusted bounds. if (child->type() != aura::WINDOW_TYPE_NORMAL || ignore_calculate_bounds_ || - child->transient_parent()) - return; - - // If a drag window is requesting bounds, make sure its attached to - // the workarea's top and fits within the total drag area. - if (drag_window_) { + child->transient_parent()) { + // Use the requested bounds as is. + } else if (drag_window_) { + // If a drag window is requesting bounds, make sure its attached to + // the workarea's top and fits within the total drag area. gfx::Rect drag_area = workspace_manager_->GetDragAreaBounds(); - requested_bounds->set_y(drag_area.y()); - *requested_bounds = requested_bounds->AdjustToFit(drag_area); - return; + adjusted_bounds.set_y(drag_area.y()); + adjusted_bounds = adjusted_bounds.AdjustToFit(drag_area); + } else { + Workspace* workspace = workspace_manager_->FindBy(child); + gfx::Rect work_area = workspace->GetWorkAreaBounds(); + adjusted_bounds.set_origin( + gfx::Point(child->GetTargetBounds().x(), work_area.y())); + adjusted_bounds = adjusted_bounds.AdjustToFit(work_area); } - Workspace* workspace = workspace_manager_->FindBy(child); - gfx::Rect work_area = workspace->GetWorkAreaBounds(); - requested_bounds->set_origin( - gfx::Point(child->GetTargetBounds().x(), work_area.y())); - *requested_bounds = requested_bounds->AdjustToFit(work_area); + ui::WindowShowState show_state = static_cast<ui::WindowShowState>( + child->GetIntProperty(aura::kShowStateKey)); + + // Second, check if the window is either maximized or in fullscreen mode. + if (show_state == ui::SHOW_STATE_MAXIMIZED || + show_state == ui::SHOW_STATE_FULLSCREEN) { + // If the request is not from workspace manager, + // remember the requested bounds. + if (!ignore_calculate_bounds_) + SetRestoreBounds(child, adjusted_bounds); + + Workspace* workspace = workspace_manager_->FindBy(child); + if (show_state == ui::SHOW_STATE_MAXIMIZED) + adjusted_bounds = workspace->GetWorkAreaBounds(); + else + adjusted_bounds = workspace->bounds(); + // Don't + if (child->GetTargetBounds() == adjusted_bounds) + return; + } + SetChildBoundsDirect(child, adjusted_bounds); } } // namespace internal diff --git a/ui/aura_shell/default_container_layout_manager.h b/ui/aura_shell/default_container_layout_manager.h index cf2fe9d..cd4421c 100644 --- a/ui/aura_shell/default_container_layout_manager.h +++ b/ui/aura_shell/default_container_layout_manager.h @@ -8,6 +8,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "ui/aura/layout_manager.h" #include "ui/aura_shell/aura_shell_export.h" @@ -23,6 +24,7 @@ class Rect; namespace aura_shell { namespace internal { +class ShowStateController; class WorkspaceManager; // LayoutManager for the default window container. @@ -33,6 +35,11 @@ class AURA_SHELL_EXPORT DefaultContainerLayoutManager WorkspaceManager* workspace_manager); virtual ~DefaultContainerLayoutManager(); + // Returns the workspace manager for this container. + WorkspaceManager* workspace_manager() { + return workspace_manager_; + } + // Invoked when a window receives drag event. void PrepareForMoveOrResize(aura::Window* drag, aura::MouseEvent* event); @@ -48,8 +55,9 @@ class AURA_SHELL_EXPORT DefaultContainerLayoutManager // Invoked when a user finished resizing window. void EndResize(aura::Window* drag, aura::MouseEvent* evnet); - // If true, |CalculateBoundsForChild| does nothing. Use in situations where - // you want to circumvent what CalculateBoundsForChild() would normally do. + // If true, |SetChildBounds| does not modify the requested bounds. + // Use in situations where you want to circumvent what + // SetChildBounds() would normally do. void set_ignore_calculate_bounds(bool value) { ignore_calculate_bounds_ = value; } @@ -60,8 +68,8 @@ class AURA_SHELL_EXPORT DefaultContainerLayoutManager virtual void OnWillRemoveWindow(aura::Window* child) OVERRIDE; virtual void OnChildWindowVisibilityChanged(aura::Window* child, bool visibile) OVERRIDE; - virtual void CalculateBoundsForChild(aura::Window* child, - gfx::Rect* requested_bounds) OVERRIDE; + virtual void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) OVERRIDE; private: aura::Window* owner_; @@ -76,6 +84,8 @@ class AURA_SHELL_EXPORT DefaultContainerLayoutManager // ignores bounds check. bool ignore_calculate_bounds_; + scoped_ptr<ShowStateController> show_state_controller_; + DISALLOW_COPY_AND_ASSIGN(DefaultContainerLayoutManager); }; diff --git a/ui/aura_shell/default_container_layout_manager_unittest.cc b/ui/aura_shell/default_container_layout_manager_unittest.cc index f96ea3f..765d167 100644 --- a/ui/aura_shell/default_container_layout_manager_unittest.cc +++ b/ui/aura_shell/default_container_layout_manager_unittest.cc @@ -7,11 +7,15 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_vector.h" -#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/aura_constants.h" #include "ui/aura/desktop.h" #include "ui/aura/screen_aura.h" +#include "ui/aura/test/aura_test_base.h" #include "ui/aura/window.h" +#include "ui/aura_shell/workspace/workspace.h" #include "ui/aura_shell/workspace/workspace_controller.h" +#include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/base/ui_base_types.h" #include "views/widget/native_widget_aura.h" namespace aura_shell { @@ -64,6 +68,11 @@ class DefaultContainerLayoutManagerTest : public aura::test::AuraTestBase { } protected: + aura_shell::internal::WorkspaceManager* workspace_manager() { + return workspace_controller_->layout_manager()->workspace_manager(); + } + + private: scoped_ptr<aura::Window> container_; scoped_ptr<aura_shell::internal::WorkspaceController> workspace_controller_; @@ -71,6 +80,24 @@ class DefaultContainerLayoutManagerTest : public aura::test::AuraTestBase { DISALLOW_COPY_AND_ASSIGN(DefaultContainerLayoutManagerTest); }; +// Utility functions to set and get show state on |window|. +void Maximize(aura::Window* window) { + window->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); +} + +void Fullscreen(aura::Window* window) { + window->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); +} + +void Restore(aura::Window* window) { + window->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); +} + +ui::WindowShowState GetShowState(aura::Window* window) { + return static_cast<ui::WindowShowState>( + window->GetIntProperty(aura::kShowStateKey)); +} + } // namespace #if !defined(OS_WIN) @@ -146,5 +173,167 @@ TEST_F(DefaultContainerLayoutManagerTest, IgnoreTransient) { EXPECT_EQ("0,0 200x200", window->bounds().ToString()); } +TEST_F(DefaultContainerLayoutManagerTest, Fullscreen) { + scoped_ptr<aura::Window> w( + CreateTestWindow(gfx::Rect(0, 0, 100, 100), container())); + gfx::Rect fullscreen_bounds = + workspace_manager()->FindBy(w.get())->bounds(); + gfx::Rect original_bounds = w->GetTargetBounds(); + + // Restoreing the restored window. + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + // Fullscreen + Fullscreen(w.get()); + EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetShowState(w.get())); + EXPECT_EQ(fullscreen_bounds.ToString(), w->bounds().ToString()); + w->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + Fullscreen(w.get()); + // Setting |ui::SHOW_STATE_FULLSCREEN| should have no additional effect. + Fullscreen(w.get()); + EXPECT_EQ(fullscreen_bounds, w->bounds()); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + // Calling SetBounds() in fullscreen mode should only update the + // restore bounds not change the bounds of the window. + gfx::Rect new_bounds(50, 50, 50, 50); + Fullscreen(w.get()); + w->SetBounds(new_bounds); + EXPECT_EQ(fullscreen_bounds.ToString(), w->bounds().ToString()); + EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetShowState(w.get())); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(50, w->bounds().height()); +} + +TEST_F(DefaultContainerLayoutManagerTest, Maximized) { + scoped_ptr<aura::Window> w( + CreateTestWindow(gfx::Rect(0, 0, 100, 100), container())); + gfx::Rect original_bounds = w->GetTargetBounds(); + gfx::Rect fullscreen_bounds = + workspace_manager()->FindBy(w.get())->bounds(); + gfx::Rect work_area_bounds = + workspace_manager()->FindBy(w.get())->GetWorkAreaBounds(); + + // Maximized + Maximize(w.get()); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetShowState(w.get())); + EXPECT_EQ(work_area_bounds.ToString(), w->bounds().ToString()); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + // Maximize twice + Maximize(w.get()); + Maximize(w.get()); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetShowState(w.get())); + EXPECT_EQ(work_area_bounds.ToString(), w->bounds().ToString()); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + // Maximized -> Fullscreen -> Maximized -> Normal + Maximize(w.get()); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetShowState(w.get())); + EXPECT_EQ(work_area_bounds.ToString(), w->bounds().ToString()); + Fullscreen(w.get()); + EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetShowState(w.get())); + EXPECT_EQ(fullscreen_bounds.ToString(), w->bounds().ToString()); + Maximize(w.get()); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetShowState(w.get())); + EXPECT_EQ(work_area_bounds.ToString(), w->bounds().ToString()); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(original_bounds.ToString(), w->bounds().ToString()); + + // Calling SetBounds() in maximized mode mode should only update the + // restore bounds not change the bounds of the window. + gfx::Rect new_bounds(50, 50, 50, 50); + Maximize(w.get()); + w->SetBounds(new_bounds); + EXPECT_EQ(work_area_bounds.ToString(), w->bounds().ToString()); + Restore(w.get()); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetShowState(w.get())); + EXPECT_EQ(50, w->bounds().height()); +} + +// Tests that fullscreen windows get resized after desktop is resized. +TEST_F(DefaultContainerLayoutManagerTest, FullscreenAfterDesktopResize) { + scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(300, 400), + container())); + gfx::Rect window_bounds = w1->GetTargetBounds(); + gfx::Rect fullscreen_bounds = + workspace_manager()->FindBy(w1.get())->bounds(); + + w1->Show(); + EXPECT_EQ(window_bounds.ToString(), w1->bounds().ToString()); + + Fullscreen(w1.get()); + EXPECT_EQ(fullscreen_bounds.ToString(), w1->bounds().ToString()); + + // Resize the desktop. + aura::Desktop* desktop = aura::Desktop::GetInstance(); + gfx::Size new_desktop_size = desktop->GetHostSize(); + new_desktop_size.Enlarge(100, 200); + desktop->OnHostResized(new_desktop_size); + + gfx::Rect new_fullscreen_bounds = + workspace_manager()->FindBy(w1.get())->bounds(); + EXPECT_NE(fullscreen_bounds.size().ToString(), + new_fullscreen_bounds.size().ToString()); + + EXPECT_EQ(new_fullscreen_bounds.ToString(), + w1->GetTargetBounds().ToString()); + + Restore(w1.get()); + + // The following test does not pass due to crbug.com/102413. + // TODO(oshima): Re-enable this once the bug is fixed. + // EXPECT_EQ(window_bounds.size().ToString(), + // w1->GetTargetBounds().size().ToString()); +} + +// Tests that maximized windows get resized after desktop is resized. +TEST_F(DefaultContainerLayoutManagerTest, MaximizeAfterDesktopResize) { + scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(300, 400), + container())); + gfx::Rect window_bounds = w1->GetTargetBounds(); + gfx::Rect work_area_bounds = + workspace_manager()->FindBy(w1.get())->GetWorkAreaBounds(); + + w1->Show(); + EXPECT_EQ(window_bounds.ToString(), w1->bounds().ToString()); + + Maximize(w1.get()); + EXPECT_EQ(work_area_bounds.ToString(), w1->bounds().ToString()); + + // Resize the desktop. + aura::Desktop* desktop = aura::Desktop::GetInstance(); + gfx::Size new_desktop_size = desktop->GetHostSize(); + new_desktop_size.Enlarge(100, 200); + desktop->OnHostResized(new_desktop_size); + + gfx::Rect new_work_area_bounds = + workspace_manager()->FindBy(w1.get())->bounds(); + EXPECT_NE(work_area_bounds.size().ToString(), + new_work_area_bounds.size().ToString()); + + EXPECT_EQ(new_work_area_bounds.ToString(), + w1->GetTargetBounds().ToString()); + + Restore(w1.get()); + // The following test does not pass due to crbug.com/102413. + // TODO(oshima): Re-enable this once the bug is fixed. + // EXPECT_EQ(window_bounds.size().ToString(), + // w1->GetTargetBounds().size().ToString()); +} + } // namespace test } // namespace aura_shell diff --git a/ui/aura_shell/desktop_layout_manager.cc b/ui/aura_shell/desktop_layout_manager.cc index 9ae4ca9..32db2ba 100644 --- a/ui/aura_shell/desktop_layout_manager.cc +++ b/ui/aura_shell/desktop_layout_manager.cc @@ -61,8 +61,9 @@ void DesktopLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, bool visibile) { } -void DesktopLayoutManager::CalculateBoundsForChild( - aura::Window* child, gfx::Rect* requested_bounds) { +void DesktopLayoutManager::SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) { + SetChildBoundsDirect(child, requested_bounds); } diff --git a/ui/aura_shell/desktop_layout_manager.h b/ui/aura_shell/desktop_layout_manager.h index e28a66e..74c00c5 100644 --- a/ui/aura_shell/desktop_layout_manager.h +++ b/ui/aura_shell/desktop_layout_manager.h @@ -48,8 +48,8 @@ class DesktopLayoutManager : public aura::LayoutManager { virtual void OnWillRemoveWindow(aura::Window* child) OVERRIDE; virtual void OnChildWindowVisibilityChanged(aura::Window* child, bool visibile) OVERRIDE; - virtual void CalculateBoundsForChild(aura::Window* child, - gfx::Rect* requested_bounds) OVERRIDE; + virtual void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) OVERRIDE; private: aura::Window* owner_; diff --git a/ui/aura_shell/property_util.cc b/ui/aura_shell/property_util.cc new file mode 100644 index 0000000..1247807 --- /dev/null +++ b/ui/aura_shell/property_util.cc @@ -0,0 +1,29 @@ +// 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 "ui/aura_shell/property_util.h" + +#include "ui/aura/aura_constants.h" +#include "ui/aura/window.h" +#include "ui/base/ui_base_types.h" +#include "ui/gfx/rect.h" + +namespace aura_shell { + +void SetRestoreBounds(aura::Window* window, const gfx::Rect& bounds) { + delete GetRestoreBounds(window); + window->SetProperty(aura::kRestoreBoundsKey, new gfx::Rect(bounds)); +} + +const gfx::Rect* GetRestoreBounds(aura::Window* window) { + return reinterpret_cast<gfx::Rect*>( + window->GetProperty(aura::kRestoreBoundsKey)); +} + +void ClearRestoreBounds(aura::Window* window) { + delete GetRestoreBounds(window); + window->SetProperty(aura::kRestoreBoundsKey, NULL); +} + +} diff --git a/ui/aura_shell/property_util.h b/ui/aura_shell/property_util.h new file mode 100644 index 0000000..35a09c9 --- /dev/null +++ b/ui/aura_shell/property_util.h @@ -0,0 +1,33 @@ +// 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 UI_AURA_SHELL_PROPERTY_UTIL_H_ +#define UI_AURA_SHELL_PROPERTY_UTIL_H_ +#pragma once + +namespace aura { +class Window; +} + +namespace gfx { +class Rect; +} + +namespace aura_shell { + +// Sets the restore bounds property on |window|. Deletes +// existing bounds value if exists. +void SetRestoreBounds(aura::Window* window, const gfx::Rect&); + +// Returns the restore bounds property on |window|. NULL if the +// restore bounds property does not exist for |window|. |window| +// owns the bounds object. +const gfx::Rect* GetRestoreBounds(aura::Window* window); + +// Deletes and clears the restore bounds property on |window|. +void ClearRestoreBounds(aura::Window* window); + +} + +#endif // UI_AURA_SHELL_PROPERTY_UTIL_H_ diff --git a/ui/aura_shell/show_state_controller.cc b/ui/aura_shell/show_state_controller.cc new file mode 100644 index 0000000..39e8c71 --- /dev/null +++ b/ui/aura_shell/show_state_controller.cc @@ -0,0 +1,50 @@ +// 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 "ui/aura_shell/show_state_controller.h" + +#include "ui/aura/aura_constants.h" +#include "ui/aura/window.h" +#include "ui/aura_shell/default_container_layout_manager.h" +#include "ui/aura_shell/property_util.h" +#include "ui/aura_shell/workspace/workspace.h" +#include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/base/ui_base_types.h" + +namespace aura_shell { +namespace internal { + +ShowStateController::ShowStateController( + DefaultContainerLayoutManager* layout_manager) + : layout_manager_(layout_manager) { +} + +ShowStateController::~ShowStateController() { +} + +void ShowStateController::OnPropertyChanged(aura::Window* window, + const char* name, + void* old) { + if (name != aura::kShowStateKey) + return; + if (window->GetIntProperty(name) == ui::SHOW_STATE_NORMAL) { + // Restore the size of window first, then let Workspace layout the window. + const gfx::Rect* restore = GetRestoreBounds(window); + window->SetProperty(aura::kRestoreBoundsKey, NULL); + if (restore) + window->SetBounds(*restore); + delete restore; + } else if (old == reinterpret_cast<void*>(ui::SHOW_STATE_NORMAL)) { + // Store the restore bounds only if previous state is normal. + DCHECK(window->GetProperty(aura::kRestoreBoundsKey) == NULL); + SetRestoreBounds(window, window->GetTargetBounds()); + } + + layout_manager_->set_ignore_calculate_bounds(true); + layout_manager_->workspace_manager()->FindBy(window)->Layout(NULL, window); + layout_manager_->set_ignore_calculate_bounds(false); +} + +} // namespace internal +} // namespace aura_shell diff --git a/ui/aura_shell/show_state_controller.h b/ui/aura_shell/show_state_controller.h new file mode 100644 index 0000000..cd5fbea --- /dev/null +++ b/ui/aura_shell/show_state_controller.h @@ -0,0 +1,44 @@ +// 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 UI_AURA_SHELL_SHOW_STATE_CONTROLLER_H_ +#define UI_AURA_SHELL_SHOW_STATE_CONTROLLER_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/window_observer.h" + +namespace aura { +class Window; +} + +namespace aura_shell { +namespace internal { + +class DefaultContainerLayoutManager; + +// ShowStateController controls the window's bounds when +// the window's show state property has changed. +class ShowStateController : public aura::WindowObserver { +public: + explicit ShowStateController(DefaultContainerLayoutManager* layout_manager); + virtual ~ShowStateController(); + + // Invoked when window proparty has changed. + virtual void OnPropertyChanged(aura::Window* window, + const char* name, + void* old) OVERRIDE; + + private: + // LayoutManager that downs this ShowStateController. + DefaultContainerLayoutManager* layout_manager_; + + DISALLOW_COPY_AND_ASSIGN(ShowStateController); +}; + +} // namepsace aura_shell +} // namepsace internal + +#endif // UI_AURA_SHELL_SHOW_STATE_CONTROLLER_H_ diff --git a/ui/aura_shell/workspace/workspace.cc b/ui/aura_shell/workspace/workspace.cc index 083644d..cf762f3 100644 --- a/ui/aura_shell/workspace/workspace.cc +++ b/ui/aura_shell/workspace/workspace.cc @@ -7,9 +7,12 @@ #include <algorithm> #include "base/logging.h" +#include "ui/aura/aura_constants.h" #include "ui/aura/desktop.h" #include "ui/aura/window.h" +#include "ui/aura_shell/property_util.h" #include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/compositor/layer.h" #include "ui/gfx/compositor/layer_animator.h" @@ -19,8 +22,26 @@ const int kWindowHorizontalMargin = 10; // Maximum number of windows a workspace can have. size_t g_max_windows_per_workspace = 2; + +// Returns the bounds of the window that should be used to calculate +// the layout. It uses the restore bounds if exits, or +// the target bounds of the window. The target bounds is the +// final destination of |window| if the window's layer is animating, +// or the current bounds of the window of no animation is currently +// in progress. +gfx::Rect GetLayoutBounds(aura::Window* window) { + const gfx::Rect* restore_bounds = aura_shell::GetRestoreBounds(window); + return restore_bounds ? *restore_bounds : window->GetTargetBounds(); +} + +// Returns the width of the window that should be used to calculate +// the layout. See |GetLayoutBounds| for more details. +int GetLayoutWidth(aura::Window* window) { + return GetLayoutBounds(window).width(); } +} // namespace + namespace aura_shell { namespace internal { @@ -171,7 +192,7 @@ void Workspace::Layout(aura::Window* ignore, aura::Window* no_animation) { gfx::Point(work_area.x() + dx, work_area.y()), no_animation != *i); } - dx += (*i)->bounds().width() + kWindowHorizontalMargin; + dx += GetLayoutWidth(*i) + kWindowHorizontalMargin; } } else { DCHECK_LT(windows_.size(), 3U); @@ -184,13 +205,25 @@ void Workspace::Layout(aura::Window* ignore, aura::Window* no_animation) { } if (windows_.size() == 2 && windows_[1] != ignore) { MoveWindowTo(windows_[1], - gfx::Point(work_area.right() - windows_[1]->bounds().width(), + gfx::Point(work_area.right() - GetLayoutWidth(windows_[1]), work_area.y()), no_animation != windows_[1]); } } } +bool Workspace::ContainsFullscreenWindow() const { + for (aura::Window::Windows::const_iterator i = windows_.begin(); + i != windows_.end(); + ++i) { + aura::Window* w = *i; + if (w->IsVisible() && + w->GetIntProperty(aura::kShowStateKey) == ui::SHOW_STATE_FULLSCREEN) + return true; + } + return false; +} + int Workspace::GetIndexOf(aura::Window* window) const { aura::Window::Windows::const_iterator i = std::find(windows_.begin(), windows_.end(), window); @@ -208,24 +241,17 @@ void Workspace::MoveWindowTo( aura::Window* window, const gfx::Point& origin, bool animate) { - if (window->show_state() == ui::SHOW_STATE_FULLSCREEN) - window->Fullscreen(); - else if (window->show_state() == ui::SHOW_STATE_MAXIMIZED) - window->Maximize(); - else { - gfx::Rect bounds = window->GetTargetBounds(); - gfx::Rect work_area = GetWorkAreaBounds(); - // Make sure the window isn't bigger than the workspace size. - bounds.SetRect(origin.x(), origin.y(), - std::min(work_area.width(), bounds.width()), - std::min(work_area.height(), bounds.height())); - if (animate) { - ui::LayerAnimator::ScopedSettings settings( - window->layer()->GetAnimator()); - window->SetBounds(bounds); - } else { - window->SetBounds(bounds); - } + gfx::Rect bounds = GetLayoutBounds(window); + gfx::Rect work_area = GetWorkAreaBounds(); + // Make sure the window isn't bigger than the workspace size. + bounds.SetRect(origin.x(), origin.y(), + std::min(work_area.width(), bounds.width()), + std::min(work_area.height(), bounds.height())); + if (animate) { + ui::LayerAnimator::ScopedSettings settings(window->layer()->GetAnimator()); + window->SetBounds(bounds); + } else { + window->SetBounds(bounds); } } @@ -236,8 +262,7 @@ int Workspace::GetTotalWindowsWidth() const { ++i) { if (total_width) total_width += kWindowHorizontalMargin; - // TODO(oshima): use restored bounds. - total_width += (*i)->bounds().width(); + total_width += GetLayoutWidth(*i); } return total_width; } diff --git a/ui/aura_shell/workspace/workspace.h b/ui/aura_shell/workspace/workspace.h index 027b393..8d454da 100644 --- a/ui/aura_shell/workspace/workspace.h +++ b/ui/aura_shell/workspace/workspace.h @@ -91,6 +91,9 @@ class AURA_SHELL_EXPORT Workspace { // windows except for the window specified by |no_animation| and |ignore|. void Layout(aura::Window* ignore, aura::Window* no_animation); + // Returns true if the workspace contains a fullscreen window. + bool ContainsFullscreenWindow() const; + private: FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, WorkspaceBasic); FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, RotateWindows); diff --git a/ui/aura_shell/workspace/workspace_manager_unittest.cc b/ui/aura_shell/workspace/workspace_manager_unittest.cc index 8038884..30f7237 100644 --- a/ui/aura_shell/workspace/workspace_manager_unittest.cc +++ b/ui/aura_shell/workspace/workspace_manager_unittest.cc @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/aura_shell/workspace/workspace.h" -#include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/aura/aura_constants.h" #include "ui/aura/desktop.h" #include "ui/aura/screen_aura.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_desktop_delegate.h" #include "ui/aura/window.h" +#include "ui/aura_shell/workspace/workspace.h" +#include "ui/aura_shell/workspace/workspace_manager.h" +#include "ui/base/ui_base_types.h" using aura::Window; @@ -202,7 +204,7 @@ TEST_F(WorkspaceManagerTest, FindRotateWindow) { ws1->AddWindowAfter(w12.get(), NULL); manager_->LayoutWorkspaces(); - // Workspaces are 0-empt-145-w11-245-margin-265-365-500. + // Workspaces are 0-<lmgn>-145-<w11>-245-<wmng>-255-<w12>-355-<rmgn>-500. EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(0, 0))); EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(100, 0))); EXPECT_EQ(w11.get(), @@ -211,9 +213,13 @@ TEST_F(WorkspaceManagerTest, FindRotateWindow) { manager_->FindRotateWindowForLocation(gfx::Point(300, 0))); EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(400, 0))); + + // The following test does not pass due to crbug.com/102413. + // TODO(oshima): Re-enable this once the bug is fixed. + /* w11->SetBounds(gfx::Rect(0, 0, 400, 100)); w12->SetBounds(gfx::Rect(0, 0, 200, 100)); - manager_->LayoutWorkspaces(); + manager_->FindBy(w11.get())->Layout(NULL, NULL); EXPECT_EQ(w11.get(), manager_->FindRotateWindowForLocation(gfx::Point(10, 0))); EXPECT_EQ(w11.get(), @@ -222,6 +228,7 @@ TEST_F(WorkspaceManagerTest, FindRotateWindow) { manager_->FindRotateWindowForLocation(gfx::Point(260, 0))); EXPECT_EQ(w12.get(), manager_->FindRotateWindowForLocation(gfx::Point(490, 0))); + */ Workspace* ws2 = manager_->CreateWorkspace(); scoped_ptr<Window> w21(CreateTestWindow()); @@ -500,5 +507,29 @@ TEST_F(WorkspaceTest, ShiftWindowsMultiple) { manager_.reset(); } +TEST_F(WorkspaceTest, ContainsFullscreenWindow) { + Workspace* ws = manager_->CreateWorkspace(); + scoped_ptr<Window> w1(CreateTestWindow()); + scoped_ptr<Window> w2(CreateTestWindow()); + ws->AddWindowAfter(w1.get(), NULL); + ws->AddWindowAfter(w2.get(), NULL); + w1->Show(); + w2->Show(); + + EXPECT_FALSE(ws->ContainsFullscreenWindow()); + + w1->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + EXPECT_TRUE(ws->ContainsFullscreenWindow()); + + w1->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_FALSE(ws->ContainsFullscreenWindow()); + + w2->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + EXPECT_TRUE(ws->ContainsFullscreenWindow()); + + w2->Hide(); + EXPECT_FALSE(ws->ContainsFullscreenWindow()); +} + } // namespace internal } // namespace aura_shell |