Commit 6344760a authored by skuhne@chromium.org's avatar skuhne@chromium.org

Adding a gray semi transparent backdrop behind the topmost window within the default container

This is part of the "always maximized" feature. Windows which cannot be maximized - or cannot be made to cover the entire screen should have a backdrop behind them which covers the desktop.

Tried various ways to implement this and this seems to be the best solution.

BUG=337567, 337563

Review URL: https://codereview.chromium.org/169643005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255863 0039d316-1c4b-4281-b951-d872f2087c98
parent 74e50c0c
......@@ -540,6 +540,8 @@
'wm/lock_state_observer.h',
'wm/maximize_mode/maximize_mode_window_manager.cc',
'wm/maximize_mode/maximize_mode_window_manager.h',
'wm/maximize_mode/workspace_backdrop_delegate.cc',
'wm/maximize_mode/workspace_backdrop_delegate.h',
'wm/mru_window_tracker.cc',
'wm/mru_window_tracker.h',
'wm/overlay_event_filter.cc',
......@@ -643,6 +645,7 @@
'wm/workspace/workspace_event_handler.h',
'wm/workspace/workspace_layout_manager.cc',
'wm/workspace/workspace_layout_manager.h',
'wm/workspace/workspace_layout_manager_delegate.h',
'wm/workspace/workspace_types.h',
'wm/workspace/workspace_window_resizer.cc',
'wm/workspace/workspace_window_resizer.h',
......@@ -969,6 +972,8 @@
'wm/window_positioner_unittest.cc',
'wm/window_state_unittest.cc',
'wm/window_util_unittest.cc',
'wm/maximize_mode/workspace_backdrop_delegate.cc',
'wm/maximize_mode/workspace_backdrop_delegate.h',
'wm/workspace/magnetism_matcher_unittest.cc',
'wm/workspace/multi_window_resize_controller_unittest.cc',
'wm/workspace/phantom_window_controller_unittest.cc',
......
......@@ -4,9 +4,12 @@
#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/switchable_windows.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/workspace_controller.h"
#include "ui/aura/window.h"
#include "ui/gfx/screen.h"
......@@ -14,7 +17,9 @@ namespace ash {
namespace internal {
MaximizeModeWindowManager::~MaximizeModeWindowManager() {
Shell::GetInstance()->RemoveShellObserver(this);
Shell::GetScreen()->RemoveObserver(this);
EnableBackdropBehindTopWindowOnEachDisplay(false);
RemoveWindowCreationObservers();
RestoreAllWindows();
}
......@@ -23,6 +28,22 @@ int MaximizeModeWindowManager::GetNumberOfManagedWindows() {
return initial_state_type_.size();
}
void MaximizeModeWindowManager::OnOverviewModeStarted() {
if (backdrops_hidden_)
return;
EnableBackdropBehindTopWindowOnEachDisplay(false);
backdrops_hidden_ = true;
}
void MaximizeModeWindowManager::OnOverviewModeEnded() {
if (!backdrops_hidden_)
return;
backdrops_hidden_ = false;
EnableBackdropBehindTopWindowOnEachDisplay(true);
}
void MaximizeModeWindowManager::OnWindowDestroying(aura::Window* window) {
// If a known window gets destroyed we need to remove all knowledge about it.
if (!IsContainerWindow(window))
......@@ -65,10 +86,15 @@ void MaximizeModeWindowManager::OnDisplayRemoved(const gfx::Display& display) {
DisplayConfigurationChanged();
}
MaximizeModeWindowManager::MaximizeModeWindowManager() {
MaximizeModeWindowManager::MaximizeModeWindowManager()
: backdrops_hidden_(false) {
// TODO(skuhne): Turn off the overview mode and full screen modes before
// entering the MaximzieMode.
MaximizeAllWindows();
AddWindowCreationObservers();
EnableBackdropBehindTopWindowOnEachDisplay(true);
Shell::GetScreen()->AddObserver(this);
Shell::GetInstance()->AddShellObserver(this);
}
void MaximizeModeWindowManager::MaximizeAllWindows() {
......@@ -110,7 +136,6 @@ void MaximizeModeWindowManager::MaximizeAndTrackWindow(
else
window_state->SetRestoreBoundsInScreen(initial_rect);
CenterWindow(window);
// TODO(skuhne): Add a background cover layer.
} else {
// Minimized windows can remain as they are.
if (state != wm::WINDOW_STATE_TYPE_MINIMIZED)
......@@ -128,7 +153,6 @@ void MaximizeModeWindowManager::RestoreAndForgetWindow(
// Restore window if it can be restored.
if (state != wm::WINDOW_STATE_TYPE_MAXIMIZED) {
if (!CanMaximize(window)) {
// TODO(skuhne): Remove the background cover layer.
if (window_state->HasRestoreBounds()) {
// TODO(skuhne): If the system shuts down in maximized mode, the proper
// restore coordinates should get saved.
......@@ -187,19 +211,17 @@ void MaximizeModeWindowManager::CenterWindow(aura::Window* window) {
void MaximizeModeWindowManager::AddWindowCreationObservers() {
DCHECK(observed_container_windows_.empty());
// Observe window activations and switchable containers on all root windows
// for newly created windows during overview.
// Observe window activations/creations in the default containers on all root
// windows.
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
for (aura::Window::Windows::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) {
aura::Window* container = Shell::GetContainer(*iter,
kSwitchableWindowContainerIds[i]);
DCHECK(observed_container_windows_.find(container) ==
observed_container_windows_.end());
container->AddObserver(this);
observed_container_windows_.insert(container);
}
aura::Window* container = Shell::GetContainer(*iter,
internal::kShellWindowId_DefaultContainer);
DCHECK(observed_container_windows_.find(container) ==
observed_container_windows_.end());
container->AddObserver(this);
observed_container_windows_.insert(container);
}
}
......@@ -213,8 +235,10 @@ void MaximizeModeWindowManager::RemoveWindowCreationObservers() {
}
void MaximizeModeWindowManager::DisplayConfigurationChanged() {
EnableBackdropBehindTopWindowOnEachDisplay(false);
RemoveWindowCreationObservers();
AddWindowCreationObservers();
EnableBackdropBehindTopWindowOnEachDisplay(true);
}
bool MaximizeModeWindowManager::IsContainerWindow(aura::Window* window) {
......@@ -222,5 +246,25 @@ bool MaximizeModeWindowManager::IsContainerWindow(aura::Window* window) {
observed_container_windows_.end();
}
void MaximizeModeWindowManager::EnableBackdropBehindTopWindowOnEachDisplay(
bool enable) {
if (backdrops_hidden_)
return;
// Inform the WorkspaceLayoutManager that we want to show a backdrop behind
// the topmost window of its container.
Shell::RootWindowControllerList controllers =
Shell::GetAllRootWindowControllers();
for (Shell::RootWindowControllerList::iterator iter = controllers.begin();
iter != controllers.end(); ++iter) {
RootWindowController* controller = *iter;
aura::Window* container = Shell::GetContainer(
controller->root_window(),
internal::kShellWindowId_DefaultContainer);
controller->workspace_controller()->SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate>(
enable ? new WorkspaceBackdropDelegate(container) : NULL));
}
}
} // namespace internal
} // namespace ash
......@@ -9,6 +9,7 @@
#include <set>
#include "ash/ash_export.h"
#include "ash/shell_observer.h"
#include "ash/wm/window_state.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
......@@ -27,12 +28,13 @@ namespace internal{
// With the destruction of the manager all windows will be restored to their
// original state.
class ASH_EXPORT MaximizeModeWindowManager : public aura::WindowObserver,
public gfx::DisplayObserver {
public gfx::DisplayObserver,
public ShellObserver {
public:
// This should only be deleted by the creator (ash::Shell).
virtual ~MaximizeModeWindowManager();
// Returns the number of maximized & tracked windows by this manager.
// Returns the number of maximized & tracked windows by this manager.
int GetNumberOfManagedWindows();
// Overridden from WindowObserver:
......@@ -48,6 +50,10 @@ class ASH_EXPORT MaximizeModeWindowManager : public aura::WindowObserver,
virtual void OnDisplayAdded(const gfx::Display& display) OVERRIDE;
virtual void OnDisplayRemoved(const gfx::Display& display) OVERRIDE;
// ShellObserver overrides:
void OnOverviewModeStarted();
void OnOverviewModeEnded();
protected:
friend class ash::Shell;
......@@ -98,12 +104,18 @@ class ASH_EXPORT MaximizeModeWindowManager : public aura::WindowObserver,
// Returns true when the |window| is a container window.
bool IsContainerWindow(aura::Window* window);
// Add a backdrop behind the currently active window on each desktop.
void EnableBackdropBehindTopWindowOnEachDisplay(bool enable);
// Every window which got touched by our window manager gets added here.
WindowToStateType initial_state_type_;
// All container windows which have to be tracked.
std::set<aura::Window*> observed_container_windows_;
// True if all backdrops are hidden.
bool backdrops_hidden_;
DISALLOW_COPY_AND_ASSIGN(MaximizeModeWindowManager);
};
......
// Copyright 2014 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/maximize_mode/workspace_backdrop_delegate.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_util.h"
#include "base/auto_reset.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/background.h"
#include "ui/views/corewm/window_util.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace internal {
namespace {
// The opacity of the backdrop.
const float kBackdropOpacity = 0.5f;
} // namespace
WorkspaceBackdropDelegate::WorkspaceBackdropDelegate(aura::Window* container)
: background_(NULL),
container_(container),
in_restacking_(false) {
background_ = new views::Widget;
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.parent = container_;
params.bounds = container_->bounds();
params.layer_type = aura::WINDOW_LAYER_SOLID_COLOR;
// To disallow the MRU list from picking this window up it should not be
// activateable.
params.can_activate = false;
background_->Init(params);
background_->GetNativeView()->SetName("WorkspaceBackdropDelegate");
background_->GetNativeView()->layer()->SetColor(SK_ColorBLACK);
Show();
RestackBackdrop();
container_->AddObserver(this);
}
WorkspaceBackdropDelegate::~WorkspaceBackdropDelegate() {
container_->RemoveObserver(this);
ui::ScopedLayerAnimationSettings settings(
background_->GetNativeView()->layer()->GetAnimator());
background_->Close();
settings.AddObserver(views::corewm::CreateHidingWindowAnimationObserver(
background_->GetNativeView()));
background_->GetNativeView()->layer()->SetOpacity(0.0f);
}
void WorkspaceBackdropDelegate::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
// The container size has changed and the layer needs to be adapt to it.
AdjustToContainerBounds();
}
void WorkspaceBackdropDelegate::OnWindowAddedToLayout(aura::Window* child) {
RestackBackdrop();
}
void WorkspaceBackdropDelegate::OnWindowRemovedFromLayout(aura::Window* child) {
RestackBackdrop();
}
void WorkspaceBackdropDelegate::OnChildWindowVisibilityChanged(
aura::Window* child,
bool visible) {
RestackBackdrop();
}
void WorkspaceBackdropDelegate::OnWindowStackingChanged(aura::Window* window) {
RestackBackdrop();
}
void WorkspaceBackdropDelegate::OnPostWindowStateTypeChange(
wm::WindowState* window_state,
wm::WindowStateType old_type) {
RestackBackdrop();
}
void WorkspaceBackdropDelegate::RestackBackdrop() {
// Avoid recursive calls.
if (in_restacking_)
return;
aura::Window* window = GetCurrentTopWindow();
if (!window) {
// Hide backdrop since no suitable window was found.
background_->Hide();
return;
}
if (window == background_->GetNativeWindow() &&
background_->IsVisible()) {
return;
}
// We are changing the order of windows which will cause recursion.
base::AutoReset<bool> lock(&in_restacking_, true);
if (!background_->IsVisible())
Show();
// Since the backdrop needs to be immediately behind the window and the
// stacking functions only guarantee a "it's above or below", we need
// to re-arrange the two windows twice.
container_->StackChildAbove(background_->GetNativeView(), window);
container_->StackChildAbove(window, background_->GetNativeView());
}
aura::Window* WorkspaceBackdropDelegate::GetCurrentTopWindow() {
const aura::Window::Windows& windows = container_->children();
for (aura::Window::Windows::const_reverse_iterator window_iter =
windows.rbegin();
window_iter != windows.rend(); ++window_iter) {
aura::Window* window = *window_iter;
if (window->TargetVisibility() &&
window->type() == ui::wm::WINDOW_TYPE_NORMAL &&
ash::wm::CanActivateWindow(window))
return window;
}
return NULL;
}
void WorkspaceBackdropDelegate::AdjustToContainerBounds() {
// Cover the entire container window.
gfx::Rect target_rect(gfx::Point(0, 0), container_->bounds().size());
if (target_rect != background_->GetNativeWindow()->bounds()) {
// This needs to be instant.
ui::ScopedLayerAnimationSettings settings(
background_->GetNativeView()->layer()->GetAnimator());
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(0));
background_->GetNativeWindow()->SetBounds(target_rect);
if (!background_->IsVisible())
background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity);
}
}
void WorkspaceBackdropDelegate::Show() {
background_->GetNativeView()->layer()->SetOpacity(0.0f);
background_->Show();
ui::ScopedLayerAnimationSettings settings(
background_->GetNativeView()->layer()->GetAnimator());
background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity);
}
} // namespace internal
} // namespace ash
// Copyright 2014 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_MAXIMIZE_MODE_WORKSPACE_BACKDROP_DELEGATE_H_
#define ASH_WM_MAXIMIZE_MODE_WORKSPACE_BACKDROP_DELEGATE_H_
#include "ash/wm/workspace/workspace_layout_manager_delegate.h"
#include "ui/aura/window_observer.h"
namespace aura {
class Window;
}
namespace ui {
class Layer;
}
namespace views {
class Widget;
}
namespace ash {
namespace internal {
// A background which gets created for a container |window| and which gets
// stacked behind the topmost window (within that container) covering the
// entire container.
class WorkspaceBackdropDelegate : public aura::WindowObserver,
public WorkspaceLayoutManagerDelegate {
public:
explicit WorkspaceBackdropDelegate(aura::Window* container);
virtual ~WorkspaceBackdropDelegate();
// WindowObserver overrides:
virtual void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) OVERRIDE;
// WorkspaceLayoutManagerDelegate overrides:
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) OVERRIDE;
virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
virtual void OnPostWindowStateTypeChange(
wm::WindowState* window_state,
wm::WindowStateType old_type) OVERRIDE;
private:
// Restack the backdrop relatively to the other windows in the container.
void RestackBackdrop();
// Returns the current visible top level window in the container.
aura::Window* GetCurrentTopWindow();
// Position & size the background over the container window.
void AdjustToContainerBounds();
// Show the overlay.
void Show();
// The background which covers the rest of the screen.
views::Widget* background_;
// The window which is being "maximized".
aura::Window* container_;
// If true, the |RestackOrHideWindow| might recurse.
bool in_restacking_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceBackdropDelegate);
};
} // namespace internal
} // namespace ash
#endif // ASH_WM_MAXIMIZE_MODE_WORKSPACE_BACKDROP_DELEGATE_H_
......@@ -17,6 +17,7 @@
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace/workspace_layout_manager_delegate.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
......@@ -50,12 +51,8 @@ WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window)
WorkspaceLayoutManager::~WorkspaceLayoutManager() {
if (root_window_)
root_window_->RemoveObserver(this);
for (WindowSet::const_iterator i = windows_.begin();
i != windows_.end();
++i) {
for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i)
(*i)->RemoveObserver(this);
wm::GetWindowState(*i)->RemoveObserver(this);
}
Shell::GetInstance()->RemoveShellObserver(this);
Shell::GetInstance()->activation_client()->RemoveObserver(this);
}
......@@ -64,6 +61,11 @@ void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) {
shelf_ = shelf;
}
void WorkspaceLayoutManager::SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate> delegate) {
backdrop_delegate_.reset(delegate.release());
}
//////////////////////////////////////////////////////////////////////////////
// WorkspaceLayoutManager, aura::LayoutManager implementation:
......@@ -76,6 +78,8 @@ void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) {
window_state->AddObserver(this);
UpdateShelfVisibility();
UpdateFullscreenState();
if (backdrop_delegate_)
backdrop_delegate_->OnWindowAddedToLayout(child);
WindowPositioner::RearrangeVisibleWindowOnShow(child);
}
......@@ -91,6 +95,8 @@ void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(Window* child) {
void WorkspaceLayoutManager::OnWindowRemovedFromLayout(Window* child) {
UpdateShelfVisibility();
UpdateFullscreenState();
if (backdrop_delegate_)
backdrop_delegate_->OnWindowRemovedFromLayout(child);
}
void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child,
......@@ -106,6 +112,8 @@ void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child,
WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child);
UpdateFullscreenState();
UpdateShelfVisibility();
if (backdrop_delegate_)
backdrop_delegate_->OnChildWindowVisibilityChanged(child, visible);
}
void WorkspaceLayoutManager::SetChildBounds(
......@@ -166,6 +174,8 @@ void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window,
void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) {
UpdateShelfVisibility();
UpdateFullscreenState();
if (backdrop_delegate_)
backdrop_delegate_->OnWindowStackingChanged(window);
}
void WorkspaceLayoutManager::OnWindowDestroying(aura::Window* window) {
......@@ -214,6 +224,8 @@ void WorkspaceLayoutManager::OnPostWindowStateTypeChange(
}
UpdateShelfVisibility();
if (backdrop_delegate_)
backdrop_delegate_->OnPostWindowStateTypeChange(window_state, old_type);
}
//////////////////////////////////////////////////////////////////////////////
......
......@@ -13,6 +13,7 @@
#include "ash/wm/wm_types.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/client/activation_change_observer.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window_observer.h"
......@@ -36,6 +37,7 @@ class WMEvent;
namespace internal {
class ShelfLayoutManager;
class WorkspaceLayoutManagerDelegate;
// LayoutManager used on the window created for a workspace.
class ASH_EXPORT WorkspaceLayoutManager
......@@ -50,6 +52,12 @@ class ASH_EXPORT WorkspaceLayoutManager
void SetShelf(internal::ShelfLayoutManager* shelf);
// A delegate which can be set to add a backdrop behind the top most visible
// window. With the call the ownership of the delegate will be transferred to
// the WorkspaceLayoutManager.
void SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate> delegate);
// Overridden from aura::LayoutManager:
virtual void OnWindowResized() OVERRIDE {}
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
......@@ -103,6 +111,18 @@ class ASH_EXPORT WorkspaceLayoutManager
// has changed.
void UpdateFullscreenState();
// Updates the bounds of the window for a stte type change from
// |old_show_type|.
void UpdateBoundsFromStateType(wm::WindowState* window_state,
wm::WindowStateType old_state_type);
// If |window_state| is maximized or fullscreen the bounds of the
// window are set and true is returned. Does nothing otherwise.
bool SetMaximizedOrFullscreenBounds(wm::WindowState* window_state);
// Animates the window bounds to |bounds|.
void SetChildBoundsAnimated(aura::Window* child, const gfx::Rect& bounds);
internal::ShelfLayoutManager* shelf_;
aura::Window* window_;
aura::Window* root_window_;
......@@ -116,6 +136,10 @@ class ASH_EXPORT WorkspaceLayoutManager
// True if this workspace is currently in fullscreen mode.
bool is_fullscreen_;
// A window which covers the full container and which gets inserted behind the
// topmost visible window.
scoped_ptr<WorkspaceLayoutManagerDelegate> backdrop_delegate_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManager);
};
......
// Copyright 2014 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_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_DELEGATE_H_
#define ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_DELEGATE_H_
#include "ash/wm/wm_types.h"
namespace aura {
class Window;
}
namespace ash {
namespace wm {
class WindowState;
}
namespace internal {
// A delegate which can be set to create and control a backdrop which gets
// placed below the top level window.
class WorkspaceLayoutManagerDelegate {
public:
WorkspaceLayoutManagerDelegate() {}
virtual ~WorkspaceLayoutManagerDelegate() {}
// A window got added to the layout.
virtual void OnWindowAddedToLayout(aura::Window* child) = 0;
// A window got removed from the layout.
virtual void OnWindowRemovedFromLayout(aura::Window* child) = 0;
// The visibility of a window has changed.
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) = 0;
// The stacking order of a window has changed.
virtual void OnWindowStackingChanged(aura::Window* window) = 0;
// A window state type has changed.
virtual void OnPostWindowStateTypeChange(wm::WindowState* window_state,
wm::WindowStateType old_type) = 0;
};
} // namespace internal
} // namespace ash
#endif // ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_DELEGATE_H_
......@@ -14,6 +14,7 @@
#include "ash/shell_observer.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
......@@ -774,4 +775,175 @@ TEST_F(WorkspaceLayoutManagerSoloTest, NotResizeWhenScreenIsLocked) {
EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString());
}
// Following tests are written to test the backdrop functionality.
namespace {
class WorkspaceLayoutManagerBackdropTest : public test::AshTestBase {
public:
WorkspaceLayoutManagerBackdropTest() {}
virtual ~WorkspaceLayoutManagerBackdropTest() {}
virtual void SetUp() OVERRIDE {
test::AshTestBase::SetUp();
UpdateDisplay("800x600");
default_container_ = Shell::GetContainer(
Shell::GetPrimaryRootWindow(),
internal::kShellWindowId_DefaultContainer);
// We set the size to something smaller then the display to avoid resizing
// issues with the shelf.
default_container_->SetBounds(gfx::Rect(0, 0, 800, 500));
}
aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateTestWindowInShellWithBounds(bounds);
return window;
}
// Turn the top window back drop on / off.
void ShowTopWindowBackdrop(bool show) {
scoped_ptr<ash::internal::WorkspaceLayoutManagerDelegate> backdrop;
if (show) {
backdrop.reset(new ash::internal::WorkspaceBackdropDelegate(
default_container_));
}
(static_cast<internal::WorkspaceLayoutManager*>
(default_container_->layout_manager()))->SetMaximizeBackdropDelegate(
backdrop.Pass());
// Closing and / or opening can be a delayed operation.
base::MessageLoop::current()->RunUntilIdle();
}
// Return the default container.
aura::Window* default_container() { return default_container_; }
// Return the order of windows (top most first) as they are in the default
// container. If the window is visible it will be a big letter, otherwise a
// small one. The backdrop will be an X and unknown windows will be shown as
// '!'.
std::string GetWindowOrderAsString(aura::Window* backdrop,
aura::Window* wa,
aura::Window* wb,
aura::Window* wc) {
std::string result;
for (int i = static_cast<int>(default_container()->children().size()) - 1;
i >= 0;
--i) {
if (!result.empty())
result += ",";
if (default_container()->children()[i] == wa)
result += default_container()->children()[i]->IsVisible() ? "A" : "a";
else if (default_container()->children()[i] == wb)
result += default_container()->children()[i]->IsVisible() ? "B" : "b";
else if (default_container()->children()[i] == wc)
result += default_container()->children()[i]->IsVisible() ? "C" : "c";
else if (default_container()->children()[i] == backdrop)
result += default_container()->children()[i]->IsVisible() ? "X" : "x";
else
result += "!";
}
return result;
}
private:
// The default container.
aura::Window* default_container_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerBackdropTest);
};
} // namespace
// Check that creating the BackDrop without destroying it does not lead into
// a crash.
TEST_F(WorkspaceLayoutManagerBackdropTest, BackdropCrashTest) {
ShowTopWindowBackdrop(true);
}
// Verify basic assumptions about the backdrop.
TEST_F(WorkspaceLayoutManagerBackdropTest, BasicBackdropTests) {
// Create a backdrop and see that there is one window (the backdrop) and
// that the size is the same as the default container as well as that it is
// not visible.
ShowTopWindowBackdrop(true);
ASSERT_EQ(1U, default_container()->children().size());
EXPECT_FALSE(default_container()->children()[0]->IsVisible());
{
// Add a window and make sure that the backdrop is the second child.
scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
window->Show();
ASSERT_EQ(2U, default_container()->children().size());
EXPECT_TRUE(default_container()->children()[0]->IsVisible());
EXPECT_TRUE(default_container()->children()[1]->IsVisible());
EXPECT_EQ(window.get(), default_container()->children()[1]);
EXPECT_EQ(default_container()->bounds().ToString(),
default_container()->children()[0]->bounds().ToString());
}
// With the window gone the backdrop should be invisible again.
ASSERT_EQ(1U, default_container()->children().size());
EXPECT_FALSE(default_container()->children()[0]->IsVisible());
// Destroying the Backdrop should empty the container.
ShowTopWindowBackdrop(false);
ASSERT_EQ(0U, default_container()->children().size());
}
// Verify that the backdrop gets properly created and placed.
TEST_F(WorkspaceLayoutManagerBackdropTest, VerifyBackdropAndItsStacking) {
scoped_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
window1->Show();
// Get the default container and check that only a single window is in there.
ASSERT_EQ(1U, default_container()->children().size());
EXPECT_EQ(window1.get(), default_container()->children()[0]);
EXPECT_EQ("A", GetWindowOrderAsString(NULL, window1.get(), NULL, NULL));
// Create 2 more windows and check that they are also in the container.
scoped_ptr<aura::Window> window2(CreateTestWindow(gfx::Rect(10, 2, 3, 4)));
scoped_ptr<aura::Window> window3(CreateTestWindow(gfx::Rect(20, 2, 3, 4)));
window2->Show();
window3->Show();
aura::Window* backdrop = NULL;
EXPECT_EQ("C,B,A",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
// Turn on the backdrop mode and check that the window shows up where it
// should be (second highest number).
ShowTopWindowBackdrop(true);
backdrop = default_container()->children()[2];
EXPECT_EQ("C,X,B,A",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
// Switch the order of windows and check that it still remains in that
// location.
default_container()->StackChildAtTop(window2.get());
EXPECT_EQ("B,X,C,A",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
// Make the top window invisible and check.
window2.get()->Hide();
EXPECT_EQ("b,C,X,A",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
// Then delete window after window and see that everything is in order.
window1.reset();
EXPECT_EQ("b,C,X",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
window3.reset();
EXPECT_EQ("b,x",
GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
window3.get()));
ShowTopWindowBackdrop(false);
EXPECT_EQ("b",
GetWindowOrderAsString(NULL, window1.get(), window2.get(),
window3.get()));
}
} // namespace ash
......@@ -13,6 +13,7 @@
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_event_handler.h"
#include "ash/wm/workspace/workspace_layout_manager.h"
#include "ash/wm/workspace/workspace_layout_manager_delegate.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
......@@ -135,5 +136,10 @@ void WorkspaceController::DoInitialAnimation() {
}
}
void WorkspaceController::SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate> delegate) {
layout_manager_->SetMaximizeBackdropDelegate(delegate.Pass());
}
} // namespace internal
} // namespace ash
......@@ -21,6 +21,7 @@ class ShelfLayoutManager;
class WorkspaceControllerTestHelper;
class WorkspaceEventHandler;
class WorkspaceLayoutManager;
class WorkspaceLayoutManagerDelegate;
// WorkspaceController acts as a central place that ties together all the
// various workspace pieces.
......@@ -37,6 +38,11 @@ class ASH_EXPORT WorkspaceController {
// Starts the animation that occurs on first login.
void DoInitialAnimation();
// Add a delegate which adds a backdrop behind the top window of the default
// workspace.
void SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate> delegate);
private:
friend class WorkspaceControllerTestHelper;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment