Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / ash / wm / base_layout_manager.cc
1 // Copyright (c) 2012 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.
4
5 #include "ash/wm/base_layout_manager.h"
6
7 #include "ash/screen_util.h"
8 #include "ash/session_state_delegate.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shell.h"
11 #include "ash/wm/window_animations.h"
12 #include "ash/wm/window_properties.h"
13 #include "ash/wm/window_state.h"
14 #include "ash/wm/window_util.h"
15 #include "ash/wm/workspace/workspace_window_resizer.h"
16 #include "ui/aura/client/activation_client.h"
17 #include "ui/aura/client/aura_constants.h"
18 #include "ui/aura/window.h"
19 #include "ui/base/ui_base_types.h"
20 #include "ui/compositor/layer.h"
21 #include "ui/gfx/screen.h"
22 #include "ui/views/corewm/corewm_switches.h"
23 #include "ui/views/corewm/window_util.h"
24
25 namespace ash {
26 namespace internal {
27
28 /////////////////////////////////////////////////////////////////////////////
29 // BaseLayoutManager, public:
30
31 BaseLayoutManager::BaseLayoutManager(aura::Window* root_window)
32     : root_window_(root_window) {
33   Shell::GetInstance()->activation_client()->AddObserver(this);
34   Shell::GetInstance()->AddShellObserver(this);
35   root_window_->AddObserver(this);
36 }
37
38 BaseLayoutManager::~BaseLayoutManager() {
39   if (root_window_)
40     root_window_->RemoveObserver(this);
41   for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i)
42     (*i)->RemoveObserver(this);
43   Shell::GetInstance()->RemoveShellObserver(this);
44   Shell::GetInstance()->activation_client()->RemoveObserver(this);
45 }
46
47 // static
48 gfx::Rect BaseLayoutManager::BoundsWithScreenEdgeVisible(
49     aura::Window* window,
50     const gfx::Rect& restore_bounds) {
51   gfx::Rect max_bounds =
52       ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window);
53   // If the restore_bounds are more than 1 grid step away from the size the
54   // window would be when maximized, inset it.
55   max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset,
56                    ash::internal::WorkspaceWindowResizer::kScreenEdgeInset);
57   if (restore_bounds.Contains(max_bounds))
58     return max_bounds;
59   return restore_bounds;
60 }
61
62 /////////////////////////////////////////////////////////////////////////////
63 // BaseLayoutManager, aura::LayoutManager overrides:
64
65 void BaseLayoutManager::OnWindowResized() {
66 }
67
68 void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
69   windows_.insert(child);
70   child->AddObserver(this);
71   wm::WindowState* window_state = wm::GetWindowState(child);
72   window_state->AddObserver(this);
73
74   // Only update the bounds if the window has a show state that depends on the
75   // workspace area.
76   if (window_state->IsMaximizedOrFullscreen())
77     UpdateBoundsFromShowType(window_state);
78 }
79
80 void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
81   windows_.erase(child);
82   child->RemoveObserver(this);
83   wm::GetWindowState(child)->RemoveObserver(this);
84 }
85
86 void BaseLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
87 }
88
89 void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
90                                                        bool visible) {
91   wm::WindowState* window_state = wm::GetWindowState(child);
92   // Attempting to show a minimized window. Unminimize it.
93   if (visible && window_state->IsMinimized())
94     window_state->Unminimize();
95 }
96
97 void BaseLayoutManager::SetChildBounds(aura::Window* child,
98                                        const gfx::Rect& requested_bounds) {
99   gfx::Rect child_bounds(requested_bounds);
100   wm::WindowState* window_state = wm::GetWindowState(child);
101   // Some windows rely on this to set their initial bounds.
102   if (window_state->IsMaximized())
103     child_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent(child);
104   else if (window_state->IsFullscreen())
105     child_bounds = ScreenUtil::GetDisplayBoundsInParent(child);
106   SetChildBoundsDirect(child, child_bounds);
107 }
108
109 /////////////////////////////////////////////////////////////////////////////
110 // BaseLayoutManager, aura::WindowObserver overrides:
111
112 void BaseLayoutManager::OnWindowDestroying(aura::Window* window) {
113   if (root_window_ == window) {
114     root_window_->RemoveObserver(this);
115     root_window_ = NULL;
116   }
117 }
118
119 void BaseLayoutManager::OnWindowBoundsChanged(aura::Window* window,
120                                               const gfx::Rect& old_bounds,
121                                               const gfx::Rect& new_bounds) {
122   if (root_window_ == window)
123     AdjustAllWindowsBoundsForWorkAreaChange(ADJUST_WINDOW_DISPLAY_SIZE_CHANGED);
124 }
125
126 //////////////////////////////////////////////////////////////////////////////
127 // BaseLayoutManager, aura::client::ActivationChangeObserver implementation:
128
129 void BaseLayoutManager::OnWindowActivated(aura::Window* gained_active,
130                                           aura::Window* lost_active) {
131   wm::WindowState* window_state = wm::GetWindowState(gained_active);
132   if (window_state && window_state->IsMinimized() &&
133       !gained_active->IsVisible()) {
134     window_state->Unminimize();
135     DCHECK(!window_state->IsMinimized());
136   }
137 }
138
139 /////////////////////////////////////////////////////////////////////////////
140 // BaseLayoutManager, ash::ShellObserver overrides:
141
142 void BaseLayoutManager::OnDisplayWorkAreaInsetsChanged() {
143   AdjustAllWindowsBoundsForWorkAreaChange(
144       ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED);
145 }
146
147 /////////////////////////////////////////////////////////////////////////////
148 // BaseLayoutManager, ash::wm::WindowStateObserver overrides:
149
150 void BaseLayoutManager::OnWindowShowTypeChanged(wm::WindowState* window_state,
151                                                 wm::WindowShowType old_type) {
152   if (old_type != wm::SHOW_TYPE_MINIMIZED &&
153       !window_state->HasRestoreBounds() &&
154       window_state->IsMaximizedOrFullscreen() &&
155       !wm::IsMaximizedOrFullscreenWindowShowType(old_type)) {
156     window_state->SetRestoreBoundsInParent(window_state->window()->bounds());
157   }
158
159   UpdateBoundsFromShowType(window_state);
160   ShowTypeChanged(window_state, old_type);
161 }
162
163 //////////////////////////////////////////////////////////////////////////////
164 // BaseLayoutManager, protected:
165
166 void BaseLayoutManager::ShowTypeChanged(
167     wm::WindowState* window_state,
168     wm::WindowShowType last_show_type) {
169   if (window_state->IsMinimized()) {
170     if (last_show_type == wm::SHOW_TYPE_MINIMIZED)
171       return;
172
173     // Save the previous show state so that we can correctly restore it.
174     window_state->window()->SetProperty(aura::client::kRestoreShowStateKey,
175                                         wm::ToWindowShowState(last_show_type));
176     views::corewm::SetWindowVisibilityAnimationType(
177         window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
178
179     // Hide the window.
180     window_state->window()->Hide();
181     // Activate another window.
182     if (window_state->IsActive())
183       window_state->Deactivate();
184   } else if ((window_state->window()->TargetVisibility() ||
185               last_show_type == wm::SHOW_TYPE_MINIMIZED) &&
186              !window_state->window()->layer()->visible()) {
187     // The layer may be hidden if the window was previously minimized. Make
188     // sure it's visible.
189     window_state->window()->Show();
190     if (last_show_type == wm::SHOW_TYPE_MINIMIZED &&
191         !window_state->IsMaximizedOrFullscreen()) {
192       window_state->set_always_restores_to_restore_bounds(false);
193     }
194   }
195 }
196
197 void BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(
198     AdjustWindowReason reason) {
199   // Don't do any adjustments of the insets while we are in screen locked mode.
200   // This would happen if the launcher was auto hidden before the login screen
201   // was shown and then gets shown when the login screen gets presented.
202   if (reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED &&
203       Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
204     return;
205
206   // If a user plugs an external display into a laptop running Aura the
207   // display size will change.  Maximized windows need to resize to match.
208   // We also do this when developers running Aura on a desktop manually resize
209   // the host window.
210   // We also need to do this when the work area insets changes.
211   for (WindowSet::const_iterator it = windows_.begin();
212        it != windows_.end();
213        ++it) {
214     AdjustWindowBoundsForWorkAreaChange(wm::GetWindowState(*it), reason);
215   }
216 }
217
218 void BaseLayoutManager::AdjustWindowBoundsForWorkAreaChange(
219     wm::WindowState* window_state,
220     AdjustWindowReason reason) {
221   aura::Window* window = window_state->window();
222   if (window_state->IsMaximized()) {
223     SetChildBoundsDirect(
224         window, ScreenUtil::GetMaximizedWindowBoundsInParent(window));
225   } else if (window_state->IsFullscreen()) {
226     SetChildBoundsDirect(
227         window, ScreenUtil::GetDisplayBoundsInParent(window));
228   } else {
229     // The work area may be smaller than the full screen.
230     gfx::Rect display_rect =
231         ScreenUtil::GetDisplayWorkAreaBoundsInParent(window);
232     // Put as much of the window as possible within the display area.
233     gfx::Rect bounds = window->bounds();
234     bounds.AdjustToFit(display_rect);
235     window->SetBounds(bounds);
236   }
237 }
238
239 //////////////////////////////////////////////////////////////////////////////
240 // BaseLayoutManager, private:
241
242 void BaseLayoutManager::UpdateBoundsFromShowType(
243     wm::WindowState* window_state) {
244   aura::Window* window = window_state->window();
245   switch (window_state->window_show_type()) {
246     case wm::SHOW_TYPE_DEFAULT:
247     case wm::SHOW_TYPE_NORMAL:
248       if (window_state->HasRestoreBounds()) {
249         gfx::Rect bounds_in_parent = window_state->GetRestoreBoundsInParent();
250         SetChildBoundsDirect(window,
251                              BoundsWithScreenEdgeVisible(window,
252                                                          bounds_in_parent));
253       }
254       window_state->ClearRestoreBounds();
255       break;
256
257     case wm::SHOW_TYPE_LEFT_SNAPPED:
258     case wm::SHOW_TYPE_RIGHT_SNAPPED:
259       if (window_state->HasRestoreBounds())
260         SetChildBoundsDirect(window, window_state->GetRestoreBoundsInParent());
261       window_state->ClearRestoreBounds();
262       break;
263
264     case wm::SHOW_TYPE_MAXIMIZED:
265       SetChildBoundsDirect(
266           window, ScreenUtil::GetMaximizedWindowBoundsInParent(window));
267       break;
268
269     case wm::SHOW_TYPE_FULLSCREEN:
270       // Don't animate the full-screen window transition.
271       // TODO(jamescook): Use animation here.  Be sure the lock screen works.
272       SetChildBoundsDirect(window,
273                            ScreenUtil::GetDisplayBoundsInParent(window));
274       break;
275
276     case wm::SHOW_TYPE_MINIMIZED:
277     case wm::SHOW_TYPE_INACTIVE:
278     case wm::SHOW_TYPE_DETACHED:
279     case wm::SHOW_TYPE_END:
280     case wm::SHOW_TYPE_AUTO_POSITIONED:
281       break;
282   }
283 }
284
285 }  // namespace internal
286 }  // namespace ash