Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "ash/wm/workspace/workspace_manager.h" | 5 #include "ash/wm/workspace/workspace_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ash/wm/property_util.h" | |
| 10 #include "ash/wm/window_util.h" | |
| 9 #include "ash/wm/workspace/workspace.h" | 11 #include "ash/wm/workspace/workspace.h" |
| 10 #include "ash/wm/workspace/workspace_observer.h" | |
| 11 #include "base/auto_reset.h" | 12 #include "base/auto_reset.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "ui/aura/client/aura_constants.h" | |
| 14 #include "ui/aura/root_window.h" | 16 #include "ui/aura/root_window.h" |
| 15 #include "ui/aura/screen_aura.h" | 17 #include "ui/aura/screen_aura.h" |
| 16 #include "ui/aura/window.h" | 18 #include "ui/aura/window.h" |
| 19 #include "ui/base/ui_base_types.h" | |
| 17 #include "ui/gfx/compositor/layer.h" | 20 #include "ui/gfx/compositor/layer.h" |
| 18 #include "ui/gfx/compositor/layer_animator.h" | 21 #include "ui/gfx/compositor/layer_animator.h" |
| 19 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" | 22 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" |
| 20 #include "ui/gfx/screen.h" | 23 #include "ui/gfx/screen.h" |
| 21 #include "ui/gfx/transform.h" | 24 #include "ui/gfx/transform.h" |
| 22 | 25 |
| 23 namespace { | 26 namespace { |
| 24 | 27 |
| 25 // The horizontal margein between workspaces in pixels. | 28 // The horizontal margein between workspaces in pixels. |
| 26 const int kWorkspaceHorizontalMargin = 50; | 29 const int kWorkspaceHorizontalMargin = 50; |
| 27 | 30 |
| 28 // Minimum/maximum scale for overview mode. | 31 // Minimum/maximum scale for overview mode. |
| 29 const float kMaxOverviewScale = 0.9f; | 32 const float kMaxOverviewScale = 0.9f; |
| 30 const float kMinOverviewScale = 0.3f; | 33 const float kMinOverviewScale = 0.3f; |
| 31 | 34 |
| 35 // Sets the visibility of the layer of each window in |windows| to |value|. | |
| 36 void SetWindowLayerVisibility(const std::vector<aura::Window*>& windows, | |
| 37 bool value) { | |
| 38 for (size_t i = 0; i < windows.size(); ++i){ | |
| 39 if (windows[i]->layer()) | |
| 40 windows[i]->layer()->SetVisible(value); | |
| 41 } | |
| 42 } | |
| 43 | |
| 32 } | 44 } |
| 33 | 45 |
| 34 namespace ash { | 46 namespace ash { |
| 35 namespace internal { | 47 namespace internal { |
| 36 | 48 |
| 37 //////////////////////////////////////////////////////////////////////////////// | 49 //////////////////////////////////////////////////////////////////////////////// |
| 38 // WindowManager, public: | 50 // WindowManager, public: |
| 39 | 51 |
| 40 WorkspaceManager::WorkspaceManager(aura::Window* contents_view) | 52 WorkspaceManager::WorkspaceManager(aura::Window* contents_view) |
| 41 : contents_view_(contents_view), | 53 : contents_view_(contents_view), |
| 42 active_workspace_(NULL), | 54 active_workspace_(NULL), |
| 43 workspace_size_( | 55 workspace_size_( |
| 44 gfx::Screen::GetMonitorAreaNearestWindow(contents_view_).size()), | 56 gfx::Screen::GetMonitorAreaNearestWindow(contents_view_).size()), |
| 45 is_overview_(false), | 57 is_overview_(false), |
| 46 layout_in_progress_(false), | |
| 47 ignored_window_(NULL) { | 58 ignored_window_(NULL) { |
| 48 DCHECK(contents_view); | 59 DCHECK(contents_view); |
| 49 } | 60 } |
| 50 | 61 |
| 51 WorkspaceManager::~WorkspaceManager() { | 62 WorkspaceManager::~WorkspaceManager() { |
| 63 for (size_t i = 0; i < workspaces_.size(); ++i) { | |
| 64 Workspace* workspace = workspaces_[i]; | |
| 65 for (size_t j = 0; j < workspace->windows().size(); ++j) | |
| 66 workspace->windows()[j]->RemoveObserver(this); | |
| 67 } | |
| 52 std::vector<Workspace*> copy_to_delete(workspaces_); | 68 std::vector<Workspace*> copy_to_delete(workspaces_); |
| 53 STLDeleteElements(©_to_delete); | 69 STLDeleteElements(©_to_delete); |
| 54 } | 70 } |
| 55 | 71 |
| 56 Workspace* WorkspaceManager::CreateWorkspace() { | 72 bool WorkspaceManager::IsManagedWindow(aura::Window* window) const { |
| 57 Workspace* workspace = new Workspace(this); | 73 return window->type() == aura::client::WINDOW_TYPE_NORMAL && |
| 58 LayoutWorkspaces(); | 74 !window->transient_parent(); |
| 59 return workspace; | |
| 60 } | 75 } |
| 61 | 76 |
| 62 Workspace* WorkspaceManager::GetActiveWorkspace() const { | 77 void WorkspaceManager::AddWindow(aura::Window* window) { |
| 63 return active_workspace_; | 78 DCHECK(IsManagedWindow(window)); |
| 79 | |
| 80 if (FindBy(window)) | |
| 81 return; // Already know about this window. | |
|
oshima
2012/01/25 23:21:12
When this can happen?
sky
2012/01/26 00:34:09
Because all windows not on the active workspace ge
| |
| 82 | |
| 83 window->AddObserver(this); | |
| 84 | |
| 85 if (!window->GetProperty(aura::client::kShowStateKey)) { | |
| 86 // TODO: set maximized if width < x. | |
| 87 window->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); | |
| 88 } | |
| 89 | |
| 90 if (window_util::IsWindowMaximized(window) && !GetRestoreBounds(window)) | |
|
oshima
2012/01/25 23:21:12
don't we have to check full screen?
sky
2012/01/26 00:34:09
I added a TODO. I haven't dealt well with fullscre
| |
| 91 SetRestoreBounds(window, window->GetTargetBounds()); | |
| 92 | |
| 93 Workspace* workspace = NULL; | |
| 94 Workspace::Type type_for_window = Workspace::TypeForWindow(window); | |
| 95 switch (type_for_window) { | |
| 96 case Workspace::TYPE_SPLIT: | |
| 97 // Splits either go in current workspace (if maximized or split). If the | |
| 98 // current workspace isn't split/maximized, then we maximize. | |
|
oshima
2012/01/25 23:21:12
then create a maximized workspace.
| |
| 99 workspace = GetActiveWorkspace(); | |
| 100 if (workspace && | |
| 101 (workspace->type() == Workspace::TYPE_SPLIT || | |
| 102 workspace->type() == Workspace::TYPE_MAXIMIZED)) { | |
| 103 // TODO: this needs to reset bounds of any existing windows in | |
| 104 // workspace. | |
| 105 workspace->SetType(Workspace::TYPE_SPLIT); | |
| 106 } else { | |
| 107 type_for_window = Workspace::TYPE_MAXIMIZED; | |
| 108 workspace = NULL; | |
| 109 } | |
| 110 break; | |
| 111 | |
| 112 case Workspace::TYPE_NORMAL: | |
| 113 // All normal windows go in the same workspace. | |
| 114 workspace = GetNormalWorkspace(); | |
| 115 break; | |
| 116 | |
| 117 case Workspace::TYPE_MAXIMIZED: | |
| 118 // All maximized windows go in their own workspace. | |
| 119 break; | |
| 120 | |
| 121 default: | |
| 122 NOTREACHED(); | |
| 123 break; | |
| 124 } | |
| 125 | |
| 126 if (!workspace) { | |
| 127 workspace = CreateWorkspace(); | |
| 128 workspace->SetType(Workspace::TypeForWindow(window)); | |
|
oshima
2012/01/25 23:21:12
I believe this needs to be type_for_window?
| |
| 129 } | |
| 130 workspace->AddWindowAfter(window, NULL); | |
| 131 workspace->Activate(); | |
| 64 } | 132 } |
| 65 | 133 |
| 66 Workspace* WorkspaceManager::FindBy(aura::Window* window) const { | 134 void WorkspaceManager::RemoveWindow(aura::Window* window) { |
| 67 int index = GetWorkspaceIndexContaining(window); | 135 Workspace* workspace = FindBy(window); |
| 68 return index < 0 ? NULL : workspaces_[index]; | 136 if (!workspace) |
| 137 return; | |
| 138 window->RemoveObserver(this); | |
| 139 workspace->RemoveWindow(window); | |
| 140 if (workspace->is_empty()) | |
| 141 delete workspace; | |
| 69 } | 142 } |
| 70 | 143 |
| 71 aura::Window* WorkspaceManager::FindRotateWindowForLocation( | 144 void WorkspaceManager::SetActiveWorkspaceByWindow(aura::Window* window) { |
| 72 const gfx::Point& point) { | 145 Workspace* workspace = FindBy(window); |
| 73 for (Workspaces::const_iterator i = workspaces_.begin(); | 146 if (workspace) |
| 74 i != workspaces_.end(); | 147 workspace->Activate(); |
| 75 ++i) { | |
| 76 aura::Window* window = (*i)->FindRotateWindowForLocation(point); | |
| 77 if (window) | |
| 78 return window; | |
| 79 } | |
| 80 return NULL; | |
| 81 } | |
| 82 | |
| 83 void WorkspaceManager::LayoutWorkspaces() { | |
| 84 UpdateContentsView(); | |
| 85 | |
| 86 gfx::Rect bounds(workspace_size_); | |
| 87 int x = 0; | |
| 88 for (Workspaces::const_iterator i = workspaces_.begin(); | |
| 89 i != workspaces_.end(); | |
| 90 ++i) { | |
| 91 Workspace* workspace = *i; | |
| 92 bounds.set_x(x); | |
| 93 workspace->SetBounds(bounds); | |
| 94 x += bounds.width() + kWorkspaceHorizontalMargin; | |
| 95 } | |
| 96 } | 148 } |
| 97 | 149 |
| 98 gfx::Rect WorkspaceManager::GetDragAreaBounds() { | 150 gfx::Rect WorkspaceManager::GetDragAreaBounds() { |
| 99 return GetWorkAreaBounds(gfx::Rect(contents_view_->bounds().size())); | 151 return GetWorkAreaBounds(); |
| 100 } | 152 } |
| 101 | 153 |
| 102 void WorkspaceManager::SetOverview(bool overview) { | 154 void WorkspaceManager::SetOverview(bool overview) { |
| 103 if (is_overview_ == overview) | 155 if (is_overview_ == overview) |
| 104 return; | 156 return; |
| 105 is_overview_ = overview; | 157 NOTIMPLEMENTED(); |
| 106 | |
| 107 ui::Transform transform; | |
| 108 if (is_overview_) { | |
| 109 // TODO(oshima|sky): We limit the how small windows can be shrinked | |
| 110 // in overview mode, thus part of the contents_view may not be visible. | |
| 111 // We need to add capability to scroll/move contents_view in overview mode. | |
| 112 float scale = std::min( | |
| 113 kMaxOverviewScale, | |
| 114 workspace_size_.width() / | |
| 115 static_cast<float>(contents_view_->bounds().width())); | |
| 116 scale = std::max(kMinOverviewScale, scale); | |
| 117 | |
| 118 transform.SetScale(scale, scale); | |
| 119 | |
| 120 int overview_width = contents_view_->bounds().width() * scale; | |
| 121 int dx = 0; | |
| 122 if (overview_width < workspace_size_.width()) { | |
| 123 dx = (workspace_size_.width() - overview_width) / 2; | |
| 124 } else if (active_workspace_) { | |
| 125 // Center the active workspace. | |
| 126 int active_workspace_mid_x = (active_workspace_->bounds().x() + | |
| 127 active_workspace_->bounds().width() / 2) * scale; | |
| 128 dx = workspace_size_.width() / 2 - active_workspace_mid_x; | |
| 129 dx = std::min(0, std::max(dx, workspace_size_.width() - overview_width)); | |
| 130 } | |
| 131 | |
| 132 transform.SetTranslateX(dx); | |
| 133 transform.SetTranslateY(workspace_size_.height() * (1.0f - scale) / 2); | |
| 134 } else if (active_workspace_) { | |
| 135 transform.SetTranslateX(-active_workspace_->bounds().x()); | |
| 136 } | |
| 137 | |
| 138 ui::ScopedLayerAnimationSettings settings( | |
| 139 contents_view_->layer()->GetAnimator()); | |
| 140 contents_view_->layer()->SetTransform(transform); | |
| 141 } | |
| 142 | |
| 143 void WorkspaceManager::RotateWindows(aura::Window* source, | |
| 144 aura::Window* target) { | |
| 145 DCHECK(source); | |
| 146 DCHECK(target); | |
| 147 int source_ws_index = GetWorkspaceIndexContaining(source); | |
| 148 int target_ws_index = GetWorkspaceIndexContaining(target); | |
| 149 DCHECK(source_ws_index >= 0); | |
| 150 DCHECK(target_ws_index >= 0); | |
| 151 if (source_ws_index == target_ws_index) { | |
| 152 workspaces_[source_ws_index]->RotateWindows(source, target); | |
| 153 } else { | |
| 154 aura::Window* insert = source; | |
| 155 aura::Window* target_to_insert = target; | |
| 156 if (source_ws_index < target_ws_index) { | |
| 157 for (int i = target_ws_index; i >= source_ws_index; --i) { | |
| 158 insert = workspaces_[i]->ShiftWindows( | |
| 159 insert, source, target_to_insert, Workspace::SHIFT_TO_LEFT); | |
| 160 // |target| can only be in the 1st workspace. | |
| 161 target_to_insert = NULL; | |
| 162 } | |
| 163 } else { | |
| 164 for (int i = target_ws_index; i <= source_ws_index; ++i) { | |
| 165 insert = workspaces_[i]->ShiftWindows( | |
| 166 insert, source, target_to_insert, Workspace::SHIFT_TO_RIGHT); | |
| 167 // |target| can only be in the 1st workspace. | |
| 168 target_to_insert = NULL; | |
| 169 } | |
| 170 } | |
| 171 } | |
| 172 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | |
| 173 WindowMoved(this, source, target)); | |
| 174 workspaces_[target_ws_index]->Activate(); | |
| 175 } | 158 } |
| 176 | 159 |
| 177 void WorkspaceManager::SetWorkspaceSize(const gfx::Size& workspace_size) { | 160 void WorkspaceManager::SetWorkspaceSize(const gfx::Size& workspace_size) { |
| 178 if (workspace_size == workspace_size_) | 161 if (workspace_size == workspace_size_) |
| 179 return; | 162 return; |
| 180 workspace_size_ = workspace_size; | 163 workspace_size_ = workspace_size; |
| 181 LayoutWorkspaces(); | 164 for (Workspaces::const_iterator i = workspaces_.begin(); |
| 165 i != workspaces_.end(); ++i) { | |
| 166 (*i)->WorkspaceSizeChanged(); | |
| 167 } | |
| 182 } | 168 } |
| 183 | 169 |
| 184 void WorkspaceManager::AddObserver(WorkspaceObserver* observer) { | 170 void WorkspaceManager::OnWindowPropertyChanged(aura::Window* window, |
| 185 observers_.AddObserver(observer); | 171 const char* name, |
| 186 } | 172 void* old) { |
| 173 if (!IsManagedWindow(window)) | |
| 174 return; | |
| 187 | 175 |
| 188 void WorkspaceManager::RemoveObserver(WorkspaceObserver* observer) { | 176 if (name != aura::client::kShowStateKey) |
| 189 observers_.RemoveObserver(observer); | 177 return; |
| 178 // TODO: handle fullscreen. | |
| 179 bool is_maximized = window->GetIntProperty(name) == ui::SHOW_STATE_MAXIMIZED; | |
| 180 bool was_maximized = | |
| 181 (old == reinterpret_cast<void*>(ui::SHOW_STATE_MAXIMIZED)); | |
| 182 if (is_maximized == was_maximized) | |
| 183 return; | |
| 184 | |
| 185 MaximizedStateChanged(window); | |
| 190 } | 186 } |
| 191 | 187 |
| 192 //////////////////////////////////////////////////////////////////////////////// | 188 //////////////////////////////////////////////////////////////////////////////// |
| 193 // WorkspaceManager, private: | 189 // WorkspaceManager, private: |
| 194 | 190 |
| 195 void WorkspaceManager::AddWorkspace(Workspace* workspace) { | 191 void WorkspaceManager::AddWorkspace(Workspace* workspace) { |
| 196 Workspaces::iterator i = std::find(workspaces_.begin(), | 192 DCHECK(std::find(workspaces_.begin(), workspaces_.end(), |
| 197 workspaces_.end(), | 193 workspace) == workspaces_.end()); |
| 198 workspace); | 194 if (active_workspace_) { |
| 199 DCHECK(i == workspaces_.end()); | 195 // New workspaces go right after current workspace. |
| 200 workspaces_.push_back(workspace); | 196 Workspaces::iterator i = std::find(workspaces_.begin(), workspaces_.end(), |
| 197 active_workspace_); | |
| 198 workspaces_.insert(++i, workspace); | |
| 199 } else { | |
| 200 workspaces_.push_back(workspace); | |
| 201 } | |
| 201 } | 202 } |
| 202 | 203 |
| 203 void WorkspaceManager::RemoveWorkspace(Workspace* workspace) { | 204 void WorkspaceManager::RemoveWorkspace(Workspace* workspace) { |
| 204 Workspaces::iterator i = std::find(workspaces_.begin(), | 205 Workspaces::iterator i = std::find(workspaces_.begin(), |
| 205 workspaces_.end(), | 206 workspaces_.end(), |
| 206 workspace); | 207 workspace); |
| 207 DCHECK(i != workspaces_.end()); | 208 DCHECK(i != workspaces_.end()); |
| 208 Workspace* old = NULL; | 209 Workspace* old = NULL; |
| 209 | 210 |
| 210 if (workspace == active_workspace_) { | 211 if (workspace == active_workspace_) { |
| 211 old = active_workspace_; | 212 old = active_workspace_; |
| 212 active_workspace_ = NULL; | 213 active_workspace_ = NULL; |
| 213 } | 214 } |
| 214 workspaces_.erase(i); | 215 workspaces_.erase(i); |
| 215 LayoutWorkspaces(); | 216 } |
| 216 | 217 |
| 217 if (old) { | 218 Workspace* WorkspaceManager::CreateWorkspace() { |
| 218 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | 219 Workspace* workspace = new Workspace(this); |
| 219 ActiveWorkspaceChanged(this, old)); | 220 return workspace; |
| 220 } | 221 } |
| 222 | |
| 223 Workspace* WorkspaceManager::GetActiveWorkspace() const { | |
| 224 return active_workspace_; | |
| 225 } | |
| 226 | |
| 227 Workspace* WorkspaceManager::FindBy(aura::Window* window) const { | |
| 228 int index = GetWorkspaceIndexContaining(window); | |
| 229 return index < 0 ? NULL : workspaces_[index]; | |
| 221 } | 230 } |
| 222 | 231 |
| 223 void WorkspaceManager::SetActiveWorkspace(Workspace* workspace) { | 232 void WorkspaceManager::SetActiveWorkspace(Workspace* workspace) { |
| 224 if (active_workspace_ == workspace) | 233 if (active_workspace_ == workspace) |
| 225 return; | 234 return; |
| 226 DCHECK(std::find(workspaces_.begin(), workspaces_.end(), | 235 DCHECK(std::find(workspaces_.begin(), workspaces_.end(), |
| 227 workspace) != workspaces_.end()); | 236 workspace) != workspaces_.end()); |
| 228 Workspace* old = active_workspace_; | 237 if (active_workspace_) |
| 238 SetWindowLayerVisibility(active_workspace_->windows(), false); | |
| 229 active_workspace_ = workspace; | 239 active_workspace_ = workspace; |
| 240 if (active_workspace_) | |
| 241 SetWindowLayerVisibility(active_workspace_->windows(), true); | |
| 230 | 242 |
| 231 is_overview_ = false; | 243 is_overview_ = false; |
| 232 UpdateContentsView(); | |
| 233 | |
| 234 FOR_EACH_OBSERVER(WorkspaceObserver, observers_, | |
| 235 ActiveWorkspaceChanged(this, old)); | |
| 236 } | 244 } |
| 237 | 245 |
| 238 gfx::Rect WorkspaceManager::GetWorkAreaBounds( | 246 gfx::Rect WorkspaceManager::GetWorkAreaBounds() { |
| 239 const gfx::Rect& workspace_bounds) { | 247 gfx::Rect bounds(workspace_size_); |
| 240 gfx::Rect bounds = workspace_bounds; | |
| 241 bounds.Inset( | 248 bounds.Inset( |
| 242 aura::RootWindow::GetInstance()->screen()->work_area_insets()); | 249 aura::RootWindow::GetInstance()->screen()->work_area_insets()); |
| 243 return bounds; | 250 return bounds; |
| 244 } | 251 } |
| 245 | 252 |
| 246 // Returns the index of the workspace that contains the |window|. | 253 // Returns the index of the workspace that contains the |window|. |
| 247 int WorkspaceManager::GetWorkspaceIndexContaining(aura::Window* window) const { | 254 int WorkspaceManager::GetWorkspaceIndexContaining(aura::Window* window) const { |
| 248 for (Workspaces::const_iterator i = workspaces_.begin(); | 255 for (Workspaces::const_iterator i = workspaces_.begin(); |
| 249 i != workspaces_.end(); | 256 i != workspaces_.end(); |
| 250 ++i) { | 257 ++i) { |
| 251 if ((*i)->Contains(window)) | 258 if ((*i)->Contains(window)) |
| 252 return i - workspaces_.begin(); | 259 return i - workspaces_.begin(); |
| 253 } | 260 } |
| 254 return -1; | 261 return -1; |
| 255 } | 262 } |
| 256 | 263 |
| 257 void WorkspaceManager::UpdateContentsView() { | 264 void WorkspaceManager::SetWindowBounds(aura::Window* window, |
| 258 int num_workspaces = std::max(1, static_cast<int>(workspaces_.size())); | 265 const gfx::Rect& bounds) { |
| 259 int total_width = workspace_size_.width() * num_workspaces + | 266 // TODO: I suspect it's possible for this to be invoked when ignored_window_ |
| 260 kWorkspaceHorizontalMargin * (num_workspaces - 1); | 267 // is non-NULL. |
| 261 gfx::Rect bounds(0, 0, total_width, workspace_size_.height()); | 268 ignored_window_ = window; |
| 269 window->SetBounds(bounds); | |
| 270 ignored_window_ = NULL; | |
| 271 } | |
| 262 | 272 |
| 263 if (contents_view_->GetTargetBounds() != bounds) | 273 void WorkspaceManager::SetWindowBoundsFromRestoreBounds(aura::Window* window) { |
| 264 contents_view_->SetBounds(bounds); | 274 Workspace* workspace = FindBy(window); |
|
oshima
2012/01/25 23:21:12
const (if possible)
| |
| 275 DCHECK(workspace); | |
| 276 const gfx::Rect* restore = GetRestoreBounds(window); | |
| 277 if (restore) { | |
| 278 SetWindowBounds(window, *restore); | |
|
oshima
2012/01/25 23:21:12
This is necessary?
| |
| 279 SetWindowBounds(window, | |
| 280 restore->AdjustToFit(workspace->GetWorkAreaBounds())); | |
| 281 } else { | |
| 282 SetWindowBounds(window, window->bounds().AdjustToFit( | |
| 283 workspace->GetWorkAreaBounds())); | |
| 284 } | |
| 285 ash::ClearRestoreBounds(window); | |
| 286 } | |
| 265 | 287 |
| 266 // Move to active workspace. | 288 void WorkspaceManager::MaximizedStateChanged(aura::Window* window) { |
| 267 if (active_workspace_) { | 289 DCHECK(IsManagedWindow(window)); |
| 268 ui::Transform transform; | 290 bool is_maximized = window_util::IsWindowMaximized(window); |
| 269 transform.SetTranslateX(-active_workspace_->bounds().x()); | 291 Workspace* current_workspace = FindBy(window); |
| 270 ui::ScopedLayerAnimationSettings settings( | 292 DCHECK(current_workspace); |
| 271 contents_view_->layer()->GetAnimator()); | 293 if (is_maximized) { |
| 272 contents_view_->SetTransform(transform); | 294 // Unmaximized -> maximized; create a new workspace (unless current only has |
| 295 // one window). | |
| 296 SetRestoreBounds(window, window->GetTargetBounds()); | |
| 297 if (current_workspace->num_windows() != 1) { | |
| 298 current_workspace->RemoveWindow(window); | |
| 299 Workspace* workspace = CreateWorkspace(); | |
| 300 workspace->SetType(Workspace::TYPE_MAXIMIZED); | |
| 301 workspace->AddWindowAfter(window, NULL); | |
| 302 current_workspace = workspace; | |
| 303 } else { | |
| 304 current_workspace->SetType(Workspace::TYPE_MAXIMIZED); | |
| 305 } | |
| 306 } else { | |
| 307 // Maximized -> unmaximized; move window to unmaximized workspace (or reuse | |
| 308 // current if there isn't one). | |
| 309 window_util::SetOpenWindowSplit(window, false); | |
| 310 Workspace* workspace = GetNormalWorkspace(); | |
| 311 if (workspace) { | |
| 312 current_workspace->RemoveWindow(window); | |
| 313 DCHECK(current_workspace->is_empty()); | |
| 314 workspace->AddWindowAfter(window, NULL); | |
| 315 delete current_workspace; | |
| 316 current_workspace = workspace; | |
| 317 } else { | |
| 318 current_workspace->SetType(Workspace::TYPE_NORMAL); | |
| 319 } | |
| 320 | |
| 321 SetWindowBoundsFromRestoreBounds(window); | |
| 273 } | 322 } |
| 323 | |
| 324 SetActiveWorkspace(FindBy(window)); | |
| 325 } | |
| 326 | |
| 327 Workspace* WorkspaceManager::GetNormalWorkspace() { | |
| 328 for (size_t i = 0; i < workspaces_.size(); ++i) { | |
| 329 if (workspaces_[i]->type() == Workspace::TYPE_NORMAL) | |
| 330 return workspaces_[i]; | |
| 331 } | |
| 332 return NULL; | |
| 274 } | 333 } |
| 275 | 334 |
| 276 } // namespace internal | 335 } // namespace internal |
| 277 } // namespace ash | 336 } // namespace ash |
| OLD | NEW |