1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "athena/wm/public/window_manager.h"
9 #include "athena/common/container_priorities.h"
10 #include "athena/input/public/accelerator_manager.h"
11 #include "athena/screen/public/screen_manager.h"
12 #include "athena/wm/bezel_controller.h"
13 #include "athena/wm/public/window_manager_observer.h"
14 #include "athena/wm/split_view_controller.h"
15 #include "athena/wm/title_drag_controller.h"
16 #include "athena/wm/window_list_provider_impl.h"
17 #include "athena/wm/window_overview_mode.h"
18 #include "base/logging.h"
19 #include "base/observer_list.h"
20 #include "ui/aura/layout_manager.h"
21 #include "ui/aura/window.h"
22 #include "ui/wm/core/shadow_controller.h"
23 #include "ui/wm/core/window_util.h"
24 #include "ui/wm/core/wm_state.h"
25 #include "ui/wm/public/activation_client.h"
26 #include "ui/wm/public/window_types.h"
31 class WindowManagerImpl
: public WindowManager
,
32 public WindowOverviewModeDelegate
,
33 public aura::WindowObserver
,
34 public AcceleratorHandler
,
35 public TitleDragControllerDelegate
{
38 virtual ~WindowManagerImpl();
43 virtual void ToggleOverview() OVERRIDE
;
45 virtual bool IsOverviewModeActive() OVERRIDE
;
52 // Sets whether overview mode is active.
53 void SetInOverview(bool active
);
55 void InstallAccelerators();
58 virtual void AddObserver(WindowManagerObserver
* observer
) OVERRIDE
;
59 virtual void RemoveObserver(WindowManagerObserver
* observer
) OVERRIDE
;
61 // WindowOverviewModeDelegate:
62 virtual void OnSelectWindow(aura::Window
* window
) OVERRIDE
;
63 virtual void OnSplitViewMode(aura::Window
* left
,
64 aura::Window
* right
) OVERRIDE
;
66 // aura::WindowObserver
67 virtual void OnWindowAdded(aura::Window
* new_window
) OVERRIDE
;
68 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
;
70 // AcceleratorHandler:
71 virtual bool IsCommandEnabled(int command_id
) const OVERRIDE
;
72 virtual bool OnAcceleratorFired(int command_id
,
73 const ui::Accelerator
& accelerator
) OVERRIDE
;
75 // TitleDragControllerDelegate:
76 virtual aura::Window
* GetWindowBehind(aura::Window
* window
) OVERRIDE
;
77 virtual void OnTitleDragStarted(aura::Window
* window
) OVERRIDE
;
78 virtual void OnTitleDragCompleted(aura::Window
* window
) OVERRIDE
;
79 virtual void OnTitleDragCanceled(aura::Window
* window
) OVERRIDE
;
81 scoped_ptr
<aura::Window
> container_
;
82 scoped_ptr
<WindowListProvider
> window_list_provider_
;
83 scoped_ptr
<WindowOverviewMode
> overview_
;
84 scoped_ptr
<BezelController
> bezel_controller_
;
85 scoped_ptr
<SplitViewController
> split_view_controller_
;
86 scoped_ptr
<wm::WMState
> wm_state_
;
87 scoped_ptr
<TitleDragController
> title_drag_controller_
;
88 scoped_ptr
<wm::ShadowController
> shadow_controller_
;
89 ObserverList
<WindowManagerObserver
> observers_
;
91 DISALLOW_COPY_AND_ASSIGN(WindowManagerImpl
);
94 class AthenaContainerLayoutManager
: public aura::LayoutManager
{
96 AthenaContainerLayoutManager();
97 virtual ~AthenaContainerLayoutManager();
100 // aura::LayoutManager:
101 virtual void OnWindowResized() OVERRIDE
;
102 virtual void OnWindowAddedToLayout(aura::Window
* child
) OVERRIDE
;
103 virtual void OnWillRemoveWindowFromLayout(aura::Window
* child
) OVERRIDE
;
104 virtual void OnWindowRemovedFromLayout(aura::Window
* child
) OVERRIDE
;
105 virtual void OnChildWindowVisibilityChanged(aura::Window
* child
,
106 bool visible
) OVERRIDE
;
107 virtual void SetChildBounds(aura::Window
* child
,
108 const gfx::Rect
& requested_bounds
) OVERRIDE
;
110 DISALLOW_COPY_AND_ASSIGN(AthenaContainerLayoutManager
);
113 class WindowManagerImpl
* instance
= NULL
;
115 WindowManagerImpl::WindowManagerImpl() {
116 ScreenManager::ContainerParams
params("DefaultContainer", CP_DEFAULT
);
117 params
.can_activate_children
= true;
118 container_
.reset(ScreenManager::Get()->CreateDefaultContainer(params
));
119 container_
->SetLayoutManager(new AthenaContainerLayoutManager
);
120 container_
->AddObserver(this);
121 window_list_provider_
.reset(new WindowListProviderImpl(container_
.get()));
122 bezel_controller_
.reset(new BezelController(container_
.get()));
123 split_view_controller_
.reset(
124 new SplitViewController(container_
.get(), window_list_provider_
.get()));
125 bezel_controller_
->set_left_right_delegate(split_view_controller_
.get());
126 container_
->AddPreTargetHandler(bezel_controller_
.get());
127 title_drag_controller_
.reset(new TitleDragController(container_
.get(), this));
128 wm_state_
.reset(new wm::WMState());
129 aura::client::ActivationClient
* activation_client
=
130 aura::client::GetActivationClient(container_
->GetRootWindow());
131 shadow_controller_
.reset(new wm::ShadowController(activation_client
));
133 InstallAccelerators();
136 WindowManagerImpl::~WindowManagerImpl() {
138 split_view_controller_
.reset();
139 window_list_provider_
.reset();
141 container_
->RemoveObserver(this);
142 container_
->RemovePreTargetHandler(bezel_controller_
.get());
144 // |title_drag_controller_| needs to be reset before |container_|.
145 title_drag_controller_
.reset();
150 void WindowManagerImpl::Layout() {
153 gfx::Rect bounds
= gfx::Rect(container_
->bounds().size());
154 const aura::Window::Windows
& children
= container_
->children();
155 for (aura::Window::Windows::const_iterator iter
= children
.begin();
156 iter
!= children
.end();
158 if ((*iter
)->type() == ui::wm::WINDOW_TYPE_NORMAL
)
159 (*iter
)->SetBounds(bounds
);
163 void WindowManagerImpl::ToggleOverview() {
164 SetInOverview(overview_
.get() == NULL
);
167 bool WindowManagerImpl::IsOverviewModeActive() {
171 void WindowManagerImpl::SetInOverview(bool active
) {
172 bool in_overview
= !!overview_
;
173 if (active
== in_overview
)
176 bezel_controller_
->set_left_right_delegate(
177 active
? NULL
: split_view_controller_
.get());
179 split_view_controller_
->DeactivateSplitMode();
180 FOR_EACH_OBSERVER(WindowManagerObserver
, observers_
,
181 OnOverviewModeEnter());
182 // Re-stack all windows in the order defined by window_list_provider_.
183 aura::Window::Windows window_list
= window_list_provider_
->GetWindowList();
184 aura::Window::Windows::iterator it
;
185 for (it
= window_list
.begin(); it
!= window_list
.end(); ++it
)
186 container_
->StackChildAtTop(*it
);
187 overview_
= WindowOverviewMode::Create(
188 container_
.get(), window_list_provider_
.get(), this);
190 CHECK(!split_view_controller_
->IsSplitViewModeActive());
192 FOR_EACH_OBSERVER(WindowManagerObserver
, observers_
,
193 OnOverviewModeExit());
197 void WindowManagerImpl::InstallAccelerators() {
198 const AcceleratorData accelerator_data
[] = {
199 {TRIGGER_ON_PRESS
, ui::VKEY_F6
, ui::EF_NONE
, CMD_TOGGLE_OVERVIEW
,
202 AcceleratorManager::Get()->RegisterAccelerators(
203 accelerator_data
, arraysize(accelerator_data
), this);
206 void WindowManagerImpl::AddObserver(WindowManagerObserver
* observer
) {
207 observers_
.AddObserver(observer
);
210 void WindowManagerImpl::RemoveObserver(WindowManagerObserver
* observer
) {
211 observers_
.RemoveObserver(observer
);
214 void WindowManagerImpl::OnSelectWindow(aura::Window
* window
) {
215 wm::ActivateWindow(window
);
216 SetInOverview(false);
219 void WindowManagerImpl::OnSplitViewMode(aura::Window
* left
,
220 aura::Window
* right
) {
221 SetInOverview(false);
222 split_view_controller_
->ActivateSplitMode(left
, right
);
225 void WindowManagerImpl::OnWindowAdded(aura::Window
* new_window
) {
226 if (new_window
->type() == ui::wm::WINDOW_TYPE_NORMAL
)
227 SetInOverview(false);
230 void WindowManagerImpl::OnWindowDestroying(aura::Window
* window
) {
231 if (window
== container_
)
235 bool WindowManagerImpl::IsCommandEnabled(int command_id
) const {
239 bool WindowManagerImpl::OnAcceleratorFired(int command_id
,
240 const ui::Accelerator
& accelerator
) {
241 switch (command_id
) {
242 case CMD_TOGGLE_OVERVIEW
:
249 aura::Window
* WindowManagerImpl::GetWindowBehind(aura::Window
* window
) {
250 const aura::Window::Windows
& windows
= window_list_provider_
->GetWindowList();
251 aura::Window::Windows::const_reverse_iterator iter
=
252 std::find(windows
.rbegin(), windows
.rend(), window
);
253 CHECK(iter
!= windows
.rend());
255 aura::Window
* behind
= NULL
;
256 if (iter
!= windows
.rend())
259 if (split_view_controller_
->IsSplitViewModeActive()) {
260 aura::Window
* left
= split_view_controller_
->left_window();
261 aura::Window
* right
= split_view_controller_
->right_window();
262 CHECK(window
== left
|| window
== right
);
263 if (behind
== left
|| behind
== right
)
264 behind
= (iter
== windows
.rend()) ? NULL
: *iter
;
270 void WindowManagerImpl::OnTitleDragStarted(aura::Window
* window
) {
271 aura::Window
* next_window
= GetWindowBehind(window
);
274 // Make sure |window| is active. Also make sure that |next_window| is visible,
275 // and positioned to match the top-left edge of |window|.
276 wm::ActivateWindow(window
);
278 int dx
= window
->bounds().x() - next_window
->bounds().x();
280 gfx::Transform transform
;
281 transform
.Translate(dx
, 0);
282 next_window
->SetTransform(transform
);
286 void WindowManagerImpl::OnTitleDragCompleted(aura::Window
* window
) {
287 aura::Window
* next_window
= GetWindowBehind(window
);
290 if (split_view_controller_
->IsSplitViewModeActive())
291 split_view_controller_
->ReplaceWindow(window
, next_window
);
293 OnSelectWindow(next_window
);
294 wm::ActivateWindow(next_window
);
297 void WindowManagerImpl::OnTitleDragCanceled(aura::Window
* window
) {
298 aura::Window
* next_window
= GetWindowBehind(window
);
301 next_window
->SetTransform(gfx::Transform());
304 AthenaContainerLayoutManager::AthenaContainerLayoutManager() {
307 AthenaContainerLayoutManager::~AthenaContainerLayoutManager() {
310 void AthenaContainerLayoutManager::OnWindowResized() {
314 void AthenaContainerLayoutManager::OnWindowAddedToLayout(aura::Window
* child
) {
318 void AthenaContainerLayoutManager::OnWillRemoveWindowFromLayout(
319 aura::Window
* child
) {
322 void AthenaContainerLayoutManager::OnWindowRemovedFromLayout(
323 aura::Window
* child
) {
327 void AthenaContainerLayoutManager::OnChildWindowVisibilityChanged(
333 void AthenaContainerLayoutManager::SetChildBounds(
335 const gfx::Rect
& requested_bounds
) {
336 if (!requested_bounds
.IsEmpty())
337 SetChildBoundsDirect(child
, requested_bounds
);
343 WindowManager
* WindowManager::Create() {
345 new WindowManagerImpl
;
351 void WindowManager::Shutdown() {
358 WindowManager
* WindowManager::GetInstance() {
363 } // namespace athena