Chromium Code Reviews| 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 bool Workspace::Contains(aura::Window* window) const { | 67 bool Workspace::Contains(aura::Window* window) const { |
| 64 return std::find(windows_.begin(), windows_.end(), window) != windows_.end(); | 68 return std::find(windows_.begin(), windows_.end(), window) != windows_.end(); |
| 65 } | 69 } |
| 66 | 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* until, | |
| 117 aura::Window* target, | |
| 118 ShiftDirection direction) { | |
| 119 DCHECK(until); | |
| 120 DCHECK(!Contains(insert)); | |
| 121 | |
| 122 bool shift_reached_until = GetIndexOf(until) >= 0; | |
| 123 if (shift_reached_until) | |
| 124 RemoveWindow(until); | |
| 125 aura::Window* pushed = NULL; | |
| 126 if (direction == SHIFT_TO_RIGHT) { | |
| 127 aura::Window::Windows::iterator iter = | |
| 128 std::find(windows_.begin(), windows_.end(), target); | |
| 129 // Insert at |target| position, or at the beginnin. | |
| 130 if (iter == windows_.end()) | |
| 131 iter = windows_.begin(); | |
| 132 windows_.insert(iter, insert); | |
| 133 if (!shift_reached_until) { | |
| 134 pushed = windows_.back(); | |
| 135 windows_.erase(--windows_.end()); | |
| 136 } | |
| 137 } else { | |
| 138 aura::Window::Windows::iterator iter = | |
| 139 std::find(windows_.begin(), windows_.end(), target); | |
| 140 // Insert after |target|, or at the end. | |
| 141 if (iter != windows_.end()) | |
| 142 iter++; | |
|
sky
2011/10/27 22:28:53
++iter.
| |
| 143 windows_.insert(iter, insert); | |
| 144 if (!shift_reached_until) { | |
| 145 pushed = windows_.front(); | |
| 146 windows_.erase(windows_.begin()); | |
| 147 } | |
| 148 } | |
| 149 Layout(shift_reached_until ? until : NULL, NULL); | |
| 150 return pushed; | |
| 151 } | |
| 152 | |
| 67 void Workspace::Activate() { | 153 void Workspace::Activate() { |
| 68 workspace_manager_->SetActiveWorkspace(this); | 154 workspace_manager_->SetActiveWorkspace(this); |
| 69 } | 155 } |
| 70 | 156 |
| 71 void Workspace::Layout(aura::Window* no_animation) { | 157 void Workspace::Layout(aura::Window* ignore, aura::Window* no_animation) { |
| 72 gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_); | 158 gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_); |
| 73 int total_width = 0; | 159 int total_width = GetTotalWindowsWidth(); |
| 74 for (aura::Window::Windows::const_iterator i = windows_.begin(); | |
| 75 i != windows_.end(); | |
| 76 ++i) { | |
| 77 if (total_width) | |
| 78 total_width += kWindowHorizontalMargin; | |
| 79 // TODO(oshima): use restored bounds. | |
| 80 total_width += (*i)->bounds().width(); | |
| 81 } | |
| 82 | |
| 83 if (total_width < work_area.width()) { | 160 if (total_width < work_area.width()) { |
| 84 int dx = (work_area.width() - total_width) / 2; | 161 int dx = (work_area.width() - total_width) / 2; |
| 85 for (aura::Window::Windows::iterator i = windows_.begin(); | 162 for (aura::Window::Windows::iterator i = windows_.begin(); |
| 86 i != windows_.end(); | 163 i != windows_.end(); |
| 87 ++i) { | 164 ++i) { |
| 88 MoveWindowTo(*i, | 165 if (*i != ignore) { |
| 89 gfx::Point(work_area.x() + dx, work_area.y()), | 166 MoveWindowTo(*i, |
| 90 no_animation != *i); | 167 gfx::Point(work_area.x() + dx, work_area.y()), |
| 168 no_animation != *i); | |
| 169 } | |
| 91 dx += (*i)->bounds().width() + kWindowHorizontalMargin; | 170 dx += (*i)->bounds().width() + kWindowHorizontalMargin; |
| 92 } | 171 } |
| 93 } else { | 172 } else { |
| 94 DCHECK_LT(windows_.size(), 3U); | 173 DCHECK_LT(windows_.size(), 3U); |
| 95 // TODO(oshima): Figure out general algorithm to layout more than | 174 // TODO(oshima): This is messy. Figure out general algorithm to |
| 96 // 2 windows. | 175 // layout more than 2 windows. |
| 97 MoveWindowTo(windows_[0], work_area.origin(), no_animation != windows_[0]); | 176 if (windows_[0] != ignore) { |
| 98 if (windows_.size() == 2) { | 177 MoveWindowTo(windows_[0], |
| 178 work_area.origin(), | |
| 179 no_animation != windows_[0]); | |
| 180 } | |
| 181 if (windows_.size() == 2 && windows_[1] != ignore) { | |
| 99 MoveWindowTo(windows_[1], | 182 MoveWindowTo(windows_[1], |
| 100 gfx::Point(work_area.right() - windows_[1]->bounds().width(), | 183 gfx::Point(work_area.right() - windows_[1]->bounds().width(), |
| 101 work_area.y()), | 184 work_area.y()), |
| 102 no_animation != windows_[1]); | 185 no_animation != windows_[1]); |
| 103 } | 186 } |
| 104 } | 187 } |
| 105 } | 188 } |
| 106 | 189 |
| 107 int Workspace::GetIndexOf(aura::Window* window) const { | 190 int Workspace::GetIndexOf(aura::Window* window) const { |
| 108 aura::Window::Windows::const_iterator i = | 191 aura::Window::Windows::const_iterator i = |
| 109 std::find(windows_.begin(), windows_.end(), window); | 192 std::find(windows_.begin(), windows_.end(), window); |
| 110 return i == windows_.end() ? -1 : i - windows_.begin(); | 193 return i == windows_.end() ? -1 : i - windows_.begin(); |
| 111 } | 194 } |
| 112 | 195 |
| 113 bool Workspace::CanAdd(aura::Window* window) const { | 196 bool Workspace::CanAdd(aura::Window* window) const { |
| 114 // TODO(oshima): This should be based on available space and the | 197 // TODO(oshima): This should be based on available space and the |
| 115 // size of the |window|. | 198 // size of the |window|. |
| 116 NOTIMPLEMENTED(); | 199 NOTIMPLEMENTED(); |
| 117 return windows_.size() < 2; | 200 return windows_.size() < g_max_windows_per_workspace; |
| 118 } | 201 } |
| 119 | 202 |
| 120 void Workspace::MoveWindowTo( | 203 void Workspace::MoveWindowTo( |
| 121 aura::Window* window, | 204 aura::Window* window, |
| 122 const gfx::Point& origin, | 205 const gfx::Point& origin, |
| 123 bool animate) { | 206 bool animate) { |
| 124 if (window->show_state() == ui::SHOW_STATE_FULLSCREEN) | 207 if (window->show_state() == ui::SHOW_STATE_FULLSCREEN) |
| 125 window->Fullscreen(); | 208 window->Fullscreen(); |
| 126 else if (window->show_state() == ui::SHOW_STATE_MAXIMIZED) | 209 else if (window->show_state() == ui::SHOW_STATE_MAXIMIZED) |
| 127 window->Maximize(); | 210 window->Maximize(); |
| 128 else { | 211 else { |
| 129 gfx::Rect bounds = window->GetTargetBounds(); | 212 gfx::Rect bounds = window->GetTargetBounds(); |
| 130 bounds.set_origin(origin); | 213 bounds.set_origin(origin); |
| 131 if (animate) | 214 if (animate) |
| 132 window->layer()->SetAnimation(aura::Window::CreateDefaultAnimation()); | 215 window->layer()->SetAnimation(aura::Window::CreateDefaultAnimation()); |
| 133 window->SetBounds(bounds); | 216 window->SetBounds(bounds); |
| 134 } | 217 } |
| 135 } | 218 } |
| 136 | 219 |
| 220 int Workspace::GetTotalWindowsWidth() const { | |
| 221 int total_width = 0; | |
| 222 for (aura::Window::Windows::const_iterator i = windows_.begin(); | |
| 223 i != windows_.end(); | |
| 224 ++i) { | |
| 225 if (total_width) | |
| 226 total_width += kWindowHorizontalMargin; | |
| 227 // TODO(oshima): use restored bounds. | |
| 228 total_width += (*i)->bounds().width(); | |
| 229 } | |
| 230 return total_width; | |
| 231 } | |
| 232 | |
| 233 // static | |
| 234 size_t Workspace::SetMaxWindowsCount(size_t max) { | |
| 235 int old = g_max_windows_per_workspace; | |
| 236 g_max_windows_per_workspace = max; | |
| 237 return old; | |
| 238 } | |
| 239 | |
| 137 } // namespace aura_shell | 240 } // namespace aura_shell |
| OLD | NEW |