Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: ash/wm/workspace/auto_window_management.cc

Issue 23205027: Correctly restore the auto managed window to the original bounds when becoming single window (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/wm/workspace/auto_window_management.h ('k') | ash/wm/workspace_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « ash/wm/workspace/auto_window_management.h ('k') | ash/wm/workspace_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698