OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 "ui/aura_shell/workspace/workspace.h" | 5 #include "ui/aura_shell/workspace/workspace.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "ui/aura/desktop.h" | |
8 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
9 #include "ui/aura_shell/workspace/workspace_manager.h" | 10 #include "ui/aura_shell/workspace/workspace_manager.h" |
10 #include "ui/gfx/compositor/layer.h" | 11 #include "ui/gfx/compositor/layer.h" |
11 | 12 |
12 namespace { | 13 namespace { |
13 // Horizontal margin between windows. | 14 // Horizontal margin between windows. |
14 const int kWindowHorizontalMargin = 10; | 15 const int kWindowHorizontalMargin = 10; |
16 | |
17 // Maximum number of windows a workspace can have. | |
18 size_t g_max_windows_per_workspace = 2; | |
15 } | 19 } |
16 | 20 |
17 namespace aura_shell { | 21 namespace aura_shell { |
18 | 22 |
19 Workspace::Workspace(WorkspaceManager* manager) | 23 Workspace::Workspace(WorkspaceManager* manager) |
20 : workspace_manager_(manager) { | 24 : workspace_manager_(manager) { |
21 workspace_manager_->AddWorkspace(this); | 25 workspace_manager_->AddWorkspace(this); |
22 } | 26 } |
23 | 27 |
24 Workspace::~Workspace() { | 28 Workspace::~Workspace() { |
25 workspace_manager_->RemoveWorkspace(this); | 29 workspace_manager_->RemoveWorkspace(this); |
26 } | 30 } |
27 | 31 |
28 void Workspace::SetBounds(const gfx::Rect& bounds) { | 32 void Workspace::SetBounds(const gfx::Rect& bounds) { |
29 bool bounds_changed = bounds_ != bounds; | 33 bool bounds_changed = bounds_ != bounds; |
30 bounds_ = bounds; | 34 bounds_ = bounds; |
31 if (bounds_changed) | 35 if (bounds_changed) |
32 Layout(NULL); | 36 Layout(NULL, NULL); |
33 } | 37 } |
34 | 38 |
35 gfx::Rect Workspace::GetWorkAreaBounds() const { | 39 gfx::Rect Workspace::GetWorkAreaBounds() const { |
36 return workspace_manager_->GetWorkAreaBounds(bounds_); | 40 return workspace_manager_->GetWorkAreaBounds(bounds_); |
37 } | 41 } |
38 | 42 |
39 bool Workspace::AddWindowAfter(aura::Window* window, aura::Window* after) { | 43 bool Workspace::AddWindowAfter(aura::Window* window, aura::Window* after) { |
40 if (!CanAdd(window)) | 44 if (!CanAdd(window)) |
41 return false; | 45 return false; |
42 DCHECK(!Contains(window)); | 46 DCHECK(!Contains(window)); |
43 | 47 |
44 if (!after) { // insert at the end. | 48 if (!after) { // insert at the end. |
45 windows_.push_back(window); | 49 windows_.push_back(window); |
46 } else { | 50 } else { |
47 DCHECK(Contains(after)); | 51 DCHECK(Contains(after)); |
48 aura::Window::Windows::iterator i = | 52 aura::Window::Windows::iterator i = |
49 std::find(windows_.begin(), windows_.end(), after); | 53 std::find(windows_.begin(), windows_.end(), after); |
50 windows_.insert(++i, window); | 54 windows_.insert(++i, window); |
51 } | 55 } |
52 Layout(window); | 56 Layout(NULL, window); |
53 | 57 |
54 return true; | 58 return true; |
55 } | 59 } |
56 | 60 |
57 void Workspace::RemoveWindow(aura::Window* window) { | 61 void Workspace::RemoveWindow(aura::Window* window) { |
58 DCHECK(Contains(window)); | 62 DCHECK(Contains(window)); |
59 windows_.erase(std::find(windows_.begin(), windows_.end(), window)); | 63 windows_.erase(std::find(windows_.begin(), windows_.end(), window)); |
60 Layout(NULL); | 64 Layout(NULL, NULL); |
61 } | 65 } |
62 | 66 |
63 | |
64 bool Workspace::Contains(aura::Window* window) const { | 67 bool Workspace::Contains(aura::Window* window) const { |
65 return std::find(windows_.begin(), windows_.end(), window) != windows_.end(); | 68 return std::find(windows_.begin(), windows_.end(), window) != windows_.end(); |
66 } | 69 } |
67 | 70 |
71 aura::Window* Workspace::FindRotateWindowForLocation( | |
72 const gfx::Point& position) { | |
73 aura::Window* active = aura::Desktop::GetInstance()->active_window(); | |
74 if (GetTotalWindowsWidth() < bounds_.width()) { | |
75 // If all windows fit to the width of the workspace, it returns the | |
76 // window which contains |position|'s x coordinate. | |
77 for (aura::Window::Windows::const_iterator i = windows_.begin(); | |
78 i != windows_.end(); | |
79 ++i) { | |
80 if (active == *i) | |
81 continue; | |
82 gfx::Rect bounds = (*i)->GetTargetBounds(); | |
83 if (bounds.x() < position.x() && position.x() < bounds.right()) | |
84 return *i; | |
85 } | |
86 } else if (bounds_.x() < position.x() && position.x() < bounds_.right()) { | |
87 // If windows are overlapping, it divides the workspace into | |
88 // regions with the same width, and returns the Nth window that | |
89 // corresponds to the region that contains the |position|. | |
90 int width = bounds_.width() / windows_.size(); | |
91 size_t index = (position.x() - bounds_.x()) / width; | |
92 DCHECK(index < windows_.size()); | |
93 aura::Window* window = windows_[index]; | |
94 if (window != active) | |
95 return window; | |
96 } | |
97 return NULL; | |
98 } | |
99 | |
100 void Workspace::RotateWindows(aura::Window* source, aura::Window* target) { | |
101 DCHECK(Contains(source)); | |
102 DCHECK(Contains(target)); | |
103 aura::Window::Windows::iterator source_iter = | |
104 std::find(windows_.begin(), windows_.end(), source); | |
105 aura::Window::Windows::iterator target_iter = | |
106 std::find(windows_.begin(), windows_.end(), target); | |
107 DCHECK(source_iter != target_iter); | |
108 if (source_iter < target_iter) | |
109 std::rotate(source_iter, source_iter + 1, target_iter + 1); | |
110 else | |
111 std::rotate(target_iter, source_iter, source_iter + 1); | |
112 Layout(source, NULL); | |
113 } | |
114 | |
115 aura::Window* Workspace::ShiftWindows(aura::Window* insert, | |
116 aura::Window* target, | |
117 ShiftDirection direction) { | |
118 DCHECK(target); | |
119 DCHECK(!Contains(insert)); | |
120 bool shift_reached_target = GetIndexOf(target) >= 0; | |
121 if (shift_reached_target) | |
122 RemoveWindow(target); | |
123 aura::Window* pushed = NULL; | |
124 if (direction == SHIFT_TO_RIGHT) { | |
125 windows_.insert(windows_.begin(), insert); | |
126 if (!shift_reached_target) { | |
127 pushed = windows_.back(); | |
128 windows_.erase(--windows_.end()); | |
129 } | |
130 } else { | |
131 windows_.push_back(insert); | |
132 if (!shift_reached_target) { | |
133 pushed = windows_.front(); | |
134 windows_.erase(windows_.begin()); | |
135 } | |
136 } | |
137 Layout(shift_reached_target ? target : NULL, NULL); | |
138 return pushed; | |
139 } | |
140 | |
68 void Workspace::Activate() { | 141 void Workspace::Activate() { |
69 workspace_manager_->SetActiveWorkspace(this); | 142 workspace_manager_->SetActiveWorkspace(this); |
70 } | 143 } |
71 | 144 |
72 void Workspace::Layout(aura::Window* no_animation) { | 145 void Workspace::Layout(aura::Window* ignore, aura::Window* no_animation) { |
73 gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_); | 146 gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_); |
74 int total_width = 0; | 147 int total_width = GetTotalWindowsWidth(); |
75 for (aura::Window::Windows::const_iterator i = windows_.begin(); | |
76 i != windows_.end(); | |
77 i++) { | |
78 if (total_width) | |
79 total_width += kWindowHorizontalMargin; | |
80 // TODO(oshima): use restored bounds. | |
81 total_width += (*i)->bounds().width(); | |
82 } | |
83 | 148 |
84 if (total_width < work_area.width()) { | 149 if (total_width < work_area.width()) { |
85 int dx = (work_area.width() - total_width) / 2; | 150 int dx = (work_area.width() - total_width) / 2; |
86 for (aura::Window::Windows::iterator i = windows_.begin(); | 151 for (aura::Window::Windows::iterator i = windows_.begin(); |
87 i != windows_.end(); | 152 i != windows_.end(); |
88 i++) { | 153 ++i) { |
89 MoveWindowTo(*i, | 154 if (*i != ignore) { |
90 gfx::Point(work_area.x() + dx, work_area.y()), | 155 MoveWindowTo(*i, |
91 no_animation != *i); | 156 gfx::Point(work_area.x() + dx, work_area.y()), |
157 no_animation != *i); | |
158 } | |
92 dx += (*i)->bounds().width() + kWindowHorizontalMargin; | 159 dx += (*i)->bounds().width() + kWindowHorizontalMargin; |
93 } | 160 } |
94 } else { | 161 } else { |
95 DCHECK_LT(windows_.size(), 3U); | 162 DCHECK_LT(windows_.size(), 3U); |
96 // TODO(oshima): Figure out general algorithm to layout more than | 163 // TODO(oshima): This is messy. Figure out general algorithm to |
97 // 2 windows. | 164 // layout more than 2 windows. |
98 MoveWindowTo(windows_[0], work_area.origin(), no_animation != windows_[0]); | 165 if (windows_[0] != ignore) { |
99 if (windows_.size() == 2) { | 166 MoveWindowTo(windows_[0], |
167 work_area.origin(), | |
168 no_animation != windows_[0]); | |
169 } | |
170 if (windows_.size() == 2 && windows_[1] != ignore) { | |
100 MoveWindowTo(windows_[1], | 171 MoveWindowTo(windows_[1], |
101 gfx::Point(work_area.right() - windows_[1]->bounds().width(), | 172 gfx::Point(work_area.right() - windows_[1]->bounds().width(), |
102 work_area.y()), | 173 work_area.y()), |
103 no_animation != windows_[1]); | 174 no_animation != windows_[1]); |
104 } | 175 } |
105 } | 176 } |
106 } | 177 } |
107 | 178 |
108 int Workspace::GetIndexOf(aura::Window* window) const { | 179 int Workspace::GetIndexOf(aura::Window* window) const { |
109 aura::Window::Windows::const_iterator i = | 180 aura::Window::Windows::const_iterator i = |
110 std::find(windows_.begin(), windows_.end(), window); | 181 std::find(windows_.begin(), windows_.end(), window); |
111 return i == windows_.end() ? -1 : i - windows_.begin(); | 182 return i == windows_.end() ? -1 : i - windows_.begin(); |
112 } | 183 } |
113 | 184 |
114 bool Workspace::CanAdd(aura::Window* window) const { | 185 bool Workspace::CanAdd(aura::Window* window) const { |
115 // TODO(oshima): This should be based on available space and the | 186 // TODO(oshima): This should be based on available space and the |
116 // size of the |window|. | 187 // size of the |window|. |
117 NOTIMPLEMENTED(); | 188 NOTIMPLEMENTED(); |
118 return windows_.size() < 2; | 189 return windows_.size() < g_max_windows_per_workspace; |
119 } | 190 } |
120 | 191 |
121 void Workspace::MoveWindowTo( | 192 void Workspace::MoveWindowTo( |
122 aura::Window* window, | 193 aura::Window* window, |
123 const gfx::Point& origin, | 194 const gfx::Point& origin, |
124 bool animate) { | 195 bool animate) { |
125 if (window->show_state() == ui::SHOW_STATE_FULLSCREEN) | 196 if (window->show_state() == ui::SHOW_STATE_FULLSCREEN) |
126 window->Fullscreen(); | 197 window->Fullscreen(); |
127 else if (window->show_state() == ui::SHOW_STATE_MAXIMIZED) | 198 else if (window->show_state() == ui::SHOW_STATE_MAXIMIZED) |
128 window->Maximize(); | 199 window->Maximize(); |
129 else { | 200 else { |
130 gfx::Rect bounds = window->GetTargetBounds(); | 201 gfx::Rect bounds = window->GetTargetBounds(); |
131 bounds.set_origin(origin); | 202 bounds.set_origin(origin); |
132 if (animate) | 203 if (animate) |
133 window->layer()->SetAnimation(aura::Window::CreateDefaultAnimation()); | 204 window->layer()->SetAnimation(aura::Window::CreateDefaultAnimation()); |
134 window->SetBounds(bounds); | 205 window->SetBounds(bounds); |
135 } | 206 } |
136 } | 207 } |
137 | 208 |
209 int Workspace::GetTotalWindowsWidth() const { | |
210 int total_width = 0; | |
211 for (aura::Window::Windows::const_iterator i = windows_.begin(); | |
212 i != windows_.end(); | |
213 ++i) { | |
214 if (total_width) | |
215 total_width += kWindowHorizontalMargin; | |
216 // TODO(oshima): use restored bounds. | |
217 total_width += (*i)->bounds().width(); | |
218 } | |
219 return total_width; | |
220 } | |
221 | |
222 // static | |
223 size_t Workspace::SetMaxWindowsCount(size_t max) { | |
224 int old = g_max_windows_per_workspace; | |
225 g_max_windows_per_workspace = max; | |
226 return old; | |
227 } | |
228 | |
229 | |
sky
2011/10/27 19:46:41
nit: remove on of these lines.
oshima
2011/10/27 20:25:43
Done.
| |
138 } // namespace aura_shell | 230 } // namespace aura_shell |
OLD | NEW |