| OLD | NEW |
| (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_manager.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/auto_reset.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/stl_util.h" | |
| 12 #include "ui/aura/root_window.h" | |
| 13 #include "ui/aura/screen_aura.h" | |
| 14 #include "ui/aura/window.h" | |
| 15 #include "ui/aura_shell/workspace/workspace.h" | |
| 16 #include "ui/aura_shell/workspace/workspace_observer.h" | |
| 17 #include "ui/gfx/compositor/layer.h" | |
| 18 #include "ui/gfx/compositor/layer_animator.h" | |
| 19 #include "ui/gfx/screen.h" | |
| 20 #include "ui/gfx/transform.h" | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 // The horizontal margein between workspaces in pixels. | |
| 25 const int kWorkspaceHorizontalMargin = 50; | |
| 26 | |
| 27 // Minimum/maximum scale for overview mode. | |
| 28 const float kMaxOverviewScale = 0.9f; | |
| 29 const float kMinOverviewScale = 0.3f; | |
| 30 | |
| 31 } | |
| 32 | |
| 33 namespace aura_shell { | |
| 34 namespace internal { | |
| 35 | |
| 36 //////////////////////////////////////////////////////////////////////////////// | |
| 37 // WindowManager, public: | |
| 38 | |
| 39 WorkspaceManager::WorkspaceManager(aura::Window* contents_view) | |
| 40 : contents_view_(contents_view), | |
| 41 active_workspace_(NULL), | |
| 42 workspace_size_( | |
| 43 gfx::Screen::GetMonitorAreaNearestWindow(contents_view_).size()), | |
| 44 is_overview_(false), | |
| 45 layout_in_progress_(false), | |
| 46 ignored_window_(NULL) { | |
| 47 DCHECK(contents_view); | |
| 48 } | |
| 49 | |
| 50 WorkspaceManager::~WorkspaceManager() { | |
| 51 std::vector<Workspace*> copy_to_delete(workspaces_); | |
| 52 STLDeleteElements(©_to_delete); | |
| 53 } | |
| 54 | |
| 55 Workspace* WorkspaceManager::CreateWorkspace() { | |
| 56 Workspace* workspace = new Workspace(this); | |
| 57 LayoutWorkspaces(); | |
| 58 return workspace; | |
| 59 } | |
| 60 | |
| 61 Workspace* WorkspaceManager::GetActiveWorkspace() const { | |
| 62 return active_workspace_; | |
| 63 } | |
| 64 | |
| 65 Workspace* WorkspaceManager::FindBy(aura::Window* window) const { | |
| 66 int index = GetWorkspaceIndexContaining(window); | |
| 67 return index < 0 ? NULL : workspaces_[index]; | |
| 68 } | |
| 69 | |
| 70 aura::Window* WorkspaceManager::FindRotateWindowForLocation( | |
| 71 const gfx::Point& point) { | |
| 72 for (Workspaces::const_iterator i = workspaces_.begin(); | |
| 73 i != workspaces_.end(); | |
| 74 ++i) { | |
| 75 aura::Window* window = (*i)->FindRotateWindowForLocation(point); | |
| 76 if (window) | |
| 77 return window; | |
| 78 } | |
| 79 return NULL; | |
| 80 } | |
| 81 | |
| 82 void WorkspaceManager::LayoutWorkspaces() { | |
| 83 UpdateContentsView(); | |
| 84 | |
| 85 gfx::Rect bounds(workspace_size_); | |
| 86 int x = 0; | |
| 87 for (Workspaces::const_iterator i = workspaces_.begin(); | |
| 88 i != workspaces_.end(); | |
| 89 ++i) { | |
| 90 Workspace* workspace = *i; | |
| 91 bounds.set_x(x); | |
| 92 workspace->SetBounds(bounds); | |
| 93 x += bounds.width() + kWorkspaceHorizontalMargin; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 gfx::Rect WorkspaceManager::GetDragAreaBounds() { | |
| 98 return GetWorkAreaBounds(gfx::Rect(contents_view_->bounds().size())); | |
| 99 } | |
| 100 | |
| 101 void WorkspaceManager::SetOverview(bool overview) { | |
| 102 if (is_overview_ == overview) | |
| 103 return; | |
| 104 is_overview_ = overview; | |
| 105 | |
| 106 ui::Transform transform; | |
| 107 if (is_overview_) { | |
| 108 // TODO(oshima|sky): We limit the how small windows can be shrinked | |
| 109 // in overview mode, thus part of the contents_view may not be visible. | |
| 110 // We need to add capability to scroll/move contents_view in overview mode. | |
| 111 float scale = std::min( | |
| 112 kMaxOverviewScale, | |
| 113 workspace_size_.width() / | |
| 114 static_cast<float>(contents_view_->bounds().width())); | |
| 115 scale = std::max(kMinOverviewScale, scale); | |
| 116 | |
| 117 transform.SetScale(scale, scale); | |
| 118 | |
| 119 int overview_width = contents_view_->bounds().width() * scale; | |
| 120 int dx = 0; | |
| 121 if (overview_width < workspace_size_.width()) { | |
| 122 dx = (workspace_size_.width() - overview_width) / 2; | |
| 123 } else if (active_workspace_) { | |
| 124 // Center the active workspace. | |
| 125 int active_workspace_mid_x = (active_workspace_->bounds().x() + | |
| 126 active_workspace_->bounds().width() / 2) * scale; | |
| 127 dx = workspace_size_.width() / 2 - active_workspace_mid_x; | |
| 128 dx = std::min(0, std::max(dx, workspace_size_.width() - overview_width)); | |
| 129 } | |
| 130 | |
| 131 transform.SetTranslateX(dx); | |
| 132 transform.SetTranslateY(workspace_size_.height() * (1.0f - scale) / 2); | |
| 133 } else if (active_workspace_) { | |
| 134 transform.SetTranslateX(-active_workspace_->bounds().x()); | |
| 135 } | |
| 136 | |
| 137 ui::LayerAnimator::ScopedSettings settings( | |
| 138 contents_view_->layer()->GetAnimator()); | |
| 139 contents_view_->layer()->SetTransform(transform); | |
| 140 } | |
| 141 | |
| 142 void WorkspaceManager::RotateWindows(aura::Window* source, | |
| 143 aura::Window* target) { | |
| 144 DCHECK(source); | |
| 145 DCHECK(target); | |
| 146 int source_ws_index = GetWorkspaceIndexContaining(source); | |
| 147 int target_ws_index = GetWorkspaceIndexContaining(target); | |
| 148 DCHECK(source_ws_index >= 0); | |
| 149 DCHECK(target_ws_index >= 0); | |
| 150 if (source_ws_index == target_ws_index) { | |
| 151 workspaces_[source_ws_index]->RotateWindows(source, target); | |
| 152 } else { | |
| 153 aura::Window* insert = source; | |
| 154 aura::Window* target_to_insert = target; | |
| 155 if (source_ws_index < target_ws_index) { | |
| 156 for (int i = target_ws_index; i >= source_ws_index; --i) { | |
| 157 insert = workspaces_[i]->ShiftWindows( | |
| 158 insert, source, target_to_insert, Workspace::SHIFT_TO_LEFT); | |
| 159 // |target| can only be in the 1st workspace. | |
| 160 target_to_insert = NULL; | |
| 161 } | |
| 162 } else { | |
| 163 for (int i = target_ws_index; i <= source_ws_index; ++i) { | |
| 164 insert = workspaces_[i]->ShiftWindows( | |
| 165 insert, source, target_to_insert, Workspace::SHIFT_TO_RIGHT); | |
| 166 // |target| can only be in the 1st workspace. | |
| 167 target_to_insert = NULL; | |
| 168 } | |
| 169 } | |
| 170 } | |
| 171 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | |
| 172 WindowMoved(this, source, target)); | |
| 173 workspaces_[target_ws_index]->Activate(); | |
| 174 } | |
| 175 | |
| 176 void WorkspaceManager::SetWorkspaceSize(const gfx::Size& workspace_size) { | |
| 177 if (workspace_size == workspace_size_) | |
| 178 return; | |
| 179 workspace_size_ = workspace_size; | |
| 180 LayoutWorkspaces(); | |
| 181 } | |
| 182 | |
| 183 void WorkspaceManager::AddObserver(WorkspaceObserver* observer) { | |
| 184 observers_.AddObserver(observer); | |
| 185 } | |
| 186 | |
| 187 void WorkspaceManager::RemoveObserver(WorkspaceObserver* observer) { | |
| 188 observers_.RemoveObserver(observer); | |
| 189 } | |
| 190 | |
| 191 //////////////////////////////////////////////////////////////////////////////// | |
| 192 // WorkspaceManager, private: | |
| 193 | |
| 194 void WorkspaceManager::AddWorkspace(Workspace* workspace) { | |
| 195 Workspaces::iterator i = std::find(workspaces_.begin(), | |
| 196 workspaces_.end(), | |
| 197 workspace); | |
| 198 DCHECK(i == workspaces_.end()); | |
| 199 workspaces_.push_back(workspace); | |
| 200 } | |
| 201 | |
| 202 void WorkspaceManager::RemoveWorkspace(Workspace* workspace) { | |
| 203 Workspaces::iterator i = std::find(workspaces_.begin(), | |
| 204 workspaces_.end(), | |
| 205 workspace); | |
| 206 DCHECK(i != workspaces_.end()); | |
| 207 Workspace* old = NULL; | |
| 208 | |
| 209 if (workspace == active_workspace_) { | |
| 210 old = active_workspace_; | |
| 211 active_workspace_ = NULL; | |
| 212 } | |
| 213 workspaces_.erase(i); | |
| 214 LayoutWorkspaces(); | |
| 215 | |
| 216 if (old) { | |
| 217 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | |
| 218 ActiveWorkspaceChanged(this, old)); | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 void WorkspaceManager::SetActiveWorkspace(Workspace* workspace) { | |
| 223 if (active_workspace_ == workspace) | |
| 224 return; | |
| 225 DCHECK(std::find(workspaces_.begin(), workspaces_.end(), | |
| 226 workspace) != workspaces_.end()); | |
| 227 Workspace* old = active_workspace_; | |
| 228 active_workspace_ = workspace; | |
| 229 | |
| 230 is_overview_ = false; | |
| 231 UpdateContentsView(); | |
| 232 | |
| 233 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | |
| 234 ActiveWorkspaceChanged(this, old)); | |
| 235 } | |
| 236 | |
| 237 gfx::Rect WorkspaceManager::GetWorkAreaBounds( | |
| 238 const gfx::Rect& workspace_bounds) { | |
| 239 gfx::Rect bounds = workspace_bounds; | |
| 240 bounds.Inset( | |
| 241 aura::RootWindow::GetInstance()->screen()->work_area_insets()); | |
| 242 return bounds; | |
| 243 } | |
| 244 | |
| 245 // Returns the index of the workspace that contains the |window|. | |
| 246 int WorkspaceManager::GetWorkspaceIndexContaining(aura::Window* window) const { | |
| 247 for (Workspaces::const_iterator i = workspaces_.begin(); | |
| 248 i != workspaces_.end(); | |
| 249 ++i) { | |
| 250 if ((*i)->Contains(window)) | |
| 251 return i - workspaces_.begin(); | |
| 252 } | |
| 253 return -1; | |
| 254 } | |
| 255 | |
| 256 void WorkspaceManager::UpdateContentsView() { | |
| 257 int num_workspaces = std::max(1, static_cast<int>(workspaces_.size())); | |
| 258 int total_width = workspace_size_.width() * num_workspaces + | |
| 259 kWorkspaceHorizontalMargin * (num_workspaces - 1); | |
| 260 gfx::Rect bounds(0, 0, total_width, workspace_size_.height()); | |
| 261 | |
| 262 if (contents_view_->GetTargetBounds() != bounds) | |
| 263 contents_view_->SetBounds(bounds); | |
| 264 | |
| 265 // Move to active workspace. | |
| 266 if (active_workspace_) { | |
| 267 ui::Transform transform; | |
| 268 transform.SetTranslateX(-active_workspace_->bounds().x()); | |
| 269 ui::LayerAnimator::ScopedSettings settings( | |
| 270 contents_view_->layer()->GetAnimator()); | |
| 271 contents_view_->SetTransform(transform); | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 } // namespace internal | |
| 276 } // namespace aura_shell | |
| OLD | NEW |