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

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

Issue 11085053: Improving window auto management between workspaces (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: No auto movement for tab dragging Created 8 years, 2 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
OLDNEW
(Empty)
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/workspace/auto_window_management.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/shell.h"
9 #include "ash/wm/property_util.h"
10 #include "ash/wm/window_animations.h"
11 #include "ash/wm/window_util.h"
12 #include "base/command_line.h"
13 #include "ui/aura/window.h"
14 #include "ui/aura/client/aura_constants.h"
15 #include "ui/compositor/layer_animator.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h"
17 #include "ui/gfx/screen.h"
18
19 namespace ash {
20 namespace internal {
21
22 namespace {
23
24 // The time in milliseconds which should be used to visually move a window
25 // through an automatic "intelligent" window management option.
26 const int kWindowAutoMoveDurationMS = 125;
27
28 // Check if the given |window| is marked to get managed.
29 bool WindowIsManaged(const aura::Window* window) {
30 return wm::IsWindowPositionManaged(window);
31 }
32
33 // Check if a given |window| can be managed. This includes that it's state is
34 // not minimized/maximized/the user has changed it's size by hand already.
35 // It furthermore checks for the WindowIsManaged status.
36 bool WindowPositionCanBeManaged(const aura::Window* window) {
37 return (WindowIsManaged(window) &&
38 !wm::IsWindowMinimized(window) &&
39 !wm::IsWindowMaximized(window) &&
40 !wm::HasUserChangedWindowPositionOrSize(window));
41 }
42
43 // Given a |window|, return the |work_area| of the desktop on which it is
44 // located as well as the only |other_window| which has an impact on the
45 // 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 // If the given window was not manageable, it cannot have caused a management
53 // operation earlier.
54 if (!WindowIsManaged(window))
55 return false;
56
57 const aura::Window::Windows& windows = window->parent()->children();
58 // Find a single open managed window.
59 for (size_t i = 0; i < windows.size(); i++) {
60 aura::Window* iterated_window = windows[i];
61 if (window != iterated_window &&
62 iterated_window->type() == aura::client::WINDOW_TYPE_NORMAL &&
63 iterated_window->TargetVisibility() &&
64 WindowIsManaged(iterated_window)) {
65 // Bail if we find a second usable window.
66 if (*other_window)
67 return false;
68 *other_window = iterated_window;
69 }
70 }
71 return *other_window != NULL;
72 }
73
74 // Get the work area for a given |window|.
75 gfx::Rect GetWorkAreaForWindow(const aura::Window* window) {
76 gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size());
77 work_area.Inset(Shell::GetScreen()->GetDisplayMatching(
78 work_area).GetWorkAreaInsets());
79 return work_area;
80 }
81
82 // Move the given |bounds| on the available |parent_width| to the
83 // direction. If |move_right| is true, the rectangle gets moved to the right
84 // corner, otherwise to the left one.
85 bool MoveRectToOneSide(int parent_width, bool move_right, gfx::Rect* bounds) {
86 if (move_right) {
87 if (parent_width > bounds->right()) {
88 bounds->set_x(parent_width - bounds->width());
89 return true;
90 }
91 } else {
92 if (0 < bounds->x()) {
93 bounds->set_x(0);
94 return true;
95 }
96 }
97 return false;
98 }
99
100 // Move a |window| to a new |bound|. Animate if desired by user.
101 // Note: The function will do nothing if the bounds did not change.
102 void SetBoundsAnimated(aura::Window* window, const gfx::Rect& bounds) {
103 if (bounds == window->GetTargetBounds())
104 return;
105
106 if (window->GetProperty(aura::client::kAnimationsDisabledKey) ||
107 CommandLine::ForCurrentProcess()->HasSwitch(
108 ash::switches::kAshWindowAnimationsDisabled)) {
109 window->SetBounds(bounds);
110 return;
111 }
112
113 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
114 settings.SetTransitionDuration(
115 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS));
116 window->SetBounds(bounds);
117 }
118
119 } // namespace
120
121 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) {
122 // If the window isn't visible it was just added. Invisible windows have no
123 // effect on auto window management.
124 // Tab dragging windows get ignored as well.
125 if (CommandLine::ForCurrentProcess()->HasSwitch(
126 switches::kAshDisableAutoWindowPlacement) ||
127 !GetTrackedByWorkspace(removed_window) ||
128 wm::HasUserChangedWindowPositionOrSize(removed_window))
129 return;
130 // Find a single open browser window.
131 aura::Window* other_shown_window = NULL;
132 if (!GetOtherVisibleAndManageableWindow(removed_window,
133 &other_shown_window) ||
134 !WindowPositionCanBeManaged(other_shown_window))
135 return;
136
137 // Center the window (only in x).
138 gfx::Rect work_area = GetWorkAreaForWindow(removed_window);
139 gfx::Rect bounds = other_shown_window->bounds();
140 bounds.set_x((work_area.width() - bounds.width()) / 2);
141 SetBoundsAnimated(other_shown_window, bounds);
142 }
143
144 void RearrangeVisibleWindowOnShow(aura::Window* added_window) {
145 // If the window isn't visible it was just added. Invisible windows have no
146 // effect on auto window management.
147 // Tab dragging windows get ignored as well.
148 if (!added_window->TargetVisibility() ||
149 !GetTrackedByWorkspace(added_window) ||
150 CommandLine::ForCurrentProcess()->HasSwitch(
sky 2012/10/23 19:35:39 Instead of sprinkling checks for the switch have a
Mr4D (OOO till 08-26) 2012/10/24 16:41:37 I had exactly that at the beginning: GetOtherVisib
151 switches::kAshDisableAutoWindowPlacement))
152 return;
153 // Find a single open managed window.
154 aura::Window* other_shown_window = NULL;
155 if (!GetOtherVisibleAndManageableWindow(added_window,
156 &other_shown_window)) {
157 // It could be that this window is the first window joining the workspace.
158 if (!WindowPositionCanBeManaged(added_window) || other_shown_window)
159 return;
160
161 // If so we have to make sure it is centered.
162 gfx::Rect work_area = GetWorkAreaForWindow(added_window);
163 gfx::Rect bounds = added_window->bounds();
164 bounds.set_x((work_area.width() - bounds.width()) / 2);
165 added_window->SetBounds(bounds);
166 return;
167 }
168
169 // When going from one to two windows both windows loose their "positioned
170 // by user" flags.
171 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false);
172 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false);
173
174 if (WindowPositionCanBeManaged(other_shown_window)) {
175 gfx::Rect work_area = GetWorkAreaForWindow(added_window);
176
177 // Push away the other window.
178 gfx::Rect other_bounds = other_shown_window->bounds();
179 bool move_right = other_bounds.CenterPoint().x() < work_area.width() / 2;
180 if (MoveRectToOneSide(work_area.width(), move_right, &other_bounds))
181 SetBoundsAnimated(other_shown_window, other_bounds);
182
183 // Push the new window also to the opposite location (if needed).
184 // Since it is just coming into view, we do not need to animate it.
185 gfx::Rect added_bounds = added_window->bounds();
186 if (MoveRectToOneSide(work_area.width(), !move_right, &added_bounds))
187 added_window->SetBounds(added_bounds);
188 }
189 }
190
191 } // namespace internal
192 } // namespace ash
193
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698