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

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: 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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698