OLD | NEW |
---|---|
(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/window_animations.h" | |
10 #include "ash/wm/window_util.h" | |
11 #include "base/command_line.h" | |
12 #include "ui/aura/window.h" | |
13 #include "ui/aura/client/aura_constants.h" | |
14 #include "ui/compositor/layer_animator.h" | |
15 #include "ui/compositor/scoped_layer_animation_settings.h" | |
16 #include "ui/gfx/screen.h" | |
17 | |
18 namespace ash { | |
19 namespace internal { | |
20 | |
21 namespace { | |
22 | |
23 // The time in milliseconds which should be used to visually move a window | |
24 // through an automatic "intelligent" window management option. | |
25 const int kWindowAutoMoveDurationMS = 125; | |
26 | |
27 // Check if the given |window| is marked to get managed. | |
28 bool WindowIsManaged(const aura::Window* window) { | |
29 return (!window->bounds().IsEmpty() && wm::IsWindowPositionManaged(window)); | |
sky
2012/10/18 16:36:10
What made you add the !IsEmpty() check? Is there r
Mr4D (OOO till 08-26)
2012/10/19 20:46:05
Think about this: Suddenly your window moves to th
sky
2012/10/19 22:00:32
I'm reminded of your comment earlier today about A
Mr4D (OOO till 08-26)
2012/10/19 22:54:41
I don't think that the example fits here. This cod
| |
30 } | |
31 | |
32 // Check if a given |window| can be managed. This includes that it's state is | |
33 // not minimized/maximized/the user has changed it's size by hand already. | |
34 // It furthermore checks for the WindowIsManaged status. | |
35 bool WindowPositionCanBeManaged(const aura::Window* window) { | |
36 return (WindowIsManaged(window) && | |
37 !wm::IsWindowMinimized(window) && | |
38 !wm::IsWindowMaximized(window) && | |
39 !wm::HasUserChangedWindowPositionOrSize(window)); | |
40 } | |
41 | |
42 // Given a |window|, return the |work_area| of the desktop on which it is | |
43 // located as well as the only |other_window| which has an impact on the | |
44 // automated window location management. If there is more then one windows, | |
sky
2012/10/18 16:36:10
windows -> window
Mr4D (OOO till 08-26)
2012/10/19 20:46:05
Done.
| |
45 // false is returned, but the |other_window| will be set to the first one | |
46 // found. | |
47 // If the return value is true a single window was found. | |
48 // Note: |work_area| is undefined if false is returned and |other_window| is | |
49 // NULL. | |
50 bool GetOtherVisibleAndManageableWindow(const aura::Window* window, | |
51 gfx::Rect* work_area, | |
52 aura::Window** other_window) { | |
53 *other_window = NULL; | |
54 // If the given window was not manageable, it cannot have caused a management | |
55 // operation earlier. | |
56 if (!WindowIsManaged(window)) | |
57 return false; | |
58 | |
59 // Get our work area. | |
60 *work_area = gfx::Rect(window->parent()->bounds().size()); | |
61 work_area->Inset(Shell::GetScreen()->GetDisplayMatching( | |
62 *work_area).GetWorkAreaInsets()); | |
63 | |
64 const aura::Window::Windows& windows = window->parent()->children(); | |
65 // Find a single open managed window. | |
66 for (size_t i = 0; i < windows.size(); i++) { | |
67 aura::Window* iterated_window = windows[i]; | |
68 if (window != iterated_window && | |
69 iterated_window->type() == aura::client::WINDOW_TYPE_NORMAL && | |
70 iterated_window->TargetVisibility() && | |
71 WindowIsManaged(iterated_window)) { | |
72 // Bail if we find a second usable window. | |
73 if (*other_window) | |
74 return false; | |
75 *other_window = iterated_window; | |
76 } | |
77 } | |
78 return *other_window != NULL; | |
79 } | |
80 | |
81 // Move the given |bounds| on the available |parent_width| to the | |
82 // direction. If |move_right| is true, the rectangle gets moved to the right | |
83 // corner, otherwise to the left one. | |
84 bool MoveRectToOneSide(int parent_width, bool move_right, gfx::Rect* bounds) { | |
85 if (move_right) { | |
86 if (parent_width > bounds->right()) { | |
87 bounds->set_x(parent_width - bounds->width()); | |
88 return true; | |
89 } | |
90 } else { | |
91 if (0 < bounds->x()) { | |
92 bounds->set_x(0); | |
93 return true; | |
94 } | |
95 } | |
96 return false; | |
97 } | |
98 | |
99 } // namespace | |
100 | |
101 void RearrangeVisibleWindowOnHide(const aura::Window* removed_window) { | |
102 // Find a single open browser window. | |
103 aura::Window* other_shown_window = NULL; | |
104 gfx::Rect work_area; | |
105 if (!GetOtherVisibleAndManageableWindow(removed_window, | |
106 &work_area, | |
107 &other_shown_window)) | |
108 return; | |
109 | |
110 if (WindowPositionCanBeManaged(other_shown_window)) { | |
111 // Center the window (only in x). | |
112 gfx::Rect bounds = other_shown_window->bounds(); | |
113 bounds.set_x((work_area.width() - bounds.width()) / 2); | |
114 if (bounds != other_shown_window->bounds()) { | |
sky
2012/10/18 16:36:10
Do you really need the bounds != bounds check here
Mr4D (OOO till 08-26)
2012/10/19 20:46:05
You told me to add this because otherwise I might
sky
2012/10/19 22:00:32
Remember bounds is the current bounds. If you real
Mr4D (OOO till 08-26)
2012/10/19 22:54:41
That answers that question I had in my back of my
| |
115 if (!other_shown_window->GetProperty( | |
sky
2012/10/18 16:36:10
Simplify this by creating a function like:
base::
sky
2012/10/18 23:47:14
The other approach that avoids unnecessary allocat
Mr4D (OOO till 08-26)
2012/10/19 22:54:41
Done.
| |
116 aura::client::kAnimationsDisabledKey) && | |
117 !CommandLine::ForCurrentProcess()->HasSwitch( | |
118 ash::switches::kAshWindowAnimationsDisabled)) { | |
119 ui::LayerAnimator* animator = | |
120 other_shown_window->layer()->GetAnimator(); | |
121 ui::ScopedLayerAnimationSettings animation_setter(animator); | |
122 animation_setter.SetTransitionDuration( | |
123 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | |
124 // SetBounds needs to be in this closure, so don't combine with the | |
125 // else case. | |
126 other_shown_window->SetBounds(bounds); | |
127 } else | |
128 other_shown_window->SetBounds(bounds); | |
129 } | |
130 } | |
131 } | |
132 | |
133 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { | |
134 // Early bail out if the window isn't visible. | |
135 if (!added_window->TargetVisibility()) | |
136 return; | |
137 // Find a single open managed window. | |
138 aura::Window* other_shown_window = NULL; | |
139 gfx::Rect work_area; | |
140 if (!GetOtherVisibleAndManageableWindow(added_window, | |
141 &work_area, | |
142 &other_shown_window)) { | |
143 // It could be that this window is the first window joining the workspace. | |
144 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) | |
145 return; | |
146 // If so we have to make sure it is centered. | |
147 gfx::Rect bounds = added_window->bounds(); | |
148 bounds.set_x((work_area.width() - bounds.width()) / 2); | |
149 added_window->SetBounds(bounds); | |
150 return; | |
151 } | |
152 | |
153 if (WindowPositionCanBeManaged(other_shown_window)) { | |
154 // Push away the other window. | |
155 gfx::Rect other_bounds = other_shown_window->bounds(); | |
156 bool move_right = other_bounds.CenterPoint().x() < work_area.width() / 2; | |
157 if (MoveRectToOneSide(work_area.width(), move_right, &other_bounds)) { | |
158 if (other_bounds != other_shown_window->bounds()) { | |
159 if (!other_shown_window->GetProperty( | |
160 aura::client::kAnimationsDisabledKey) && | |
161 !CommandLine::ForCurrentProcess()->HasSwitch( | |
162 ash::switches::kAshWindowAnimationsDisabled)) { | |
163 ui::LayerAnimator* animator = | |
164 other_shown_window->layer()->GetAnimator(); | |
165 ui::ScopedLayerAnimationSettings animation_setter(animator); | |
166 animation_setter.SetTransitionDuration( | |
167 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | |
168 // SetBounds needs to be in this closure, so don't combine with the | |
169 // else case. | |
170 other_shown_window->SetBounds(other_bounds); | |
171 } else | |
172 other_shown_window->SetBounds(other_bounds); | |
173 } | |
174 } | |
175 // Push the new window also to the opposite location (if needed). | |
176 // Since it is just coming into view, we do not need to animate it. | |
177 gfx::Rect added_bounds = added_window->bounds(); | |
178 if (MoveRectToOneSide(work_area.width(), !move_right, &added_bounds)) | |
179 added_window->SetBounds(added_bounds); | |
180 } | |
181 } | |
182 | |
183 } // namespace internal | |
184 } // namespace ash | |
185 | |
OLD | NEW |