blob: a7bc2c720c36cd83b204f5b904db2cf7b223789e [file] [log] [blame]
// 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_WORKSPACE_WORKSPACE_MANAGER_H_
#define ASH_WM_WORKSPACE_WORKSPACE_MANAGER_H_
#include <set>
#include <string>
#include <vector>
#include "ash/ash_export.h"
#include "ash/shell_observer.h"
#include "ash/wm/workspace/workspace_types.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/base/ui_base_types.h"
namespace aura {
class Window;
}
namespace base {
class TimeDelta;
}
namespace gfx {
class Point;
class Rect;
}
namespace ui {
class Layer;
}
namespace ash {
namespace internal {
class DesktopBackgroundFadeController;
class ShelfLayoutManager;
class WorkspaceLayoutManager;
class WorkspaceManagerTest2;
class Workspace;
// WorkspaceManager manages multiple workspaces in the desktop. Workspaces are
// implicitly created as windows are maximized (or made fullscreen), and
// destroyed when maximized windows are closed or restored. There is always one
// workspace for the desktop.
// Internally WorkspaceManager creates a Window for each Workspace. As windows
// are maximized and restored they are reparented to the right Window.
class ASH_EXPORT WorkspaceManager : public ash::ShellObserver {
public:
explicit WorkspaceManager(aura::Window* viewport);
virtual ~WorkspaceManager();
// Returns the current window state.
WorkspaceWindowState GetWindowState() const;
void SetShelf(ShelfLayoutManager* shelf);
// Activates the workspace containing |window|. Does nothing if |window| is
// NULL or not contained in a workspace.
void SetActiveWorkspaceByWindow(aura::Window* window);
// Returns the container window for the active workspace, never NULL.
aura::Window* GetActiveWorkspaceWindow();
// Returns the parent for |window|. This is invoked from StackingController
// when a new Window is being added.
aura::Window* GetParentForNewWindow(aura::Window* window);
// Starts the animation that occurs on first login.
void DoInitialAnimation();
// ShellObserver overrides:
virtual void OnAppTerminating() OVERRIDE;
private:
friend class WorkspaceLayoutManager;
friend class WorkspaceManagerTest;
class LayoutManagerImpl;
typedef std::vector<Workspace*> Workspaces;
// Reason for the workspace switch. Used to determine the characteristics of
// the animation.
enum SwitchReason {
SWITCH_WINDOW_MADE_ACTIVE,
SWITCH_MAXIMIZED_OR_RESTORED,
SWITCH_TRACKED_BY_WORKSPACE_CHANGED,
// Switch as the result of DoInitialAnimation(). This isn't a real switch,
// rather we run the animations as if a switch occurred.
SWITCH_INITIAL,
// Switch as the result of the user selecting a new active workspace via the
// workspace cycler.
SWITCH_WORKSPACE_CYCLER,
// Edge case. See comment in OnWorkspaceWindowShowStateChanged(). Don't
// make other types randomly use this!
SWITCH_OTHER,
};
// Updates the visibility and whether any windows overlap the shelf.
void UpdateShelfVisibility();
// Returns the workspace that contains |window|.
Workspace* FindBy(aura::Window* window) const;
// Sets the active workspace.
void SetActiveWorkspace(Workspace* workspace,
SwitchReason reason);
// Returns the bounds of the work area.
gfx::Rect GetWorkAreaBounds() const;
// Returns an iterator into |workspaces_| for |workspace|.
Workspaces::iterator FindWorkspace(Workspace* workspace);
Workspace* desktop_workspace() { return workspaces_[0]; }
const Workspace* desktop_workspace() const { return workspaces_[0]; }
// Creates a new workspace to test multiple workspaces. The Workspace is not
// added to anything and is owned by the caller.
Workspace* CreateWorkspaceForTest();
// Moves all the non-maximized child windows of |workspace| to the desktop
// stacked beneath |stack_beneath| (if non-NULL). After moving child windows
// if |workspace| contains no children it is deleted, otherwise it it moved to
// |pending_workspaces_|.
void MoveWorkspaceToPendingOrDelete(Workspace* workspace,
aura::Window* stack_beneath,
SwitchReason reason);
// Moves the children of |window| to the desktop. This excludes certain
// windows. If |stack_beneath| is non-NULL the windows are stacked beneath it.
void MoveChildrenToDesktop(aura::Window* window, aura::Window* stack_beneath);
// Selects the next workspace.
void SelectNextWorkspace(SwitchReason reason);
// Schedules |workspace| for deletion when it no longer contains any layers.
// See comments above |to_delete_| as to why we do this.
void ScheduleDelete(Workspace* workspace);
// Deletes any workspaces scheduled via ScheduleDelete() that don't contain
// any layers.
void ProcessDeletion();
// Fades the desktop. This is only used when maximizing or restoring a
// window. The actual fade is handled by
// DesktopBackgroundFadeController. |window| is used when restoring and
// indicates the window to stack the DesktopBackgroundFadeController's window
// above.
void FadeDesktop(aura::Window* window, base::TimeDelta duration);
// Shows/hides |workspace| animating as necessary.
void ShowWorkspace(Workspace* workspace,
Workspace* last_active,
SwitchReason reason) const;
void HideWorkspace(Workspace* workspace, SwitchReason reason) const;
// These methods are forwarded from the LayoutManager installed on the
// Workspace's window.
void OnWindowAddedToWorkspace(Workspace* workspace, aura::Window* child);
void OnWillRemoveWindowFromWorkspace(Workspace* workspace,
aura::Window* child);
void OnWindowRemovedFromWorkspace(Workspace* workspace, aura::Window* child);
void OnWorkspaceChildWindowVisibilityChanged(Workspace* workspace,
aura::Window* child);
void OnWorkspaceWindowChildBoundsChanged(Workspace* workspace,
aura::Window* child);
void OnWorkspaceWindowShowStateChanged(Workspace* workspace,
aura::Window* child,
ui::WindowShowState last_show_state);
void OnTrackedByWorkspaceChanged(Workspace* workspace,
aura::Window* window);
aura::Window* contents_window_;
Workspace* active_workspace_;
// The set of active workspaces. There is always at least one in this stack,
// which identifies the desktop.
Workspaces workspaces_;
// The set of workspaces not currently active. Workspaces ended up here in
// two scenarios:
// . Prior to adding a window a new workspace is created for it. The
// Workspace is added to this set.
// . When the maximized window is minimized the workspace is added here.
// Once any window in the workspace is activated the workspace is moved to
// |workspaces_|.
std::set<Workspace*> pending_workspaces_;
// Owned by the Shell. May be NULL.
ShelfLayoutManager* shelf_;
// Whether or not we're in MoveWorkspaceToPendingOrDelete(). As
// MoveWorkspaceToPendingOrDelete() may trigger another call to
// MoveWorkspaceToPendingOrDelete() we use this to avoid doing anything if
// already in MoveWorkspaceToPendingOrDelete().
bool in_move_;
// Ideally we would delete workspaces when not needed. Unfortunately doing so
// would effectively cancel animations. Instead when a workspace is no longer
// needed we add it here and start a timer. When the timer fires any windows
// no longer contain layers are deleted.
std::set<Workspace*> to_delete_;
base::OneShotTimer<WorkspaceManager> delete_timer_;
// Set to true if the app is terminating. If true we don't animate the
// background, otherwise it can get stuck in the fading position when chrome
// exits (as the last frame we draw before exiting is a frame from the
// animation).
bool app_terminating_;
scoped_ptr<DesktopBackgroundFadeController> desktop_fade_controller_;
// Set to true while in the process of creating a
// DesktopBackgroundFadeController.
bool creating_fade_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceManager);
};
} // namespace internal
} // namespace ash
#endif // ASH_WM_WORKSPACE_WORKSPACE_MANAGER_H_