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

Side by Side Diff: ui/aura_shell/workspace/workspace.cc

Issue 9035001: Move some more WM functionality down into ash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 12 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 | « ui/aura_shell/workspace/workspace.h ('k') | ui/aura_shell/workspace/workspace_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "ui/aura_shell/workspace/workspace.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "ui/aura/client/aura_constants.h"
11 #include "ui/aura/root_window.h"
12 #include "ui/aura/window.h"
13 #include "ui/aura_shell/property_util.h"
14 #include "ui/aura_shell/window_util.h"
15 #include "ui/aura_shell/workspace/workspace_manager.h"
16 #include "ui/base/ui_base_types.h"
17 #include "ui/gfx/compositor/layer.h"
18 #include "ui/gfx/compositor/layer_animator.h"
19
20 namespace {
21 // Horizontal margin between windows.
22 const int kWindowHorizontalMargin = 10;
23
24 // Maximum number of windows a workspace can have.
25 size_t g_max_windows_per_workspace = 2;
26
27 // Returns the bounds of the window that should be used to calculate
28 // the layout. It uses the restore bounds if exits, or
29 // the target bounds of the window. The target bounds is the
30 // final destination of |window| if the window's layer is animating,
31 // or the current bounds of the window of no animation is currently
32 // in progress.
33 gfx::Rect GetLayoutBounds(aura::Window* window) {
34 const gfx::Rect* restore_bounds = aura_shell::GetRestoreBounds(window);
35 return restore_bounds ? *restore_bounds : window->GetTargetBounds();
36 }
37
38 // Returns the width of the window that should be used to calculate
39 // the layout. See |GetLayoutBounds| for more details.
40 int GetLayoutWidth(aura::Window* window) {
41 return GetLayoutBounds(window).width();
42 }
43
44 } // namespace
45
46 namespace aura_shell {
47 namespace internal {
48
49 Workspace::Workspace(WorkspaceManager* manager)
50 : workspace_manager_(manager) {
51 workspace_manager_->AddWorkspace(this);
52 }
53
54 Workspace::~Workspace() {
55 workspace_manager_->RemoveWorkspace(this);
56 }
57
58 void Workspace::SetBounds(const gfx::Rect& bounds) {
59 bool bounds_changed = bounds_ != bounds;
60 bounds_ = bounds;
61 if (bounds_changed)
62 Layout(NULL);
63 }
64
65 gfx::Rect Workspace::GetWorkAreaBounds() const {
66 return workspace_manager_->GetWorkAreaBounds(bounds_);
67 }
68
69 bool Workspace::AddWindowAfter(aura::Window* window, aura::Window* after) {
70 if (!CanAdd(window))
71 return false;
72 DCHECK(!Contains(window));
73
74 if (!after) { // insert at the end.
75 windows_.push_back(window);
76 } else {
77 DCHECK(Contains(after));
78 aura::Window::Windows::iterator i =
79 std::find(windows_.begin(), windows_.end(), after);
80 windows_.insert(++i, window);
81 }
82 Layout(window);
83
84 return true;
85 }
86
87 void Workspace::RemoveWindow(aura::Window* window) {
88 DCHECK(Contains(window));
89 windows_.erase(std::find(windows_.begin(), windows_.end(), window));
90 Layout(NULL);
91 }
92
93 bool Workspace::Contains(aura::Window* window) const {
94 return std::find(windows_.begin(), windows_.end(), window) != windows_.end();
95 }
96
97 aura::Window* Workspace::FindRotateWindowForLocation(
98 const gfx::Point& position) {
99 aura::Window* active = aura_shell::GetActiveWindow();
100 if (GetTotalWindowsWidth() < bounds_.width()) {
101 // If all windows fit to the width of the workspace, it returns the
102 // window which contains |position|'s x coordinate.
103 for (aura::Window::Windows::const_iterator i = windows_.begin();
104 i != windows_.end();
105 ++i) {
106 if (active == *i)
107 continue;
108 gfx::Rect bounds = (*i)->GetTargetBounds();
109 if (bounds.x() < position.x() && position.x() < bounds.right())
110 return *i;
111 }
112 } else if (bounds_.x() < position.x() && position.x() < bounds_.right()) {
113 // If windows are overlapping, it divides the workspace into
114 // regions with the same width, and returns the Nth window that
115 // corresponds to the region that contains the |position|.
116 int width = bounds_.width() / windows_.size();
117 size_t index = (position.x() - bounds_.x()) / width;
118 DCHECK(index < windows_.size());
119 aura::Window* window = windows_[index];
120 if (window != active)
121 return window;
122 }
123 return NULL;
124 }
125
126 void Workspace::RotateWindows(aura::Window* source, aura::Window* target) {
127 DCHECK(Contains(source));
128 DCHECK(Contains(target));
129 aura::Window::Windows::iterator source_iter =
130 std::find(windows_.begin(), windows_.end(), source);
131 aura::Window::Windows::iterator target_iter =
132 std::find(windows_.begin(), windows_.end(), target);
133 DCHECK(source_iter != target_iter);
134 if (source_iter < target_iter)
135 std::rotate(source_iter, source_iter + 1, target_iter + 1);
136 else
137 std::rotate(target_iter, source_iter, source_iter + 1);
138 Layout(NULL);
139 }
140
141 aura::Window* Workspace::ShiftWindows(aura::Window* insert,
142 aura::Window* until,
143 aura::Window* target,
144 ShiftDirection direction) {
145 DCHECK(until);
146 DCHECK(!Contains(insert));
147
148 bool shift_reached_until = GetIndexOf(until) >= 0;
149 if (shift_reached_until) {
150 // Calling RemoveWindow here causes the animation set in Layout below
151 // to be ignored. See crbug.com/102413.
152 windows_.erase(std::find(windows_.begin(), windows_.end(), until));
153 }
154 aura::Window* pushed = NULL;
155 if (direction == SHIFT_TO_RIGHT) {
156 aura::Window::Windows::iterator iter =
157 std::find(windows_.begin(), windows_.end(), target);
158 // Insert at |target| position, or at the begining.
159 if (iter == windows_.end())
160 iter = windows_.begin();
161 windows_.insert(iter, insert);
162 if (!shift_reached_until) {
163 pushed = windows_.back();
164 windows_.erase(--windows_.end());
165 }
166 } else {
167 aura::Window::Windows::iterator iter =
168 std::find(windows_.begin(), windows_.end(), target);
169 // Insert after |target|, or at the end.
170 if (iter != windows_.end())
171 ++iter;
172 windows_.insert(iter, insert);
173 if (!shift_reached_until) {
174 pushed = windows_.front();
175 windows_.erase(windows_.begin());
176 }
177 }
178 Layout(NULL);
179 return pushed;
180 }
181
182 void Workspace::Activate() {
183 workspace_manager_->SetActiveWorkspace(this);
184 }
185
186 void Workspace::Layout(aura::Window* no_animation) {
187 aura::Window* ignore = workspace_manager_->ignored_window();
188 workspace_manager_->set_layout_in_progress(true);
189 gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_);
190 int total_width = GetTotalWindowsWidth();
191 if (total_width < work_area.width()) {
192 int dx = (work_area.width() - total_width) / 2;
193 for (aura::Window::Windows::iterator i = windows_.begin();
194 i != windows_.end();
195 ++i) {
196 if (*i != ignore) {
197 MoveWindowTo(*i,
198 gfx::Point(work_area.x() + dx, work_area.y()),
199 no_animation != *i);
200 }
201 dx += GetLayoutWidth(*i) + kWindowHorizontalMargin;
202 }
203 } else {
204 DCHECK_LT(windows_.size(), 3U);
205 // TODO(oshima): This is messy. Figure out general algorithm to
206 // layout more than 2 windows.
207 if (windows_[0] != ignore) {
208 MoveWindowTo(windows_[0],
209 work_area.origin(),
210 no_animation != windows_[0]);
211 }
212 if (windows_.size() == 2 && windows_[1] != ignore) {
213 MoveWindowTo(windows_[1],
214 gfx::Point(work_area.right() - GetLayoutWidth(windows_[1]),
215 work_area.y()),
216 no_animation != windows_[1]);
217 }
218 }
219 workspace_manager_->set_layout_in_progress(false);
220 }
221
222 bool Workspace::ContainsFullscreenWindow() const {
223 for (aura::Window::Windows::const_iterator i = windows_.begin();
224 i != windows_.end();
225 ++i) {
226 aura::Window* w = *i;
227 if (w->IsVisible() &&
228 w->GetIntProperty(aura::client::kShowStateKey) ==
229 ui::SHOW_STATE_FULLSCREEN)
230 return true;
231 }
232 return false;
233 }
234
235 int Workspace::GetIndexOf(aura::Window* window) const {
236 aura::Window::Windows::const_iterator i =
237 std::find(windows_.begin(), windows_.end(), window);
238 return i == windows_.end() ? -1 : i - windows_.begin();
239 }
240
241 bool Workspace::CanAdd(aura::Window* window) const {
242 // TODO(oshima): This should be based on available space and the
243 // size of the |window|.
244 //NOTIMPLEMENTED();
245 return windows_.size() < g_max_windows_per_workspace;
246 }
247
248 void Workspace::MoveWindowTo(
249 aura::Window* window,
250 const gfx::Point& origin,
251 bool animate) {
252 gfx::Rect bounds = GetLayoutBounds(window);
253 gfx::Rect work_area = GetWorkAreaBounds();
254 // Make sure the window isn't bigger than the workspace size.
255 bounds.SetRect(origin.x(), origin.y(),
256 std::min(work_area.width(), bounds.width()),
257 std::min(work_area.height(), bounds.height()));
258 if (animate) {
259 ui::LayerAnimator::ScopedSettings settings(window->layer()->GetAnimator());
260 window->SetBounds(bounds);
261 } else {
262 window->SetBounds(bounds);
263 }
264 }
265
266 int Workspace::GetTotalWindowsWidth() const {
267 int total_width = 0;
268 for (aura::Window::Windows::const_iterator i = windows_.begin();
269 i != windows_.end();
270 ++i) {
271 if (total_width)
272 total_width += kWindowHorizontalMargin;
273 total_width += GetLayoutWidth(*i);
274 }
275 return total_width;
276 }
277
278 // static
279 size_t Workspace::SetMaxWindowsCount(size_t max) {
280 int old = g_max_windows_per_workspace;
281 g_max_windows_per_workspace = max;
282 return old;
283 }
284
285 } // namespace internal
286 } // namespace aura_shell
OLDNEW
« no previous file with comments | « ui/aura_shell/workspace/workspace.h ('k') | ui/aura_shell/workspace/workspace_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698