OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/workspace/auto_window_management.h" | 5 #include "ash/wm/workspace/auto_window_management.h" |
6 | 6 |
7 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
8 #include "ash/screen_ash.h" | 8 #include "ash/screen_ash.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ash/wm/mru_window_tracker.h" | 10 #include "ash/wm/mru_window_tracker.h" |
11 #include "ash/wm/property_util.h" | |
12 #include "ash/wm/window_animations.h" | 11 #include "ash/wm/window_animations.h" |
13 #include "ash/wm/window_settings.h" | 12 #include "ash/wm/window_state.h" |
14 #include "ash/wm/window_util.h" | 13 #include "ash/wm/window_util.h" |
15 #include "base/command_line.h" | 14 #include "base/command_line.h" |
16 #include "ui/aura/window.h" | 15 #include "ui/aura/window.h" |
17 #include "ui/aura/client/aura_constants.h" | 16 #include "ui/aura/client/aura_constants.h" |
18 #include "ui/compositor/layer_animator.h" | 17 #include "ui/compositor/layer_animator.h" |
19 #include "ui/compositor/scoped_layer_animation_settings.h" | 18 #include "ui/compositor/scoped_layer_animation_settings.h" |
20 #include "ui/gfx/screen.h" | 19 #include "ui/gfx/screen.h" |
21 | 20 |
22 namespace ash { | 21 namespace ash { |
23 namespace internal { | 22 namespace internal { |
24 | 23 |
25 namespace { | 24 namespace { |
26 | 25 |
27 // The time in milliseconds which should be used to visually move a window | 26 // The time in milliseconds which should be used to visually move a window |
28 // through an automatic "intelligent" window management option. | 27 // through an automatic "intelligent" window management option. |
29 const int kWindowAutoMoveDurationMS = 125; | 28 const int kWindowAutoMoveDurationMS = 125; |
30 | 29 |
31 // Check if any management should be performed (with a given |window|). | 30 // Check if any management should be performed (with a given |window|). |
32 bool UseAutoWindowManager(const aura::Window* window) { | 31 bool UseAutoWindowManager(const aura::Window* window) { |
33 const wm::WindowSettings* settings = wm::GetWindowSettings(window); | 32 const wm::WindowState* window_state = wm::GetWindowState(window); |
34 return settings->tracked_by_workspace() && | 33 return window_state->tracked_by_workspace() && |
35 settings->window_position_managed(); | 34 window_state->window_position_managed(); |
36 } | 35 } |
37 | 36 |
38 // Check if a given |window| can be managed. This includes that it's state is | 37 // Check if a given |window| can be managed. This includes that it's state is |
39 // not minimized/maximized/the user has changed it's size by hand already. | 38 // not minimized/maximized/the user has changed it's size by hand already. |
40 // It furthermore checks for the WindowIsManaged status. | 39 // It furthermore checks for the WindowIsManaged status. |
41 bool WindowPositionCanBeManaged(const aura::Window* window) { | 40 bool WindowPositionCanBeManaged(const aura::Window* window) { |
42 const wm::WindowSettings* settings = wm::GetWindowSettings(window); | 41 const wm::WindowState* window_state = wm::GetWindowState(window); |
43 return settings->window_position_managed() && | 42 return window_state->window_position_managed() && |
44 !wm::IsWindowMinimized(window) && | 43 !window_state->IsMinimized() && |
45 !wm::IsWindowMaximized(window) && | 44 !window_state->IsMaximized() && |
46 !settings->bounds_changed_by_user(); | 45 !window_state->bounds_changed_by_user(); |
47 } | 46 } |
48 | 47 |
49 // Get the work area for a given |window| in parent coordinates. | 48 // Get the work area for a given |window| in parent coordinates. |
50 gfx::Rect GetWorkAreaForWindowInParent(aura::Window* window) { | 49 gfx::Rect GetWorkAreaForWindowInParent(aura::Window* window) { |
51 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
52 // On Win 8, the host window can't be resized, so | 51 // On Win 8, the host window can't be resized, so |
53 // use window's bounds instead. | 52 // use window's bounds instead. |
54 // TODO(oshima): Emulate host window resize on win8. | 53 // TODO(oshima): Emulate host window resize on win8. |
55 gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size()); | 54 gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size()); |
56 work_area.Inset(Shell::GetScreen()->GetDisplayMatching( | 55 work_area.Inset(Shell::GetScreen()->GetDisplayMatching( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | 96 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); |
98 window->SetBounds(bounds); | 97 window->SetBounds(bounds); |
99 } | 98 } |
100 | 99 |
101 // Move |window| into the center of the screen - or restore it to the previous | 100 // Move |window| into the center of the screen - or restore it to the previous |
102 // position. | 101 // position. |
103 void AutoPlaceSingleWindow(aura::Window* window, bool animated) { | 102 void AutoPlaceSingleWindow(aura::Window* window, bool animated) { |
104 gfx::Rect work_area = GetWorkAreaForWindowInParent(window); | 103 gfx::Rect work_area = GetWorkAreaForWindowInParent(window); |
105 gfx::Rect bounds = window->bounds(); | 104 gfx::Rect bounds = window->bounds(); |
106 const gfx::Rect* user_defined_area = | 105 const gfx::Rect* user_defined_area = |
107 ash::wm::GetPreAutoManageWindowBounds(window); | 106 wm::GetWindowState(window)->pre_auto_manage_window_bounds(); |
108 if (user_defined_area) { | 107 if (user_defined_area) { |
109 bounds = *user_defined_area; | 108 bounds = *user_defined_area; |
110 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area, &bounds); | 109 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area, &bounds); |
111 } else { | 110 } else { |
112 // Center the window (only in x). | 111 // Center the window (only in x). |
113 bounds.set_x(work_area.x() + (work_area.width() - bounds.width()) / 2); | 112 bounds.set_x(work_area.x() + (work_area.width() - bounds.width()) / 2); |
114 } | 113 } |
115 | 114 |
116 if (animated) | 115 if (animated) |
117 SetBoundsAnimated(window, bounds); | 116 SetBoundsAnimated(window, bounds); |
(...skipping 30 matching lines...) Expand all Loading... |
148 // (and so on). Note that we might cycle a few indices twice if there is no | 147 // (and so on). Note that we might cycle a few indices twice if there is no |
149 // suitable window. However - since the list is fairly small this should be | 148 // suitable window. However - since the list is fairly small this should be |
150 // very fast anyways. | 149 // very fast anyways. |
151 aura::Window* found = NULL; | 150 aura::Window* found = NULL; |
152 for (int i = index + windows.size(); i >= 0; i--) { | 151 for (int i = index + windows.size(); i >= 0; i--) { |
153 aura::Window* window = windows[i % windows.size()]; | 152 aura::Window* window = windows[i % windows.size()]; |
154 if (window != exclude && | 153 if (window != exclude && |
155 window->type() == aura::client::WINDOW_TYPE_NORMAL && | 154 window->type() == aura::client::WINDOW_TYPE_NORMAL && |
156 window->GetRootWindow() == root_window && | 155 window->GetRootWindow() == root_window && |
157 window->TargetVisibility() && | 156 window->TargetVisibility() && |
158 wm::GetWindowSettings(window)->window_position_managed()) { | 157 wm::GetWindowState(window)->window_position_managed()) { |
159 if (found && found != window) { | 158 if (found && found != window) { |
160 // no need to check !signle_window because the function must have | 159 // no need to check !signle_window because the function must have |
161 // been already returned in the "if (!single_window)" below. | 160 // been already returned in the "if (!single_window)" below. |
162 *single_window = false; | 161 *single_window = false; |
163 return found; | 162 return found; |
164 } | 163 } |
165 found = window; | 164 found = window; |
166 // If there is no need to check single window, return now. | 165 // If there is no need to check single window, return now. |
167 if (!single_window) | 166 if (!single_window) |
168 return found; | 167 return found; |
(...skipping 11 matching lines...) Expand all Loading... |
180 bool single_window; | 179 bool single_window; |
181 aura::Window* other_shown_window = GetReferenceWindow( | 180 aura::Window* other_shown_window = GetReferenceWindow( |
182 removed_window->GetRootWindow(), removed_window, &single_window); | 181 removed_window->GetRootWindow(), removed_window, &single_window); |
183 if (!other_shown_window || !single_window || | 182 if (!other_shown_window || !single_window || |
184 !WindowPositionCanBeManaged(other_shown_window)) | 183 !WindowPositionCanBeManaged(other_shown_window)) |
185 return; | 184 return; |
186 AutoPlaceSingleWindow(other_shown_window, true); | 185 AutoPlaceSingleWindow(other_shown_window, true); |
187 } | 186 } |
188 | 187 |
189 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { | 188 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { |
| 189 wm::WindowState* added_window_state = wm::GetWindowState(added_window); |
| 190 |
190 if (!UseAutoWindowManager(added_window) || | 191 if (!UseAutoWindowManager(added_window) || |
191 wm::GetWindowSettings(added_window)->bounds_changed_by_user() || | 192 added_window_state->bounds_changed_by_user() || |
192 !added_window->TargetVisibility()) | 193 !added_window->TargetVisibility()) |
193 return; | 194 return; |
194 // Find a single open managed window. | 195 // Find a single open managed window. |
195 bool single_window; | 196 bool single_window; |
196 aura::Window* other_shown_window = GetReferenceWindow( | 197 aura::Window* other_shown_window = GetReferenceWindow( |
197 added_window->GetRootWindow(), added_window, &single_window); | 198 added_window->GetRootWindow(), added_window, &single_window); |
198 | 199 |
199 if (!other_shown_window) { | 200 if (!other_shown_window) { |
200 // It could be that this window is the first window joining the workspace. | 201 // It could be that this window is the first window joining the workspace. |
201 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) | 202 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) |
202 return; | 203 return; |
203 // Since we might be going from 0 to 1 window, we have to arrange the new | 204 // Since we might be going from 0 to 1 window, we have to arrange the new |
204 // window to a good default. | 205 // window to a good default. |
205 AutoPlaceSingleWindow(added_window, false); | 206 AutoPlaceSingleWindow(added_window, false); |
206 return; | 207 return; |
207 } | 208 } |
208 | 209 |
209 gfx::Rect other_bounds = other_shown_window->bounds(); | 210 gfx::Rect other_bounds = other_shown_window->bounds(); |
210 gfx::Rect work_area = GetWorkAreaForWindowInParent(added_window); | 211 gfx::Rect work_area = GetWorkAreaForWindowInParent(added_window); |
211 bool move_other_right = | 212 bool move_other_right = |
212 other_bounds.CenterPoint().x() > work_area.x() + work_area.width() / 2; | 213 other_bounds.CenterPoint().x() > work_area.x() + work_area.width() / 2; |
213 | 214 |
214 // Push the other window to the size only if there are two windows left. | 215 // Push the other window to the size only if there are two windows left. |
215 if (single_window) { | 216 if (single_window) { |
216 // When going from one to two windows both windows loose their "positioned | 217 // When going from one to two windows both windows loose their |
217 // by user" flags. | 218 // "positioned by user" flags. |
218 wm::GetWindowSettings(added_window)->set_bounds_changed_by_user(false); | 219 added_window_state->set_bounds_changed_by_user(false); |
219 wm::GetWindowSettings(other_shown_window)-> | 220 wm::WindowState* other_window_state = |
220 set_bounds_changed_by_user(false); | 221 wm::GetWindowState(other_shown_window); |
| 222 other_window_state->set_bounds_changed_by_user(false); |
221 | 223 |
222 if (WindowPositionCanBeManaged(other_shown_window)) { | 224 if (WindowPositionCanBeManaged(other_shown_window)) { |
223 // Don't override pre auto managed bounds as the current bounds | 225 // Don't override pre auto managed bounds as the current bounds |
224 // may not be original. | 226 // may not be original. |
225 if (!ash::wm::GetPreAutoManageWindowBounds(other_shown_window)) | 227 if (!other_window_state->pre_auto_manage_window_bounds()) |
226 ash::wm::SetPreAutoManageWindowBounds(other_shown_window, other_bounds); | 228 other_window_state->SetPreAutoManageWindowBounds(other_bounds); |
227 | 229 |
228 // Push away the other window after remembering its current position. | 230 // Push away the other window after remembering its current position. |
229 if (MoveRectToOneSide(work_area, move_other_right, &other_bounds)) | 231 if (MoveRectToOneSide(work_area, move_other_right, &other_bounds)) |
230 SetBoundsAnimated(other_shown_window, other_bounds); | 232 SetBoundsAnimated(other_shown_window, other_bounds); |
231 } | 233 } |
232 } | 234 } |
233 | 235 |
234 // Remember the current location of the window if it's new and push | 236 // Remember the current location of the window if it's new and push |
235 // it also to the opposite location if needed. Since it is just | 237 // it also to the opposite location if needed. Since it is just |
236 // being shown, we do not need to animate it. | 238 // being shown, we do not need to animate it. |
237 gfx::Rect added_bounds = added_window->bounds(); | 239 gfx::Rect added_bounds = added_window->bounds(); |
238 if (!ash::wm::GetPreAutoManageWindowBounds(added_window)) | 240 if (!added_window_state->pre_auto_manage_window_bounds()) |
239 ash::wm::SetPreAutoManageWindowBounds(added_window, added_bounds); | 241 added_window_state->SetPreAutoManageWindowBounds(added_bounds); |
240 if (MoveRectToOneSide(work_area, !move_other_right, &added_bounds)) | 242 if (MoveRectToOneSide(work_area, !move_other_right, &added_bounds)) |
241 added_window->SetBounds(added_bounds); | 243 added_window->SetBounds(added_bounds); |
242 } | 244 } |
243 | 245 |
244 } // namespace internal | 246 } // namespace internal |
245 | 247 |
246 aura::Window* GetTopWindowForNewWindow(const aura::RootWindow* root_window) { | 248 aura::Window* GetTopWindowForNewWindow(const aura::RootWindow* root_window) { |
247 return internal::GetReferenceWindow(root_window, NULL, NULL); | 249 return internal::GetReferenceWindow(root_window, NULL, NULL); |
248 } | 250 } |
249 | 251 |
250 } // namespace ash | 252 } // namespace ash |
OLD | NEW |