diff options
-rw-r--r-- | ash/ash.gyp | 3 | ||||
-rw-r--r-- | ash/root_window_controller.cc | 1 | ||||
-rw-r--r-- | ash/shell.cc | 1 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.cc | 284 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.h | 128 | ||||
-rw-r--r-- | ash/wm/base_layout_manager_unittest.cc | 313 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_layout_manager.cc | 158 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_layout_manager.h | 58 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_layout_manager_unittest.cc | 296 | ||||
-rw-r--r-- | ash/wm/workspace_controller.cc | 1 |
10 files changed, 493 insertions, 750 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index ffeb74b..9d45eb6 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -444,8 +444,6 @@ 'wm/ash_native_cursor_manager.h', 'wm/ash_focus_rules.cc', 'wm/ash_focus_rules.h', - 'wm/base_layout_manager.cc', - 'wm/base_layout_manager.h', 'wm/boot_splash_screen_chromeos.cc', 'wm/boot_splash_screen_chromeos.h', 'wm/caption_buttons/alternate_frame_size_button.cc', @@ -897,7 +895,6 @@ 'touch/touch_observer_hud_unittest.cc', 'wm/app_list_controller_unittest.cc', 'wm/ash_native_cursor_manager_unittest.cc', - 'wm/base_layout_manager_unittest.cc', 'wm/caption_buttons/alternate_frame_size_button_unittest.cc', 'wm/caption_buttons/frame_caption_button_container_view_unittest.cc', 'wm/caption_buttons/frame_maximize_button_unittest.cc', diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index cd24636..a3ec739 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc @@ -30,7 +30,6 @@ #include "ash/touch/touch_hud_projection.h" #include "ash/touch/touch_observer_hud.h" #include "ash/wm/always_on_top_controller.h" -#include "ash/wm/base_layout_manager.h" #include "ash/wm/dock/docked_window_layout_manager.h" #include "ash/wm/panels/panel_layout_manager.h" #include "ash/wm/panels/panel_window_event_handler.h" diff --git a/ash/shell.cc b/ash/shell.cc index 986612e..a01990e 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -54,7 +54,6 @@ #include "ash/wm/app_list_controller.h" #include "ash/wm/ash_focus_rules.h" #include "ash/wm/ash_native_cursor_manager.h" -#include "ash/wm/base_layout_manager.h" #include "ash/wm/coordinate_conversion.h" #include "ash/wm/custom_frame_view_ash.h" #include "ash/wm/event_client_impl.h" diff --git a/ash/wm/base_layout_manager.cc b/ash/wm/base_layout_manager.cc deleted file mode 100644 index 18c8ee8..0000000 --- a/ash/wm/base_layout_manager.cc +++ /dev/null @@ -1,284 +0,0 @@ -// 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/screen_util.h" -#include "ash/session_state_delegate.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/corewm_switches.h" -#include "ui/views/corewm/window_util.h" - -namespace ash { -namespace internal { - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, public: - -BaseLayoutManager::BaseLayoutManager(aura::Window* root_window) - : root_window_(root_window) { - Shell::GetInstance()->activation_client()->AddObserver(this); - Shell::GetInstance()->AddShellObserver(this); - root_window_->AddObserver(this); -} - -BaseLayoutManager::~BaseLayoutManager() { - if (root_window_) - root_window_->RemoveObserver(this); - for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) - (*i)->RemoveObserver(this); - Shell::GetInstance()->RemoveShellObserver(this); - Shell::GetInstance()->activation_client()->RemoveObserver(this); -} - -// static -gfx::Rect BaseLayoutManager::BoundsWithScreenEdgeVisible( - aura::Window* window, - const gfx::Rect& restore_bounds) { - gfx::Rect max_bounds = - ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window); - // If the restore_bounds are more than 1 grid step away from the size the - // window would be when maximized, inset it. - max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset, - ash::internal::WorkspaceWindowResizer::kScreenEdgeInset); - if (restore_bounds.Contains(max_bounds)) - return max_bounds; - return restore_bounds; -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::LayoutManager overrides: - -void BaseLayoutManager::OnWindowResized() { -} - -void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - windows_.insert(child); - child->AddObserver(this); - wm::WindowState* window_state = wm::GetWindowState(child); - window_state->AddObserver(this); - - // Only update the bounds if the window has a show state that depends on the - // workspace area. - if (window_state->IsMaximizedOrFullscreen()) - UpdateBoundsFromShowType(window_state); -} - -void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { - windows_.erase(child); - child->RemoveObserver(this); - wm::GetWindowState(child)->RemoveObserver(this); -} - -void BaseLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { -} - -void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) { - wm::WindowState* window_state = wm::GetWindowState(child); - // Attempting to show a minimized window. Unminimize it. - if (visible && window_state->IsMinimized()) - window_state->Unminimize(); -} - -void BaseLayoutManager::SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) { - gfx::Rect child_bounds(requested_bounds); - wm::WindowState* window_state = wm::GetWindowState(child); - // Some windows rely on this to set their initial bounds. - if (window_state->IsMaximized()) - child_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent(child); - else if (window_state->IsFullscreen()) - child_bounds = ScreenUtil::GetDisplayBoundsInParent(child); - SetChildBoundsDirect(child, child_bounds); -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::WindowObserver overrides: - -void BaseLayoutManager::OnWindowDestroying(aura::Window* window) { - if (root_window_ == window) { - root_window_->RemoveObserver(this); - root_window_ = NULL; - } -} - -void BaseLayoutManager::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (root_window_ == window) - AdjustAllWindowsBoundsForWorkAreaChange(ADJUST_WINDOW_DISPLAY_SIZE_CHANGED); -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::client::ActivationChangeObserver implementation: - -void BaseLayoutManager::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - wm::WindowState* window_state = wm::GetWindowState(gained_active); - if (window_state && window_state->IsMinimized() && - !gained_active->IsVisible()) { - window_state->Unminimize(); - DCHECK(!window_state->IsMinimized()); - } -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, ash::ShellObserver overrides: - -void BaseLayoutManager::OnDisplayWorkAreaInsetsChanged() { - AdjustAllWindowsBoundsForWorkAreaChange( - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, ash::wm::WindowStateObserver overrides: - -void BaseLayoutManager::OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) { - if (old_type != wm::SHOW_TYPE_MINIMIZED && - !window_state->HasRestoreBounds() && - window_state->IsMaximizedOrFullscreen() && - !wm::IsMaximizedOrFullscreenWindowShowType(old_type)) { - window_state->SetRestoreBoundsInParent(window_state->window()->bounds()); - } - - UpdateBoundsFromShowType(window_state); - ShowTypeChanged(window_state, old_type); -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, protected: - -void BaseLayoutManager::ShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType last_show_type) { - if (window_state->IsMinimized()) { - if (last_show_type == wm::SHOW_TYPE_MINIMIZED) - return; - - // Save the previous show state so that we can correctly restore it. - window_state->window()->SetProperty(aura::client::kRestoreShowStateKey, - wm::ToWindowShowState(last_show_type)); - views::corewm::SetWindowVisibilityAnimationType( - window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); - - // Hide the window. - window_state->window()->Hide(); - // Activate another window. - if (window_state->IsActive()) - window_state->Deactivate(); - } else if ((window_state->window()->TargetVisibility() || - last_show_type == wm::SHOW_TYPE_MINIMIZED) && - !window_state->window()->layer()->visible()) { - // The layer may be hidden if the window was previously minimized. Make - // sure it's visible. - window_state->window()->Show(); - if (last_show_type == wm::SHOW_TYPE_MINIMIZED) - window_state->set_unminimize_to_restore_bounds(false); - } -} - -void BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) { - // Don't do any adjustments of the insets while we are in screen locked mode. - // This would happen if the launcher was auto hidden before the login screen - // was shown and then gets shown when the login screen gets presented. - if (reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED && - Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) - return; - - // If a user plugs an external display into a laptop running Aura the - // display 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. - // We also need to do this when the work area insets changes. - for (WindowSet::const_iterator it = windows_.begin(); - it != windows_.end(); - ++it) { - AdjustWindowBoundsForWorkAreaChange(wm::GetWindowState(*it), reason); - } -} - -void BaseLayoutManager::AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) { - aura::Window* window = window_state->window(); - if (window_state->IsMaximized()) { - SetChildBoundsDirect( - window, ScreenUtil::GetMaximizedWindowBoundsInParent(window)); - } else if (window_state->IsFullscreen()) { - SetChildBoundsDirect( - window, ScreenUtil::GetDisplayBoundsInParent(window)); - } else { - // The work area may be smaller than the full screen. - gfx::Rect display_rect = - ScreenUtil::GetDisplayWorkAreaBoundsInParent(window); - // Put as much of the window as possible within the display area. - gfx::Rect bounds = window->bounds(); - bounds.AdjustToFit(display_rect); - window->SetBounds(bounds); - } -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, private: - -void BaseLayoutManager::UpdateBoundsFromShowType( - wm::WindowState* window_state) { - aura::Window* window = window_state->window(); - switch (window_state->window_show_type()) { - case wm::SHOW_TYPE_DEFAULT: - case wm::SHOW_TYPE_NORMAL: - if (window_state->HasRestoreBounds()) { - gfx::Rect bounds_in_parent = window_state->GetRestoreBoundsInParent(); - SetChildBoundsDirect(window, - BoundsWithScreenEdgeVisible(window, - bounds_in_parent)); - } - window_state->ClearRestoreBounds(); - break; - - case wm::SHOW_TYPE_LEFT_SNAPPED: - case wm::SHOW_TYPE_RIGHT_SNAPPED: - if (window_state->HasRestoreBounds()) - SetChildBoundsDirect(window, window_state->GetRestoreBoundsInParent()); - window_state->ClearRestoreBounds(); - break; - - case wm::SHOW_TYPE_MAXIMIZED: - SetChildBoundsDirect( - window, ScreenUtil::GetMaximizedWindowBoundsInParent(window)); - break; - - case wm::SHOW_TYPE_FULLSCREEN: - // Don't animate the full-screen window transition. - // TODO(jamescook): Use animation here. Be sure the lock screen works. - SetChildBoundsDirect(window, - ScreenUtil::GetDisplayBoundsInParent(window)); - break; - - case wm::SHOW_TYPE_MINIMIZED: - case wm::SHOW_TYPE_INACTIVE: - case wm::SHOW_TYPE_DETACHED: - case wm::SHOW_TYPE_END: - case wm::SHOW_TYPE_AUTO_POSITIONED: - break; - } -} - -} // namespace internal -} // namespace ash diff --git a/ash/wm/base_layout_manager.h b/ash/wm/base_layout_manager.h deleted file mode 100644 index 341915e..0000000 --- a/ash/wm/base_layout_manager.h +++ /dev/null @@ -1,128 +0,0 @@ -// 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_ - -#include <set> - -#include "ash/ash_export.h" -#include "ash/shell_observer.h" -#include "ash/wm/window_state_observer.h" -#include "ash/wm/wm_types.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace wm { -class WindowState; -} - -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::WindowObserver, - public aura::client::ActivationChangeObserver, - public ShellObserver, - public wm::WindowStateObserver { - public: - typedef std::set<aura::Window*> WindowSet; - - explicit BaseLayoutManager(aura::Window* root_window); - virtual ~BaseLayoutManager(); - - const WindowSet& windows() const { return windows_; } - - // Given a |window| and tentative |restore_bounds|, returns new bounds that - // ensure that at least a few pixels of the screen background are visible - // outside the edges of the window. - static gfx::Rect BoundsWithScreenEdgeVisible(aura::Window* window, - const gfx::Rect& restore_bounds); - - // aura::LayoutManager overrides: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // aura::WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - // aura::client::ActivationChangeObserver overrides: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - // ash::ShellObserver overrides: - virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE; - - // wm::WindowStateObserver overrides: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType type) OVERRIDE; - - protected: - enum AdjustWindowReason { - ADJUST_WINDOW_DISPLAY_SIZE_CHANGED, - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED, - }; - - // Invoked from OnWindowShowTypeChanged(). - virtual void ShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType last_show_type); - - // Adjusts the window's bounds when the display area changes for given - // window. This happens when the display size, work area insets or - // the display on which the window exists has changed. - // If this is called for a display size change (i.e. |reason| - // is ADJUST_WINDOW_DISPLAY_SIZE_CHANGED), the non-maximized/non-fullscreen - // windows are readjusted to make sure the window is completely within the - // display region. Otherwise, it makes sure at least some parts of the window - // is on display. - virtual void AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason); - - // Adjusts the sizes of the specific window in respond to a screen change or - // display-area size change. - virtual void AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason); - - aura::Window* root_window() { return root_window_; } - - private: - // Update window bounds based on a change in show type. - void UpdateBoundsFromShowType(wm::WindowState* controller); - - // Set of windows we're listening to. - WindowSet windows_; - - aura::Window* root_window_; - - DISALLOW_COPY_AND_ASSIGN(BaseLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#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 deleted file mode 100644 index b869648..0000000 --- a/ash/wm/base_layout_manager_unittest.cc +++ /dev/null @@ -1,313 +0,0 @@ -// 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/screen_util.h" -#include "ash/session_state_delegate.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.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/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -class BaseLayoutManagerTest : public test::AshTestBase { - public: - BaseLayoutManagerTest() {} - virtual ~BaseLayoutManagerTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - UpdateDisplay("800x600"); - aura::Window* default_container = Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_DefaultContainer); - default_container->SetLayoutManager(new internal::BaseLayoutManager( - Shell::GetPrimaryRootWindow())); - } - - aura::Window* CreateTestWindow(const gfx::Rect& bounds) { - return CreateTestWindowInShellWithBounds(bounds); - } - - private: - DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest); -}; - -// Tests normal->maximize->normal. -TEST_F(BaseLayoutManagerTest, Maximize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - // Maximized window fills the work area, not the whole display. - EXPECT_EQ( - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Tests normal->minimize->normal. -TEST_F(BaseLayoutManagerTest, Minimize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - // Note: Currently minimize doesn't do anything except set the state. - // See crbug.com/104571. - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// A WindowDelegate which sets the focus when the window -// becomes visible. -class FocusDelegate : public aura::test::TestWindowDelegate { - public: - FocusDelegate() - : window_(NULL), - show_state_(ui::SHOW_STATE_END) { - } - virtual ~FocusDelegate() {} - - void set_window(aura::Window* window) { window_ = window; } - - // aura::test::TestWindowDelegate overrides: - virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { - if (window_) { - if (visible) - window_->Focus(); - show_state_ = window_->GetProperty(aura::client::kShowStateKey); - } - } - - ui::WindowShowState GetShowStateAndReset() { - ui::WindowShowState ret = show_state_; - show_state_ = ui::SHOW_STATE_END; - return ret; - } - - private: - aura::Window* window_; - ui::WindowShowState show_state_; - - DISALLOW_COPY_AND_ASSIGN(FocusDelegate); -}; - -// Make sure that the window's show state is correct in -// |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting -// focus in this callback doesn't cause DCHECK error. See -// crbug.com/168383. -TEST_F(BaseLayoutManagerTest, FocusDuringUnminimize) { - FocusDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - &delegate, 0, gfx::Rect(100, 100, 100, 100))); - delegate.set_window(window.get()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_FALSE(window->IsVisible()); - EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset()); - window->Show(); - EXPECT_TRUE(window->IsVisible()); - EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset()); -} - -// 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->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - gfx::Rect initial_work_area_bounds = - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()); - EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString()); - // Enlarge the root window. We should still match the work area size. - UpdateDisplay("900x700"); - EXPECT_EQ( - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window->bounds().ToString()); - EXPECT_NE( - initial_work_area_bounds.ToString(), - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString()); -} - -// Tests normal->fullscreen->normal. -TEST_F(BaseLayoutManagerTest, Fullscreen) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - // Fullscreen window fills the whole display. - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// 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 display. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); - // Enlarge the root window. We should still match the display size. - UpdateDisplay("800x600"); - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); -} - -// 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 = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - // 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. - UpdateDisplay("300x400"); - work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - EXPECT_LE(window->bounds().width(), work_area.width()); - EXPECT_LE(window->bounds().height(), work_area.height()); - - // Make the root window shorter than our window. - UpdateDisplay("300x200"); - work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - 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(); - UpdateDisplay("800x600"); - EXPECT_EQ(old_bounds.width(), window->bounds().width()); - EXPECT_EQ(old_bounds.height(), window->bounds().height()); -} - -// Tests that a maximized window with too-large restore bounds will be restored -// to smaller than the full work area. -TEST_F(BaseLayoutManagerTest, BoundsWithScreenEdgeVisible) { - // Create a window with bounds that fill the screen. - gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - // Maximize it, which writes the old bounds to restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - // Restore it. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - // It should have the default maximized window bounds, inset by the grid size. - int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset; - gfx::Rect max_bounds = - ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()); - max_bounds.Inset(grid_size, grid_size); - EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString()); -} - -// Verifies maximizing sets the restore bounds, and restoring -// restores the bounds. -TEST_F(BaseLayoutManagerTest, MaximizeSetsRestoreBounds) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Maximize it, which will keep the previous restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ("1,2 3x4", window_state->GetRestoreBoundsInParent().ToString()); - - // Restore it, which should restore bounds and reset restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ("1,2 3x4", window->bounds().ToString()); - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Verifies maximizing keeps the restore bounds if set. -TEST_F(BaseLayoutManagerTest, MaximizeResetsRestoreBounds) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13)); - - // Maximize it, which will keep the previous restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString()); -} - -// Verifies that the restore bounds do not get reset when restoring to a -// maximzied state from a minimized state. -TEST_F(BaseLayoutManagerTest, BoundsAfterRestoringToMaximizeFromMinimize) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - gfx::Rect bounds(10, 15, 25, 35); - window->SetBounds(bounds); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Maximize it, which should reset restore bounds. - window_state->Maximize(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - - // Minimize the window. The restore bounds should not change. - window_state->Minimize(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - - // Show the window again. The window should be maximized, and the restore - // bounds should not change. - window->Show(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - EXPECT_TRUE(window_state->IsMaximized()); - - window_state->Restore(); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Verify if the window is not resized during screen lock. See: crbug.com/173127 -TEST_F(BaseLayoutManagerTest, NotResizeWhenScreenIsLocked) { - SetCanLockScreen(true); - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - // window with AlwaysOnTop will be managed by BaseLayoutManager. - window->SetProperty(aura::client::kAlwaysOnTopKey, true); - window->Show(); - - internal::ShelfLayoutManager* shelf = - internal::ShelfLayoutManager::ForShelf(window.get()); - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - - window->SetBounds(ScreenUtil::GetMaximizedWindowBoundsInParent(window.get())); - gfx::Rect window_bounds = window->bounds(); - EXPECT_EQ( - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window_bounds.ToString()); - - Shell::GetInstance()->session_state_delegate()->LockScreen(); - shelf->UpdateVisibilityState(); - EXPECT_NE( - ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window_bounds.ToString()); - - Shell::GetInstance()->session_state_delegate()->UnlockScreen(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString()); -} - -} // namespace -} // namespace ash diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc index 031534a..4e79c6e 100644 --- a/ash/wm/workspace/workspace_layout_manager.cc +++ b/ash/wm/workspace/workspace_layout_manager.cc @@ -7,21 +7,25 @@ #include "ash/display/display_controller.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" +#include "ash/session_state_delegate.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/wm/always_on_top_controller.h" -#include "ash/wm/base_layout_manager.h" #include "ash/wm/window_animations.h" #include "ash/wm/window_positioner.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" +#include "ash/wm/workspace/workspace_window_resizer.h" +#include "ui/aura/client/activation_client.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" #include "ui/base/ui_base_types.h" +#include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/events/event.h" +#include "ui/gfx/screen.h" #include "ui/views/corewm/window_util.h" using aura::Window; @@ -65,49 +69,96 @@ void MoveToDisplayForRestore(wm::WindowState* window_state) { } } +gfx::Rect BoundsWithScreenEdgeVisible( + aura::Window* window, + const gfx::Rect& restore_bounds) { + gfx::Rect max_bounds = + ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window); + // If the restore_bounds are more than 1 grid step away from the size the + // window would be when maximized, inset it. + max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset, + ash::internal::WorkspaceWindowResizer::kScreenEdgeInset); + if (restore_bounds.Contains(max_bounds)) + return max_bounds; + return restore_bounds; +} + } // namespace WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window) - : BaseLayoutManager(window->GetRootWindow()), - shelf_(NULL), + : shelf_(NULL), window_(window), + root_window_(window->GetRootWindow()), work_area_in_parent_(ScreenUtil::ConvertRectFromScreen( window_, Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area())), is_fullscreen_(GetRootWindowController( window->GetRootWindow())->GetWindowForFullscreenMode() != NULL) { + Shell::GetInstance()->activation_client()->AddObserver(this); + Shell::GetInstance()->AddShellObserver(this); + root_window_->AddObserver(this); } WorkspaceLayoutManager::~WorkspaceLayoutManager() { + if (root_window_) + root_window_->RemoveObserver(this); + for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) + (*i)->RemoveObserver(this); + Shell::GetInstance()->RemoveShellObserver(this); + Shell::GetInstance()->activation_client()->RemoveObserver(this); } void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) { shelf_ = shelf; } +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, aura::LayoutManager implementation: + void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) { AdjustWindowBoundsWhenAdded(wm::GetWindowState(child)); - BaseLayoutManager::OnWindowAddedToLayout(child); + + windows_.insert(child); + child->AddObserver(this); + wm::WindowState* window_state = wm::GetWindowState(child); + window_state->AddObserver(this); + + // Only update the bounds if the window has a show state that depends on the + // workspace area. + if (window_state->IsMaximized()) { + SetChildBoundsDirect( + child, ScreenUtil::GetMaximizedWindowBoundsInParent(child)); + } else if (window_state->IsFullscreen()) { + SetChildBoundsDirect( + child, ScreenUtil::GetDisplayBoundsInParent(child)); + } + UpdateShelfVisibility(); UpdateFullscreenState(); WindowPositioner::RearrangeVisibleWindowOnShow(child); } void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(Window* child) { - BaseLayoutManager::OnWillRemoveWindowFromLayout(child); + windows_.erase(child); + child->RemoveObserver(this); + wm::GetWindowState(child)->RemoveObserver(this); + if (child->TargetVisibility()) WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); } void WorkspaceLayoutManager::OnWindowRemovedFromLayout(Window* child) { - BaseLayoutManager::OnWindowRemovedFromLayout(child); UpdateShelfVisibility(); UpdateFullscreenState(); } void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child, bool visible) { - BaseLayoutManager::OnChildWindowVisibilityChanged(child, visible); + wm::WindowState* window_state = wm::GetWindowState(child); + // Attempting to show a minimized window. Unminimize it. + if (visible && window_state->IsMinimized()) + window_state->Unminimize(); + if (child->TargetVisibility()) { WindowPositioner::RearrangeVisibleWindowOnShow(child); } else { @@ -139,6 +190,9 @@ void WorkspaceLayoutManager::SetChildBounds( UpdateShelfVisibility(); } +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, ash::ShellObserver implementation: + void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { const gfx::Rect work_area(ScreenUtil::ConvertRectFromScreen( window_, @@ -149,6 +203,9 @@ void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { } } +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, aura::WindowObserver implementation: + void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window, const void* key, intptr_t old) { @@ -160,11 +217,41 @@ void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window, } void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) { - BaseLayoutManager::OnWindowStackingChanged(window); UpdateShelfVisibility(); UpdateFullscreenState(); } +void WorkspaceLayoutManager::OnWindowDestroying(aura::Window* window) { + if (root_window_ == window) { + root_window_->RemoveObserver(this); + root_window_ = NULL; + } +} + +void WorkspaceLayoutManager::OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + if (root_window_ == window) + AdjustAllWindowsBoundsForWorkAreaChange(ADJUST_WINDOW_DISPLAY_SIZE_CHANGED); +} + +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, +// aura::client::ActivationChangeObserver implementation: + +void WorkspaceLayoutManager::OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) { + wm::WindowState* window_state = wm::GetWindowState(gained_active); + if (window_state && window_state->IsMinimized() && + !gained_active->IsVisible()) { + window_state->Unminimize(); + DCHECK(!window_state->IsMinimized()); + } +} + +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, wm::WindowStateObserver implementation: + void WorkspaceLayoutManager::OnWindowShowTypeChanged( wm::WindowState* window_state, wm::WindowShowType old_type) { @@ -204,12 +291,63 @@ void WorkspaceLayoutManager::OnWindowShowTypeChanged( UpdateShelfVisibility(); } +void WorkspaceLayoutManager::ShowTypeChanged( + wm::WindowState* window_state, + wm::WindowShowType last_show_type) { + if (window_state->IsMinimized()) { + if (last_show_type == wm::SHOW_TYPE_MINIMIZED) + return; + + // Save the previous show state so that we can correctly restore it. + window_state->window()->SetProperty(aura::client::kRestoreShowStateKey, + wm::ToWindowShowState(last_show_type)); + views::corewm::SetWindowVisibilityAnimationType( + window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); + + // Hide the window. + window_state->window()->Hide(); + // Activate another window. + if (window_state->IsActive()) + window_state->Deactivate(); + } else if ((window_state->window()->TargetVisibility() || + last_show_type == wm::SHOW_TYPE_MINIMIZED) && + !window_state->window()->layer()->visible()) { + // The layer may be hidden if the window was previously minimized. Make + // sure it's visible. + window_state->window()->Show(); + if (last_show_type == wm::SHOW_TYPE_MINIMIZED && + !window_state->IsMaximizedOrFullscreen()) { + window_state->set_unminimize_to_restore_bounds(false); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// WorkspaceLayoutManager, private: + void WorkspaceLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( AdjustWindowReason reason) { work_area_in_parent_ = ScreenUtil::ConvertRectFromScreen( window_, Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area()); - BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(reason); + + // Don't do any adjustments of the insets while we are in screen locked mode. + // This would happen if the launcher was auto hidden before the login screen + // was shown and then gets shown when the login screen gets presented. + if (reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED && + Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) + return; + + // If a user plugs an external display into a laptop running Aura the + // display 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. + // We also need to do this when the work area insets changes. + for (WindowSet::const_iterator it = windows_.begin(); + it != windows_.end(); + ++it) { + AdjustWindowBoundsForWorkAreaChange(wm::GetWindowState(*it), reason); + } } void WorkspaceLayoutManager::AdjustWindowBoundsForWorkAreaChange( @@ -322,7 +460,7 @@ void WorkspaceLayoutManager::UpdateBoundsFromShowType( show_type == wm::SHOW_TYPE_RIGHT_SNAPPED) { AdjustSnappedBounds(window_state, &bounds_in_parent); } else { - bounds_in_parent = BaseLayoutManager::BoundsWithScreenEdgeVisible( + bounds_in_parent = BoundsWithScreenEdgeVisible( window, bounds_in_parent); } diff --git a/ash/wm/workspace/workspace_layout_manager.h b/ash/wm/workspace/workspace_layout_manager.h index 906a04a..8cd44cc 100644 --- a/ash/wm/workspace/workspace_layout_manager.h +++ b/ash/wm/workspace/workspace_layout_manager.h @@ -7,11 +7,14 @@ #include <set> +#include "ash/ash_export.h" #include "ash/shell_observer.h" -#include "ash/wm/base_layout_manager.h" +#include "ash/wm/window_state_observer.h" #include "ash/wm/wm_types.h" #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "ui/aura/client/activation_change_observer.h" +#include "ui/aura/layout_manager.h" #include "ui/aura/window_observer.h" #include "ui/gfx/rect.h" @@ -25,13 +28,21 @@ class Layer; } namespace ash { +namespace wm { +class WindowState; +} namespace internal { class ShelfLayoutManager; // LayoutManager used on the window created for a workspace. -class ASH_EXPORT WorkspaceLayoutManager : public BaseLayoutManager { +class ASH_EXPORT WorkspaceLayoutManager + : public aura::LayoutManager, + public aura::WindowObserver, + public aura::client::ActivationChangeObserver, + public ShellObserver, + public wm::WindowStateObserver { public: explicit WorkspaceLayoutManager(aura::Window* window); virtual ~WorkspaceLayoutManager(); @@ -56,18 +67,45 @@ class ASH_EXPORT WorkspaceLayoutManager : public BaseLayoutManager { const void* key, intptr_t old) OVERRIDE; virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE; + virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; + virtual void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) OVERRIDE; + + // aura::client::ActivationChangeObserver overrides: + virtual void OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) OVERRIDE; // WindowStateObserver overrides: virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, wm::WindowShowType old_type) OVERRIDE; private: - // Overridden from BaseLayoutManager: - virtual void AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) OVERRIDE; - virtual void AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) OVERRIDE; + typedef std::set<aura::Window*> WindowSet; + + enum AdjustWindowReason { + ADJUST_WINDOW_DISPLAY_SIZE_CHANGED, + ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED, + }; + + // Invoked from OnWindowShowTypeChanged(). + void ShowTypeChanged(wm::WindowState* window_state, + wm::WindowShowType last_show_type); + + // Adjusts the window's bounds when the display area changes for given + // window. This happens when the display size, work area insets or + // the display on which the window exists has changed. + // If this is called for a display size change (i.e. |reason| + // is ADJUST_WINDOW_DISPLAY_SIZE_CHANGED), the non-maximized/non-fullscreen + // windows are readjusted to make sure the window is completely within the + // display region. Otherwise, it makes sure at least some parts of the window + // is on display. + void AdjustAllWindowsBoundsForWorkAreaChange(AdjustWindowReason reason); + + // Adjusts the sizes of the specific window in respond to a screen change or + // display-area size change. + void AdjustWindowBoundsForWorkAreaChange(wm::WindowState* window_state, + AdjustWindowReason reason); void AdjustWindowBoundsWhenAdded(wm::WindowState* window_state); @@ -96,6 +134,10 @@ class ASH_EXPORT WorkspaceLayoutManager : public BaseLayoutManager { internal::ShelfLayoutManager* shelf_; aura::Window* window_; + aura::Window* root_window_; + + // Set of windows we're listening to. + WindowSet windows_; // The work area in the coordinates of |window_|. gfx::Rect work_area_in_parent_; diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index 41e067f..8baf51c 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc @@ -8,18 +8,24 @@ #include "ash/display/display_manager.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" +#include "ash/session_state_delegate.h" #include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_observer.h" +#include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" +#include "ash/wm/workspace/workspace_window_resizer.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/test/test_windows.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/insets.h" +#include "ui/gfx/screen.h" #include "ui/views/corewm/window_util.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -479,4 +485,292 @@ TEST_F(WorkspaceLayoutManagerTest, NotifyFullscreenChanges) { EXPECT_FALSE(observer.is_fullscreen()); } +// Following tests were originally written for BaseLayoutManager. + +namespace { + +class WorkspaceLayoutManagerSoloTest : public test::AshTestBase { + public: + WorkspaceLayoutManagerSoloTest() {} + virtual ~WorkspaceLayoutManagerSoloTest() {} + + virtual void SetUp() OVERRIDE { + test::AshTestBase::SetUp(); + UpdateDisplay("800x600"); + aura::Window* default_container = Shell::GetContainer( + Shell::GetPrimaryRootWindow(), + internal::kShellWindowId_DefaultContainer); + default_container->SetLayoutManager(new internal::WorkspaceLayoutManager( + Shell::GetPrimaryRootWindow())); + } + + aura::Window* CreateTestWindow(const gfx::Rect& bounds) { + return CreateTestWindowInShellWithBounds(bounds); + } + + private: + DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerSoloTest); +}; + +} // namespace + +// Tests normal->maximize->normal. +TEST_F(WorkspaceLayoutManagerSoloTest, Maximize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + // Maximized window fills the work area, not the whole display. + EXPECT_EQ( + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), + window->bounds().ToString()); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); +} + +// Tests normal->minimize->normal. +TEST_F(WorkspaceLayoutManagerSoloTest, Minimize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); + // Note: Currently minimize doesn't do anything except set the state. + // See crbug.com/104571. + EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); +} + +// A WindowDelegate which sets the focus when the window +// becomes visible. +class FocusDelegate : public aura::test::TestWindowDelegate { + public: + FocusDelegate() + : window_(NULL), + show_state_(ui::SHOW_STATE_END) { + } + virtual ~FocusDelegate() {} + + void set_window(aura::Window* window) { window_ = window; } + + // aura::test::TestWindowDelegate overrides: + virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { + if (window_) { + if (visible) + window_->Focus(); + show_state_ = window_->GetProperty(aura::client::kShowStateKey); + } + } + + ui::WindowShowState GetShowStateAndReset() { + ui::WindowShowState ret = show_state_; + show_state_ = ui::SHOW_STATE_END; + return ret; + } + + private: + aura::Window* window_; + ui::WindowShowState show_state_; + + DISALLOW_COPY_AND_ASSIGN(FocusDelegate); +}; + +// Make sure that the window's show state is correct in +// |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting +// focus in this callback doesn't cause DCHECK error. See +// crbug.com/168383. +TEST_F(WorkspaceLayoutManagerSoloTest, FocusDuringUnminimize) { + FocusDelegate delegate; + scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( + &delegate, 0, gfx::Rect(100, 100, 100, 100))); + delegate.set_window(window.get()); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); + EXPECT_FALSE(window->IsVisible()); + EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset()); + window->Show(); + EXPECT_TRUE(window->IsVisible()); + EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset()); +} + +// Tests maximized window size during root window resize. +TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeRootWindowResize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + gfx::Rect initial_work_area_bounds = + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()); + EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString()); + // Enlarge the root window. We should still match the work area size. + UpdateDisplay("900x700"); + EXPECT_EQ( + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), + window->bounds().ToString()); + EXPECT_NE( + initial_work_area_bounds.ToString(), + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString()); +} + +// Tests normal->fullscreen->normal. +TEST_F(WorkspaceLayoutManagerSoloTest, Fullscreen) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + // Fullscreen window fills the whole display. + EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).bounds().ToString(), + window->bounds().ToString()); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); +} + +// Tests fullscreen window size during root window resize. +TEST_F(WorkspaceLayoutManagerSoloTest, FullscreenRootWindowResize) { + gfx::Rect bounds(100, 100, 200, 200); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + // Fullscreen window fills the whole display. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).bounds().ToString(), + window->bounds().ToString()); + // Enlarge the root window. We should still match the display size. + UpdateDisplay("800x600"); + EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).bounds().ToString(), + window->bounds().ToString()); +} + +// Tests that when the screen gets smaller the windows aren't bigger than +// the screen. +TEST_F(WorkspaceLayoutManagerSoloTest, RootWindowResizeShrinksWindows) { + scoped_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(10, 20, 500, 400))); + gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).work_area(); + // 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. + UpdateDisplay("300x400"); + work_area = Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).work_area(); + EXPECT_LE(window->bounds().width(), work_area.width()); + EXPECT_LE(window->bounds().height(), work_area.height()); + + // Make the root window shorter than our window. + UpdateDisplay("300x200"); + work_area = Shell::GetScreen()->GetDisplayNearestWindow( + window.get()).work_area(); + 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(); + UpdateDisplay("800x600"); + EXPECT_EQ(old_bounds.width(), window->bounds().width()); + EXPECT_EQ(old_bounds.height(), window->bounds().height()); +} + +// Tests that a maximized window with too-large restore bounds will be restored +// to smaller than the full work area. +TEST_F(WorkspaceLayoutManagerSoloTest, BoundsWithScreenEdgeVisible) { + // Create a window with bounds that fill the screen. + gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); + scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); + // Maximize it, which writes the old bounds to restore bounds. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + // Restore it. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + // It should have the default maximized window bounds, inset by the grid size. + int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset; + gfx::Rect max_bounds = + ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()); + max_bounds.Inset(grid_size, grid_size); + EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString()); +} + +// Verifies maximizing sets the restore bounds, and restoring +// restores the bounds. +TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeSetsRestoreBounds) { + scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(10, 20, 30, 40))); + wm::WindowState* window_state = wm::GetWindowState(window.get()); + + // Maximize it, which will keep the previous restore bounds. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + EXPECT_EQ("10,20 30x40", window_state->GetRestoreBoundsInParent().ToString()); + + // Restore it, which should restore bounds and reset restore bounds. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + EXPECT_EQ("10,20 30x40", window->bounds().ToString()); + EXPECT_FALSE(window_state->HasRestoreBounds()); +} + +// Verifies maximizing keeps the restore bounds if set. +TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeResetsRestoreBounds) { + scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); + + wm::WindowState* window_state = wm::GetWindowState(window.get()); + window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13)); + + // Maximize it, which will keep the previous restore bounds. + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString()); +} + +// Verifies that the restore bounds do not get reset when restoring to a +// maximzied state from a minimized state. +TEST_F(WorkspaceLayoutManagerSoloTest, + BoundsAfterRestoringToMaximizeFromMinimize) { + scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); + gfx::Rect bounds(10, 15, 25, 35); + window->SetBounds(bounds); + + wm::WindowState* window_state = wm::GetWindowState(window.get()); + // Maximize it, which should reset restore bounds. + window_state->Maximize(); + EXPECT_EQ(bounds.ToString(), + window_state->GetRestoreBoundsInParent().ToString()); + // Minimize the window. The restore bounds should not change. + window_state->Minimize(); + EXPECT_EQ(bounds.ToString(), + window_state->GetRestoreBoundsInParent().ToString()); + + // Show the window again. The window should be maximized, and the restore + // bounds should not change. + window->Show(); + EXPECT_EQ(bounds.ToString(), + window_state->GetRestoreBoundsInParent().ToString()); + EXPECT_TRUE(window_state->IsMaximized()); + + window_state->Restore(); + EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); +} + +// Verify if the window is not resized during screen lock. See: crbug.com/173127 +TEST_F(WorkspaceLayoutManagerSoloTest, NotResizeWhenScreenIsLocked) { + SetCanLockScreen(true); + scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); + // window with AlwaysOnTop will be managed by BaseLayoutManager. + window->SetProperty(aura::client::kAlwaysOnTopKey, true); + window->Show(); + + internal::ShelfLayoutManager* shelf = + internal::ShelfLayoutManager::ForShelf(window.get()); + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + + window->SetBounds(ScreenUtil::GetMaximizedWindowBoundsInParent(window.get())); + gfx::Rect window_bounds = window->bounds(); + EXPECT_EQ( + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), + window_bounds.ToString()); + + Shell::GetInstance()->session_state_delegate()->LockScreen(); + shelf->UpdateVisibilityState(); + EXPECT_NE( + ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(), + window_bounds.ToString()); + + Shell::GetInstance()->session_state_delegate()->UnlockScreen(); + shelf->UpdateVisibilityState(); + EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString()); +} + } // namespace ash diff --git a/ash/wm/workspace_controller.cc b/ash/wm/workspace_controller.cc index fa162e4..d869d13 100644 --- a/ash/wm/workspace_controller.cc +++ b/ash/wm/workspace_controller.cc @@ -8,7 +8,6 @@ #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" -#include "ash/wm/base_layout_manager.h" #include "ash/wm/window_animations.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" |