Chromium Code Reviews| 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 = | |
| 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) { | |
|
Mr4D (OOO till 08-26)
2013/08/28 21:58:15
Please add here a comment why if (single_window) i
oshima
2013/08/29 09:18:04
Done.
| |
| 154 *single_window = false; | |
| 155 return found; | |
| 156 } | |
| 157 found = window; | |
| 158 // If there is no need to check single window, return now. | |
| 159 if (!single_window) | |
| 160 return found; | |
| 161 } | |
| 162 } | |
| 163 return found; | |
| 164 } | |
| 165 | |
| 140 } // namespace | 166 } // namespace |
| 141 | 167 |
| 142 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) { | 168 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) { |
| 143 if (!UseAutoWindowManager(removed_window)) | 169 if (!UseAutoWindowManager(removed_window)) |
| 144 return; | 170 return; |
| 145 // Find a single open browser window. | 171 // Find a single open browser window. |
| 146 aura::Window* other_shown_window = NULL; | 172 bool single_window; |
| 147 if (!GetOtherVisibleAndManageableWindow(removed_window, | 173 aura::Window* other_shown_window = GetReferenceWindow( |
| 148 &other_shown_window) || | 174 removed_window->GetRootWindow(), removed_window, &single_window); |
| 175 if (!other_shown_window || !single_window || | |
| 149 !WindowPositionCanBeManaged(other_shown_window)) | 176 !WindowPositionCanBeManaged(other_shown_window)) |
| 150 return; | 177 return; |
| 151 AutoPlaceSingleWindow(other_shown_window, true); | 178 AutoPlaceSingleWindow(other_shown_window, true); |
| 152 } | 179 } |
| 153 | 180 |
| 154 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { | 181 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { |
| 155 if (!UseAutoWindowManager(added_window) || | 182 if (!UseAutoWindowManager(added_window) || |
| 156 wm::HasUserChangedWindowPositionOrSize(added_window) || | 183 wm::HasUserChangedWindowPositionOrSize(added_window) || |
| 157 !added_window->TargetVisibility()) | 184 !added_window->TargetVisibility()) |
| 158 return; | 185 return; |
| 159 // Find a single open managed window. | 186 // Find a single open managed window. |
| 160 aura::Window* other_shown_window = NULL; | 187 bool single_window; |
| 161 if (!GetOtherVisibleAndManageableWindow(added_window, | 188 aura::Window* other_shown_window = GetReferenceWindow( |
| 162 &other_shown_window)) { | 189 added_window->GetRootWindow(), added_window, &single_window); |
| 190 | |
| 191 if (!other_shown_window) { | |
| 163 // It could be that this window is the first window joining the workspace. | 192 // It could be that this window is the first window joining the workspace. |
| 164 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) | 193 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) |
| 165 return; | 194 return; |
| 166 // Since we might be going from 0 to 1 window, we have to arrange the new | 195 // Since we might be going from 0 to 1 window, we have to arrange the new |
| 167 // window to a good default. | 196 // window to a good default. |
| 168 AutoPlaceSingleWindow(added_window, false); | 197 AutoPlaceSingleWindow(added_window, false); |
| 169 return; | 198 return; |
| 170 } | 199 } |
| 171 | 200 |
| 172 // When going from one to two windows both windows loose their "positioned | 201 gfx::Rect other_bounds = other_shown_window->bounds(); |
| 173 // by user" flags. | 202 gfx::Rect work_area = GetWorkAreaForWindow(added_window); |
| 174 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false); | 203 bool move_other_right = |
| 175 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false); | 204 other_bounds.CenterPoint().x() > work_area.width() / 2; |
| 176 | 205 |
| 177 if (WindowPositionCanBeManaged(other_shown_window)) { | 206 // Push the other window to the size only if there are two windows left. |
| 178 gfx::Rect work_area = GetWorkAreaForWindow(added_window); | 207 if (single_window) { |
| 208 // When going from one to two windows both windows loose their "positioned | |
| 209 // by user" flags. | |
| 210 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false); | |
| 211 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false); | |
| 179 | 212 |
| 180 // Push away the other window after remembering its current position. | 213 if (WindowPositionCanBeManaged(other_shown_window)) { |
| 181 gfx::Rect other_bounds = other_shown_window->bounds(); | 214 // Don't override pre audo managed bounds as the current bounds |
|
Mr4D (OOO till 08-26)
2013/08/28 21:58:15
audo -> auto
oshima
2013/08/29 09:18:04
Done.
| |
| 182 ash::wm::SetPreAutoManageWindowBounds(other_shown_window, other_bounds); | 215 // may not be original. |
| 216 if (!ash::wm::GetPreAutoManageWindowBounds(other_shown_window)) | |
| 217 ash::wm::SetPreAutoManageWindowBounds(other_shown_window, other_bounds); | |
| 183 | 218 |
| 184 bool move_right = other_bounds.CenterPoint().x() > work_area.width() / 2; | 219 // Push away the other window after remembering its current position. |
| 185 if (MoveRectToOneSide(work_area.width(), move_right, &other_bounds)) | 220 if (MoveRectToOneSide(work_area.width(), move_other_right, &other_bounds)) |
| 186 SetBoundsAnimated(other_shown_window, other_bounds); | 221 SetBoundsAnimated(other_shown_window, other_bounds); |
| 222 } | |
| 223 } | |
| 187 | 224 |
| 188 // Remember the current location of the new window and push it also to the | 225 // Remember the current location of the window if it's new and push |
| 189 // opposite location (if needed). | 226 // 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. | 227 // being shown, we do not need to animate it. |
| 191 gfx::Rect added_bounds = added_window->bounds(); | 228 gfx::Rect added_bounds = added_window->bounds(); |
| 229 if (!ash::wm::GetPreAutoManageWindowBounds(added_window)) | |
| 192 ash::wm::SetPreAutoManageWindowBounds(added_window, added_bounds); | 230 ash::wm::SetPreAutoManageWindowBounds(added_window, added_bounds); |
| 193 if (MoveRectToOneSide(work_area.width(), !move_right, &added_bounds)) | 231 if (MoveRectToOneSide(work_area.width(), !move_other_right, &added_bounds)) |
| 194 added_window->SetBounds(added_bounds); | 232 added_window->SetBounds(added_bounds); |
| 195 } | |
| 196 } | 233 } |
| 197 | 234 |
| 198 } // namespace internal | 235 } // namespace internal |
| 236 | |
| 237 aura::Window* GetTopWindowForNewWindow(const aura::RootWindow* root_window) { | |
| 238 return internal::GetReferenceWindow(root_window, NULL, NULL); | |
| 239 } | |
| 240 | |
| 199 } // namespace ash | 241 } // namespace ash |
| OLD | NEW |