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/shell.h" | 8 #include "ash/shell.h" |
9 #include "ash/wm/mru_window_tracker.h" | |
9 #include "ash/wm/property_util.h" | 10 #include "ash/wm/property_util.h" |
10 #include "ash/wm/window_animations.h" | 11 #include "ash/wm/window_animations.h" |
11 #include "ash/wm/window_util.h" | 12 #include "ash/wm/window_util.h" |
12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
13 #include "ui/aura/window.h" | 14 #include "ui/aura/window.h" |
14 #include "ui/aura/client/aura_constants.h" | 15 #include "ui/aura/client/aura_constants.h" |
15 #include "ui/compositor/layer_animator.h" | 16 #include "ui/compositor/layer_animator.h" |
16 #include "ui/compositor/scoped_layer_animation_settings.h" | 17 #include "ui/compositor/scoped_layer_animation_settings.h" |
17 #include "ui/gfx/screen.h" | 18 #include "ui/gfx/screen.h" |
18 | 19 |
(...skipping 15 matching lines...) Expand all Loading... | |
34 // Check if a given |window| can be managed. This includes that it's state is | 35 // Check if a given |window| can be managed. This includes that it's state is |
35 // not minimized/maximized/the user has changed it's size by hand already. | 36 // not minimized/maximized/the user has changed it's size by hand already. |
36 // It furthermore checks for the WindowIsManaged status. | 37 // It furthermore checks for the WindowIsManaged status. |
37 bool WindowPositionCanBeManaged(const aura::Window* window) { | 38 bool WindowPositionCanBeManaged(const aura::Window* window) { |
38 return (wm::IsWindowPositionManaged(window) && | 39 return (wm::IsWindowPositionManaged(window) && |
39 !wm::IsWindowMinimized(window) && | 40 !wm::IsWindowMinimized(window) && |
40 !wm::IsWindowMaximized(window) && | 41 !wm::IsWindowMaximized(window) && |
41 !wm::HasUserChangedWindowPositionOrSize(window)); | 42 !wm::HasUserChangedWindowPositionOrSize(window)); |
42 } | 43 } |
43 | 44 |
44 // Given a |window|, return the only |other_window| which has an impact on | |
45 // the automated windows location management. If there is more then one window, | |
46 // false is returned, but the |other_window| will be set to the first one | |
47 // found. | |
48 // If the return value is true a single window was found. | |
49 bool GetOtherVisibleAndManageableWindow(const aura::Window* window, | |
50 aura::Window** other_window) { | |
51 *other_window = NULL; | |
52 const aura::Window::Windows& windows = window->parent()->children(); | |
53 // Find a single open managed window. | |
54 for (size_t i = 0; i < windows.size(); i++) { | |
55 aura::Window* iterated_window = windows[i]; | |
56 if (window != iterated_window && | |
57 iterated_window->type() == aura::client::WINDOW_TYPE_NORMAL && | |
58 iterated_window->TargetVisibility() && | |
59 wm::IsWindowPositionManaged(iterated_window)) { | |
60 // Bail if we find a second usable window. | |
61 if (*other_window) | |
62 return false; | |
63 *other_window = iterated_window; | |
64 } | |
65 } | |
66 return *other_window != NULL; | |
67 } | |
68 | |
69 // Get the work area for a given |window|. | 45 // Get the work area for a given |window|. |
70 gfx::Rect GetWorkAreaForWindow(aura::Window* window) { | 46 gfx::Rect GetWorkAreaForWindow(aura::Window* window) { |
71 #if defined(OS_WIN) | 47 #if defined(OS_WIN) |
72 // On Win 8, the host window can't be resized, so | 48 // On Win 8, the host window can't be resized, so |
73 // use window's bounds instead. | 49 // use window's bounds instead. |
74 // TODO(oshima): Emulate host window resize on win8. | 50 // TODO(oshima): Emulate host window resize on win8. |
75 gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size()); | 51 gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size()); |
76 work_area.Inset(Shell::GetScreen()->GetDisplayMatching( | 52 work_area.Inset(Shell::GetScreen()->GetDisplayMatching( |
77 work_area).GetWorkAreaInsets()); | 53 work_area).GetWorkAreaInsets()); |
78 return work_area; | 54 return work_area; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 // Center the window (only in x). | 106 // Center the window (only in x). |
131 bounds.set_x((work_area.width() - bounds.width()) / 2); | 107 bounds.set_x((work_area.width() - bounds.width()) / 2); |
132 } | 108 } |
133 | 109 |
134 if (animated) | 110 if (animated) |
135 SetBoundsAnimated(window, bounds); | 111 SetBoundsAnimated(window, bounds); |
136 else | 112 else |
137 window->SetBounds(bounds); | 113 window->SetBounds(bounds); |
138 } | 114 } |
139 | 115 |
116 // Get the first open (non minimized) window which is on the screen defined. | |
117 aura::Window* GetReferenceWindow(const aura::RootWindow* root_window, | |
118 const aura::Window* exclude, | |
119 bool *single_window) { | |
120 if (single_window) | |
121 *single_window = true; | |
122 // Get the active window. | |
123 aura::Window* active = ash::wm::GetActiveWindow(); | |
124 if (active && active->GetRootWindow() != root_window) | |
125 active = NULL; | |
126 | |
127 // Get a list of all windows. | |
128 const std::vector<aura::Window*> windows = | |
sky
2013/08/29 19:33:31
Are you sure we want all windows here? It was my u
oshima
2013/08/29 19:49:52
They're excluded by IsWindowPositionManaged check.
| |
129 ash::MruWindowTracker::BuildWindowList(false); | |
130 | |
131 if (windows.empty()) | |
132 return NULL; | |
133 | |
134 aura::Window::Windows::const_iterator iter = windows.begin(); | |
135 // Find the index of the current active window. | |
136 if (active) | |
137 iter = std::find(windows.begin(), windows.end(), active); | |
138 | |
139 int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); | |
140 | |
141 // Scan the cycle list backwards to see which is the second topmost window | |
142 // (and so on). Note that we might cycle a few indices twice if there is no | |
143 // suitable window. However - since the list is fairly small this should be | |
144 // very fast anyways. | |
145 aura::Window* found = NULL; | |
146 for (int i = index + windows.size(); i >= 0; i--) { | |
147 aura::Window* window = windows[i % windows.size()]; | |
148 if (window != exclude && | |
149 window->type() == aura::client::WINDOW_TYPE_NORMAL && | |
150 window->GetRootWindow() == root_window && | |
151 window->TargetVisibility() && | |
152 wm::IsWindowPositionManaged(window)) { | |
153 if (found && found != window) { | |
154 // no need to check !signle_window because the function must have | |
sky
2013/08/29 20:18:09
single_window
oshima
2013/08/29 20:48:05
Done.
| |
155 // been already returned in the "if (!single_window)" below. | |
156 *single_window = false; | |
157 return found; | |
158 } | |
159 found = window; | |
160 // If there is no need to check single window, return now. | |
161 if (!single_window) | |
162 return found; | |
163 } | |
164 } | |
165 return found; | |
166 } | |
167 | |
140 } // namespace | 168 } // namespace |
141 | 169 |
142 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) { | 170 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) { |
143 if (!UseAutoWindowManager(removed_window)) | 171 if (!UseAutoWindowManager(removed_window)) |
144 return; | 172 return; |
145 // Find a single open browser window. | 173 // Find a single open browser window. |
146 aura::Window* other_shown_window = NULL; | 174 bool single_window; |
147 if (!GetOtherVisibleAndManageableWindow(removed_window, | 175 aura::Window* other_shown_window = GetReferenceWindow( |
148 &other_shown_window) || | 176 removed_window->GetRootWindow(), removed_window, &single_window); |
177 if (!other_shown_window || !single_window || | |
149 !WindowPositionCanBeManaged(other_shown_window)) | 178 !WindowPositionCanBeManaged(other_shown_window)) |
150 return; | 179 return; |
151 AutoPlaceSingleWindow(other_shown_window, true); | 180 AutoPlaceSingleWindow(other_shown_window, true); |
152 } | 181 } |
153 | 182 |
154 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { | 183 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { |
155 if (!UseAutoWindowManager(added_window) || | 184 if (!UseAutoWindowManager(added_window) || |
156 wm::HasUserChangedWindowPositionOrSize(added_window) || | 185 wm::HasUserChangedWindowPositionOrSize(added_window) || |
157 !added_window->TargetVisibility()) | 186 !added_window->TargetVisibility()) |
158 return; | 187 return; |
159 // Find a single open managed window. | 188 // Find a single open managed window. |
160 aura::Window* other_shown_window = NULL; | 189 bool single_window; |
161 if (!GetOtherVisibleAndManageableWindow(added_window, | 190 aura::Window* other_shown_window = GetReferenceWindow( |
162 &other_shown_window)) { | 191 added_window->GetRootWindow(), added_window, &single_window); |
192 | |
193 if (!other_shown_window) { | |
163 // It could be that this window is the first window joining the workspace. | 194 // It could be that this window is the first window joining the workspace. |
164 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) | 195 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) |
165 return; | 196 return; |
166 // Since we might be going from 0 to 1 window, we have to arrange the new | 197 // Since we might be going from 0 to 1 window, we have to arrange the new |
167 // window to a good default. | 198 // window to a good default. |
168 AutoPlaceSingleWindow(added_window, false); | 199 AutoPlaceSingleWindow(added_window, false); |
169 return; | 200 return; |
170 } | 201 } |
171 | 202 |
172 // When going from one to two windows both windows loose their "positioned | 203 gfx::Rect other_bounds = other_shown_window->bounds(); |
173 // by user" flags. | 204 gfx::Rect work_area = GetWorkAreaForWindow(added_window); |
174 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false); | 205 bool move_other_right = |
175 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false); | 206 other_bounds.CenterPoint().x() > work_area.width() / 2; |
176 | 207 |
177 if (WindowPositionCanBeManaged(other_shown_window)) { | 208 // Push the other window to the size only if there are two windows left. |
178 gfx::Rect work_area = GetWorkAreaForWindow(added_window); | 209 if (single_window) { |
210 // When going from one to two windows both windows loose their "positioned | |
211 // by user" flags. | |
212 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false); | |
213 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false); | |
179 | 214 |
180 // Push away the other window after remembering its current position. | 215 if (WindowPositionCanBeManaged(other_shown_window)) { |
181 gfx::Rect other_bounds = other_shown_window->bounds(); | 216 // Don't override pre auto managed bounds as the current bounds |
182 ash::wm::SetPreAutoManageWindowBounds(other_shown_window, other_bounds); | 217 // may not be original. |
218 if (!ash::wm::GetPreAutoManageWindowBounds(other_shown_window)) | |
219 ash::wm::SetPreAutoManageWindowBounds(other_shown_window, other_bounds); | |
183 | 220 |
184 bool move_right = other_bounds.CenterPoint().x() > work_area.width() / 2; | 221 // Push away the other window after remembering its current position. |
185 if (MoveRectToOneSide(work_area.width(), move_right, &other_bounds)) | 222 if (MoveRectToOneSide(work_area.width(), move_other_right, &other_bounds)) |
186 SetBoundsAnimated(other_shown_window, other_bounds); | 223 SetBoundsAnimated(other_shown_window, other_bounds); |
224 } | |
225 } | |
187 | 226 |
188 // Remember the current location of the new window and push it also to the | 227 // Remember the current location of the window if it's new and push |
189 // opposite location (if needed). | 228 // it also to the opposite location if needed. Since it is just |
190 // Since it is just coming into view, we do not need to animate it. | 229 // being shown, we do not need to animate it. |
191 gfx::Rect added_bounds = added_window->bounds(); | 230 gfx::Rect added_bounds = added_window->bounds(); |
231 if (!ash::wm::GetPreAutoManageWindowBounds(added_window)) | |
192 ash::wm::SetPreAutoManageWindowBounds(added_window, added_bounds); | 232 ash::wm::SetPreAutoManageWindowBounds(added_window, added_bounds); |
193 if (MoveRectToOneSide(work_area.width(), !move_right, &added_bounds)) | 233 if (MoveRectToOneSide(work_area.width(), !move_other_right, &added_bounds)) |
194 added_window->SetBounds(added_bounds); | 234 added_window->SetBounds(added_bounds); |
195 } | |
196 } | 235 } |
197 | 236 |
198 } // namespace internal | 237 } // namespace internal |
238 | |
239 aura::Window* GetTopWindowForNewWindow(const aura::RootWindow* root_window) { | |
240 return internal::GetReferenceWindow(root_window, NULL, NULL); | |
241 } | |
242 | |
199 } // namespace ash | 243 } // namespace ash |
OLD | NEW |