| 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 #include <functional> | 8 #include <functional> |
| 9 | 9 |
| 10 #include "ash/root_window_controller.h" | 10 #include "ash/root_window_controller.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 DISALLOW_COPY_AND_ASSIGN(LayoutManagerImpl); | 106 DISALLOW_COPY_AND_ASSIGN(LayoutManagerImpl); |
| 107 }; | 107 }; |
| 108 | 108 |
| 109 // WorkspaceManager ----------------------------------------------------------- | 109 // WorkspaceManager ----------------------------------------------------------- |
| 110 | 110 |
| 111 WorkspaceManager::WorkspaceManager(Window* contents_window) | 111 WorkspaceManager::WorkspaceManager(Window* contents_window) |
| 112 : contents_window_(contents_window), | 112 : contents_window_(contents_window), |
| 113 active_workspace_(NULL), | 113 active_workspace_(NULL), |
| 114 shelf_(NULL), | 114 shelf_(NULL), |
| 115 in_move_(false), | 115 in_move_(false), |
| 116 clear_unminimizing_workspace_factory_(this), | |
| 117 unminimizing_workspace_(NULL), | |
| 118 app_terminating_(false), | 116 app_terminating_(false), |
| 119 creating_fade_(false) { | 117 creating_fade_(false) { |
| 120 // Clobber any existing event filter. | 118 // Clobber any existing event filter. |
| 121 contents_window->SetEventFilter(NULL); | 119 contents_window->SetEventFilter(NULL); |
| 122 // |contents_window| takes ownership of LayoutManagerImpl. | 120 // |contents_window| takes ownership of LayoutManagerImpl. |
| 123 contents_window->SetLayoutManager(new LayoutManagerImpl(this)); | 121 contents_window->SetLayoutManager(new LayoutManagerImpl(this)); |
| 124 active_workspace_ = CreateWorkspace(false); | 122 active_workspace_ = new Workspace(this, contents_window_); |
| 125 workspaces_.push_back(active_workspace_); | 123 workspaces_.push_back(active_workspace_); |
| 126 active_workspace_->window()->Show(); | 124 active_workspace_->window()->Show(); |
| 127 Shell::GetInstance()->AddShellObserver(this); | 125 Shell::GetInstance()->AddShellObserver(this); |
| 128 | 126 |
| 129 if (ash::WorkspaceCyclerConfiguration::IsCyclerEnabled()) | 127 if (ash::WorkspaceCyclerConfiguration::IsCyclerEnabled()) |
| 130 workspace_cycler_.reset(new WorkspaceCycler(this)); | 128 workspace_cycler_.reset(new WorkspaceCycler(this)); |
| 131 } | 129 } |
| 132 | 130 |
| 133 WorkspaceManager::~WorkspaceManager() { | 131 WorkspaceManager::~WorkspaceManager() { |
| 134 Shell::GetInstance()->RemoveShellObserver(this); | 132 Shell::GetInstance()->RemoveShellObserver(this); |
| 135 // Release the windows, they'll be destroyed when |contents_window_| is | 133 // Release the windows, they'll be destroyed when |contents_window_| is |
| 136 // destroyed. | 134 // destroyed. |
| 137 std::for_each(workspaces_.begin(), workspaces_.end(), | 135 std::for_each(workspaces_.begin(), workspaces_.end(), |
| 138 std::mem_fun(&Workspace::ReleaseWindow)); | 136 std::mem_fun(&Workspace::ReleaseWindow)); |
| 139 std::for_each(pending_workspaces_.begin(), pending_workspaces_.end(), | 137 std::for_each(pending_workspaces_.begin(), pending_workspaces_.end(), |
| 140 std::mem_fun(&Workspace::ReleaseWindow)); | 138 std::mem_fun(&Workspace::ReleaseWindow)); |
| 141 std::for_each(to_delete_.begin(), to_delete_.end(), | 139 std::for_each(to_delete_.begin(), to_delete_.end(), |
| 142 std::mem_fun(&Workspace::ReleaseWindow)); | 140 std::mem_fun(&Workspace::ReleaseWindow)); |
| 143 STLDeleteElements(&workspaces_); | 141 STLDeleteElements(&workspaces_); |
| 144 STLDeleteElements(&pending_workspaces_); | 142 STLDeleteElements(&pending_workspaces_); |
| 145 STLDeleteElements(&to_delete_); | 143 STLDeleteElements(&to_delete_); |
| 146 } | 144 } |
| 147 | 145 |
| 148 // static | |
| 149 bool WorkspaceManager::WillRestoreToWorkspace(Window* window) { | |
| 150 return wm::IsWindowMinimized(window) && | |
| 151 window->GetProperty(aura::client::kRestoreShowStateKey) == | |
| 152 ui::SHOW_STATE_FULLSCREEN; | |
| 153 } | |
| 154 | |
| 155 WorkspaceWindowState WorkspaceManager::GetWindowState() const { | 146 WorkspaceWindowState WorkspaceManager::GetWindowState() const { |
| 156 if (!shelf_) | 147 if (!shelf_) |
| 157 return WORKSPACE_WINDOW_STATE_DEFAULT; | 148 return WORKSPACE_WINDOW_STATE_DEFAULT; |
| 158 | 149 |
| 159 const bool is_active_fullscreen = active_workspace_->is_fullscreen(); | |
| 160 const gfx::Rect shelf_bounds(shelf_->GetIdealBounds()); | 150 const gfx::Rect shelf_bounds(shelf_->GetIdealBounds()); |
| 161 const Window::Windows& windows(active_workspace_->window()->children()); | 151 const Window::Windows& windows(active_workspace_->window()->children()); |
| 162 bool window_overlaps_launcher = false; | 152 bool window_overlaps_launcher = false; |
| 163 bool has_maximized_window = false; | 153 bool has_maximized_window = false; |
| 164 for (Window::Windows::const_iterator i = windows.begin(); | 154 for (Window::Windows::const_iterator i = windows.begin(); |
| 165 i != windows.end(); ++i) { | 155 i != windows.end(); ++i) { |
| 166 if (GetIgnoredByShelf(*i)) | 156 if (GetIgnoredByShelf(*i)) |
| 167 continue; | 157 continue; |
| 168 ui::Layer* layer = (*i)->layer(); | 158 ui::Layer* layer = (*i)->layer(); |
| 169 if (!layer->GetTargetVisibility() || layer->GetTargetOpacity() == 0.0f) | 159 if (!layer->GetTargetVisibility() || layer->GetTargetOpacity() == 0.0f) |
| 170 continue; | 160 continue; |
| 171 if (wm::IsWindowMaximized(*i)) { | 161 if (wm::IsWindowMaximized(*i)) { |
| 172 // An untracked window may still be fullscreen so we keep iterating when | 162 // An untracked window may still be fullscreen so we keep iterating when |
| 173 // we hit a maximized window. | 163 // we hit a maximized window. |
| 174 has_maximized_window = true; | 164 has_maximized_window = true; |
| 175 } else if (is_active_fullscreen && wm::IsWindowFullscreen(*i)) { | 165 } else if (wm::IsWindowFullscreen(*i)) { |
| 176 // Ignore fullscreen windows if we're in the desktop. Such a state | |
| 177 // is transitory and means we haven't yet switched. If we did consider | |
| 178 // such windows we'll return the wrong thing, which can lead to | |
| 179 // prematurely anging the launcher state and clobbering restore bounds. | |
| 180 return WORKSPACE_WINDOW_STATE_FULL_SCREEN; | 166 return WORKSPACE_WINDOW_STATE_FULL_SCREEN; |
| 181 } | 167 } |
| 182 if (!window_overlaps_launcher && (*i)->bounds().Intersects(shelf_bounds)) | 168 if (!window_overlaps_launcher && (*i)->bounds().Intersects(shelf_bounds)) |
| 183 window_overlaps_launcher = true; | 169 window_overlaps_launcher = true; |
| 184 } | 170 } |
| 185 if (has_maximized_window) | 171 if (has_maximized_window) |
| 186 return WORKSPACE_WINDOW_STATE_MAXIMIZED; | 172 return WORKSPACE_WINDOW_STATE_MAXIMIZED; |
| 187 | 173 |
| 188 return window_overlaps_launcher ? | 174 return window_overlaps_launcher ? |
| 189 WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF : | 175 WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF : |
| (...skipping 21 matching lines...) Expand all Loading... |
| 211 // have to allow dragging of a fullscreen window to work in this case. | 197 // have to allow dragging of a fullscreen window to work in this case. |
| 212 // . The window persists across all workspaces. For example, the task | 198 // . The window persists across all workspaces. For example, the task |
| 213 // manager is in the desktop worskpace and the current workspace is | 199 // manager is in the desktop worskpace and the current workspace is |
| 214 // fullscreen. If we swapped to the desktop you would lose context. | 200 // fullscreen. If we swapped to the desktop you would lose context. |
| 215 // Instead we reparent. The exception to this is if the window is | 201 // Instead we reparent. The exception to this is if the window is |
| 216 // fullscreen (it needs its own workspace then) or we're in the process of | 202 // fullscreen (it needs its own workspace then) or we're in the process of |
| 217 // fullscreen. If we're in the process of fullscreen the window needs its | 203 // fullscreen. If we're in the process of fullscreen the window needs its |
| 218 // own workspace. | 204 // own workspace. |
| 219 if (!GetTrackedByWorkspace(window) || | 205 if (!GetTrackedByWorkspace(window) || |
| 220 (GetPersistsAcrossAllWorkspaces(window) && | 206 (GetPersistsAcrossAllWorkspaces(window) && |
| 221 !wm::IsWindowFullscreen(window) && !WillRestoreToWorkspace(window))) { | 207 !wm::IsWindowFullscreen(window))) { |
| 222 ReparentWindow(window, active_workspace_->window(), NULL); | 208 ReparentWindow(window, active_workspace_->window(), NULL); |
| 223 } else { | 209 } else { |
| 224 SetActiveWorkspace(workspace, SWITCH_WINDOW_MADE_ACTIVE); | 210 SetActiveWorkspace(workspace, SWITCH_WINDOW_MADE_ACTIVE); |
| 225 } | 211 } |
| 226 } | 212 } |
| 227 | |
| 228 if (workspace->is_fullscreen() && wm::IsWindowFullscreen(window)) { | |
| 229 // Clicking on the fullscreen window in a fullscreen workspace. Force all | |
| 230 // other windows to drop to the desktop. | |
| 231 MoveChildrenToDesktop(workspace->window(), NULL); | |
| 232 } | |
| 233 } | 213 } |
| 234 | 214 |
| 235 Window* WorkspaceManager::GetActiveWorkspaceWindow() { | 215 Window* WorkspaceManager::GetActiveWorkspaceWindow() { |
| 236 return active_workspace_->window(); | 216 return active_workspace_->window(); |
| 237 } | 217 } |
| 238 | 218 |
| 239 Window* WorkspaceManager::GetParentForNewWindow(Window* window) { | 219 Window* WorkspaceManager::GetParentForNewWindow(Window* window) { |
| 240 // Try to put windows with transient parents in the same workspace as their | 220 // Try to put windows with transient parents in the same workspace as their |
| 241 // transient parent. | 221 // transient parent. |
| 242 if (window->transient_parent() && !wm::IsWindowFullscreen(window)) { | 222 if (window->transient_parent()) { |
| 243 Workspace* workspace = FindBy(window->transient_parent()); | 223 Workspace* workspace = FindBy(window->transient_parent()); |
| 244 if (workspace) | 224 if (workspace) |
| 245 return workspace->window(); | 225 return workspace->window(); |
| 246 // Fall through to normal logic. | 226 // Fall through to normal logic. |
| 247 } | 227 } |
| 248 | 228 |
| 249 if (!GetTrackedByWorkspace(window)) | 229 if (!GetTrackedByWorkspace(window)) |
| 250 return active_workspace_->window(); | 230 return active_workspace_->window(); |
| 251 | 231 |
| 252 if (wm::IsWindowFullscreen(window)) { | |
| 253 // Wait for the window to be made active before showing the workspace. | |
| 254 Workspace* workspace = CreateWorkspace(true); | |
| 255 pending_workspaces_.insert(workspace); | |
| 256 return workspace->window(); | |
| 257 } | |
| 258 | |
| 259 if (!GetTrackedByWorkspace(window) || GetPersistsAcrossAllWorkspaces(window)) | |
| 260 return active_workspace_->window(); | |
| 261 | |
| 262 return desktop_workspace()->window(); | 232 return desktop_workspace()->window(); |
| 263 } | 233 } |
| 264 | 234 |
| 265 bool WorkspaceManager::CanStartCyclingThroughWorkspaces() const { | 235 bool WorkspaceManager::CanStartCyclingThroughWorkspaces() const { |
| 266 return workspace_cycler_.get() && workspaces_.size() > 1u; | 236 return workspace_cycler_.get() && workspaces_.size() > 1u; |
| 267 } | 237 } |
| 268 | 238 |
| 269 void WorkspaceManager::InitWorkspaceCyclerAnimatorWithCurrentState( | 239 void WorkspaceManager::InitWorkspaceCyclerAnimatorWithCurrentState( |
| 270 WorkspaceCyclerAnimator* animator) { | 240 WorkspaceCyclerAnimator* animator) { |
| 271 if (animator) | 241 if (animator) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 } | 302 } |
| 333 | 303 |
| 334 Workspace* last_active = active_workspace_; | 304 Workspace* last_active = active_workspace_; |
| 335 active_workspace_ = workspace; | 305 active_workspace_ = workspace; |
| 336 | 306 |
| 337 // The display work-area may have changed while |workspace| was not the active | 307 // The display work-area may have changed while |workspace| was not the active |
| 338 // workspace. Give it a chance to adjust its state for the new work-area. | 308 // workspace. Give it a chance to adjust its state for the new work-area. |
| 339 active_workspace_->workspace_layout_manager()-> | 309 active_workspace_->workspace_layout_manager()-> |
| 340 OnDisplayWorkAreaInsetsChanged(); | 310 OnDisplayWorkAreaInsetsChanged(); |
| 341 | 311 |
| 342 const bool is_unminimizing_fullscreen_window = | 312 contents_window_->StackChildAtTop(last_active->window()); |
| 343 unminimizing_workspace_ && unminimizing_workspace_ == active_workspace_ && | |
| 344 active_workspace_->is_fullscreen(); | |
| 345 if (is_unminimizing_fullscreen_window) { | |
| 346 // If we're unminimizing a window it needs to be on the top, otherwise you | |
| 347 // won't see the animation. | |
| 348 contents_window_->StackChildAtTop(active_workspace_->window()); | |
| 349 } else if (active_workspace_->is_fullscreen() && | |
| 350 last_active->is_fullscreen() && | |
| 351 reason != SWITCH_FULLSCREEN_FROM_FULLSCREEN_WORKSPACE) { | |
| 352 // When switching between fullscreen windows we need the last active | |
| 353 // workspace on top of the new, otherwise the animations won't look | |
| 354 // right. Since only one workspace is visible at a time stacking order of | |
| 355 // the workspace windows ultimately doesn't matter. | |
| 356 contents_window_->StackChildAtTop(last_active->window()); | |
| 357 } | |
| 358 | 313 |
| 359 HideWorkspace(last_active, reason, is_unminimizing_fullscreen_window); | 314 HideWorkspace(last_active, reason); |
| 360 ShowWorkspace(workspace, last_active, reason); | 315 ShowWorkspace(workspace, last_active, reason); |
| 361 | 316 |
| 362 UpdateShelfVisibility(); | 317 UpdateShelfVisibility(); |
| 363 | 318 |
| 364 // Showing or hiding a workspace may change the "solo window" status of | 319 // Showing or hiding a workspace may change the "solo window" status of |
| 365 // a window, requiring the header to be updated. | 320 // a window, requiring the header to be updated. |
| 366 FramePainter::UpdateSoloWindowHeader(contents_window_->GetRootWindow()); | 321 FramePainter::UpdateSoloWindowHeader(contents_window_->GetRootWindow()); |
| 367 } | 322 } |
| 368 | 323 |
| 369 WorkspaceManager::Workspaces::iterator | 324 WorkspaceManager::Workspaces::iterator |
| 370 WorkspaceManager::FindWorkspace(Workspace* workspace) { | 325 WorkspaceManager::FindWorkspace(Workspace* workspace) { |
| 371 return std::find(workspaces_.begin(), workspaces_.end(), workspace); | 326 return std::find(workspaces_.begin(), workspaces_.end(), workspace); |
| 372 } | 327 } |
| 373 | 328 |
| 374 Workspace* WorkspaceManager::CreateWorkspace(bool fullscreen) { | 329 Workspace* WorkspaceManager::CreateWorkspaceForTest() { |
| 375 return new Workspace(this, contents_window_, fullscreen); | 330 return new Workspace(this, contents_window_); |
| 376 } | 331 } |
| 377 | 332 |
| 378 void WorkspaceManager::MoveWorkspaceToPendingOrDelete( | 333 void WorkspaceManager::MoveWorkspaceToPendingOrDelete( |
| 379 Workspace* workspace, | 334 Workspace* workspace, |
| 380 Window* stack_beneath, | 335 Window* stack_beneath, |
| 381 SwitchReason reason) { | 336 SwitchReason reason) { |
| 382 // We're all ready moving windows. | 337 // We're all ready moving windows. |
| 383 if (in_move_) | 338 if (in_move_) |
| 384 return; | 339 return; |
| 385 | 340 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 397 | 352 |
| 398 MoveChildrenToDesktop(workspace->window(), stack_beneath); | 353 MoveChildrenToDesktop(workspace->window(), stack_beneath); |
| 399 | 354 |
| 400 { | 355 { |
| 401 Workspaces::iterator workspace_i(FindWorkspace(workspace)); | 356 Workspaces::iterator workspace_i(FindWorkspace(workspace)); |
| 402 if (workspace_i != workspaces_.end()) | 357 if (workspace_i != workspaces_.end()) |
| 403 workspaces_.erase(workspace_i); | 358 workspaces_.erase(workspace_i); |
| 404 } | 359 } |
| 405 | 360 |
| 406 if (workspace->window()->children().empty()) { | 361 if (workspace->window()->children().empty()) { |
| 407 if (workspace == unminimizing_workspace_) | |
| 408 unminimizing_workspace_ = NULL; | |
| 409 pending_workspaces_.erase(workspace); | 362 pending_workspaces_.erase(workspace); |
| 410 ScheduleDelete(workspace); | 363 ScheduleDelete(workspace); |
| 411 } else { | 364 } else { |
| 412 pending_workspaces_.insert(workspace); | 365 pending_workspaces_.insert(workspace); |
| 413 } | 366 } |
| 414 } | 367 } |
| 415 | 368 |
| 416 void WorkspaceManager::MoveChildrenToDesktop(aura::Window* window, | 369 void WorkspaceManager::MoveChildrenToDesktop(aura::Window* window, |
| 417 aura::Window* stack_beneath) { | 370 aura::Window* stack_beneath) { |
| 418 // Build the list of windows to move. Exclude fullscreen and windows with | 371 // Build the list of windows to move. Exclude fullscreen and windows with |
| 419 // transient parents. | 372 // transient parents. |
| 420 Window::Windows to_move; | 373 Window::Windows to_move; |
| 421 for (size_t i = 0; i < window->children().size(); ++i) { | 374 for (size_t i = 0; i < window->children().size(); ++i) { |
| 422 Window* child = window->children()[i]; | 375 Window* child = window->children()[i]; |
| 423 if (!child->transient_parent() && !wm::IsWindowFullscreen(child) && | 376 if (!child->transient_parent() && !wm::IsWindowFullscreen(child)) { |
| 424 !WillRestoreToWorkspace(child)) { | |
| 425 to_move.push_back(child); | 377 to_move.push_back(child); |
| 426 } | 378 } |
| 427 } | 379 } |
| 428 // Move the windows, but make sure the window is still a child of |window| | 380 // Move the windows, but make sure the window is still a child of |window| |
| 429 // (moving may cascade and cause other windows to move). | 381 // (moving may cascade and cause other windows to move). |
| 430 for (size_t i = 0; i < to_move.size(); ++i) { | 382 for (size_t i = 0; i < to_move.size(); ++i) { |
| 431 if (std::find(window->children().begin(), window->children().end(), | 383 if (std::find(window->children().begin(), window->children().end(), |
| 432 to_move[i]) != window->children().end()) { | 384 to_move[i]) != window->children().end()) { |
| 433 ReparentWindow(to_move[i], desktop_workspace()->window(), | 385 ReparentWindow(to_move[i], desktop_workspace()->window(), |
| 434 stack_beneath); | 386 stack_beneath); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 447 SetActiveWorkspace(*(workspace_i - 1), reason); | 399 SetActiveWorkspace(*(workspace_i - 1), reason); |
| 448 } | 400 } |
| 449 | 401 |
| 450 void WorkspaceManager::ScheduleDelete(Workspace* workspace) { | 402 void WorkspaceManager::ScheduleDelete(Workspace* workspace) { |
| 451 to_delete_.insert(workspace); | 403 to_delete_.insert(workspace); |
| 452 delete_timer_.Stop(); | 404 delete_timer_.Stop(); |
| 453 delete_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, | 405 delete_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, |
| 454 &WorkspaceManager::ProcessDeletion); | 406 &WorkspaceManager::ProcessDeletion); |
| 455 } | 407 } |
| 456 | 408 |
| 457 void WorkspaceManager::SetUnminimizingWorkspace(Workspace* workspace) { | |
| 458 // The normal sequence of unminimizing a window is: Show() the window, which | |
| 459 // triggers changing the kShowStateKey to NORMAL and lastly the window is made | |
| 460 // active. This means at the time the window is unminimized we don't know if | |
| 461 // the workspace it is in is going to become active. To track this | |
| 462 // |unminimizing_workspace_| is set at the time we unminimize and a task is | |
| 463 // schedule to reset it. This way when we get the activate we know we're in | |
| 464 // the process unminimizing and can do the right animation. | |
| 465 unminimizing_workspace_ = workspace; | |
| 466 if (unminimizing_workspace_) { | |
| 467 base::MessageLoop::current()->PostTask( | |
| 468 FROM_HERE, | |
| 469 base::Bind(&WorkspaceManager::SetUnminimizingWorkspace, | |
| 470 clear_unminimizing_workspace_factory_.GetWeakPtr(), | |
| 471 static_cast<Workspace*>(NULL))); | |
| 472 } | |
| 473 } | |
| 474 | |
| 475 void WorkspaceManager::FadeDesktop(aura::Window* window, | 409 void WorkspaceManager::FadeDesktop(aura::Window* window, |
| 476 base::TimeDelta duration) { | 410 base::TimeDelta duration) { |
| 477 if (views::corewm::WindowAnimationsDisabled(NULL) || | 411 if (views::corewm::WindowAnimationsDisabled(NULL) || |
| 478 ui::ScopedAnimationDurationScaleMode::duration_scale_mode() == | 412 ui::ScopedAnimationDurationScaleMode::duration_scale_mode() == |
| 479 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION) | 413 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION) |
| 480 return; | 414 return; |
| 481 | 415 |
| 482 base::AutoReset<bool> reseter(&creating_fade_, true); | 416 base::AutoReset<bool> reseter(&creating_fade_, true); |
| 483 DesktopBackgroundFadeController::Direction direction; | 417 DesktopBackgroundFadeController::Direction direction; |
| 484 aura::Window* parent = NULL; | 418 aura::Window* parent = NULL; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 505 Workspace* last_active, | 439 Workspace* last_active, |
| 506 SwitchReason reason) const { | 440 SwitchReason reason) const { |
| 507 WorkspaceAnimationDetails details; | 441 WorkspaceAnimationDetails details; |
| 508 details.direction = | 442 details.direction = |
| 509 (last_active == desktop_workspace() || reason == SWITCH_INITIAL) ? | 443 (last_active == desktop_workspace() || reason == SWITCH_INITIAL) ? |
| 510 WORKSPACE_ANIMATE_DOWN : WORKSPACE_ANIMATE_UP; | 444 WORKSPACE_ANIMATE_DOWN : WORKSPACE_ANIMATE_UP; |
| 511 | 445 |
| 512 switch (reason) { | 446 switch (reason) { |
| 513 case SWITCH_WINDOW_MADE_ACTIVE: | 447 case SWITCH_WINDOW_MADE_ACTIVE: |
| 514 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: | 448 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: |
| 515 case SWITCH_WINDOW_REMOVED: | |
| 516 case SWITCH_VISIBILITY_CHANGED: | |
| 517 case SWITCH_MINIMIZED: | |
| 518 details.animate = details.animate_scale = true; | 449 details.animate = details.animate_scale = true; |
| 519 details.animate_opacity = last_active == desktop_workspace(); | 450 details.animate_opacity = last_active == desktop_workspace(); |
| 520 break; | 451 break; |
| 521 | 452 |
| 522 case SWITCH_INITIAL: | 453 case SWITCH_INITIAL: |
| 523 details.animate = details.animate_opacity = details.animate_scale = true; | 454 details.animate = details.animate_opacity = details.animate_scale = true; |
| 524 details.pause_time_ms = kInitialPauseTimeMS; | 455 details.pause_time_ms = kInitialPauseTimeMS; |
| 525 break; | 456 break; |
| 526 | 457 |
| 527 // Remaining cases require no animation. | 458 // Remaining cases require no animation. |
| 528 default: | 459 default: |
| 529 break; | 460 break; |
| 530 } | 461 } |
| 531 ash::internal::ShowWorkspace(workspace->window(), details); | 462 ash::internal::ShowWorkspace(workspace->window(), details); |
| 532 } | 463 } |
| 533 | 464 |
| 534 void WorkspaceManager::HideWorkspace( | 465 void WorkspaceManager::HideWorkspace( |
| 535 Workspace* workspace, | 466 Workspace* workspace, |
| 536 SwitchReason reason, | 467 SwitchReason reason) const { |
| 537 bool is_unminimizing_fullscreen_window) const { | |
| 538 WorkspaceAnimationDetails details; | 468 WorkspaceAnimationDetails details; |
| 539 details.direction = active_workspace_ == desktop_workspace() ? | 469 details.direction = active_workspace_ == desktop_workspace() ? |
| 540 WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN; | 470 WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN; |
| 541 switch (reason) { | 471 switch (reason) { |
| 542 case SWITCH_WINDOW_MADE_ACTIVE: | 472 case SWITCH_WINDOW_MADE_ACTIVE: |
| 543 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: | 473 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: |
| 544 details.animate_opacity = | 474 details.animate_opacity = |
| 545 ((active_workspace_ == desktop_workspace() || | 475 ((active_workspace_ == desktop_workspace() || |
| 546 workspace != desktop_workspace()) && | 476 workspace != desktop_workspace())); |
| 547 !is_unminimizing_fullscreen_window); | |
| 548 details.animate_scale = true; | 477 details.animate_scale = true; |
| 549 details.animate = true; | 478 details.animate = true; |
| 550 break; | 479 break; |
| 551 | 480 |
| 552 case SWITCH_VISIBILITY_CHANGED: | |
| 553 // The window is most likely closing. Make the workspace visible for the | |
| 554 // duration of the switch so that the close animation is visible. | |
| 555 details.animate = true; | |
| 556 details.animate_scale = true; | |
| 557 break; | |
| 558 | |
| 559 case SWITCH_FULLSCREEN_FROM_FULLSCREEN_WORKSPACE: | |
| 560 case SWITCH_MAXIMIZED_OR_RESTORED: | |
| 561 if (active_workspace_->is_fullscreen()) { | |
| 562 // Delay the hide until the animation is done. | |
| 563 details.duration = | |
| 564 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); | |
| 565 details.animate = true; | |
| 566 } | |
| 567 break; | |
| 568 | |
| 569 // Remaining cases require no animation. | 481 // Remaining cases require no animation. |
| 570 default: | 482 default: |
| 571 break; | 483 break; |
| 572 } | 484 } |
| 573 ash::internal::HideWorkspace(workspace->window(), details); | 485 ash::internal::HideWorkspace(workspace->window(), details); |
| 574 } | 486 } |
| 575 | 487 |
| 576 void WorkspaceManager::ProcessDeletion() { | 488 void WorkspaceManager::ProcessDeletion() { |
| 577 std::set<Workspace*> to_delete; | 489 std::set<Workspace*> to_delete; |
| 578 to_delete.swap(to_delete_); | 490 to_delete.swap(to_delete_); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 608 | 520 |
| 609 void WorkspaceManager::OnWillRemoveWindowFromWorkspace(Workspace* workspace, | 521 void WorkspaceManager::OnWillRemoveWindowFromWorkspace(Workspace* workspace, |
| 610 Window* child) { | 522 Window* child) { |
| 611 if (child->TargetVisibility()) | 523 if (child->TargetVisibility()) |
| 612 RearrangeVisibleWindowOnHideOrRemove(child); | 524 RearrangeVisibleWindowOnHideOrRemove(child); |
| 613 child->ClearProperty(kWorkspaceKey); | 525 child->ClearProperty(kWorkspaceKey); |
| 614 } | 526 } |
| 615 | 527 |
| 616 void WorkspaceManager::OnWindowRemovedFromWorkspace(Workspace* workspace, | 528 void WorkspaceManager::OnWindowRemovedFromWorkspace(Workspace* workspace, |
| 617 Window* child) { | 529 Window* child) { |
| 618 if (workspace->ShouldMoveToPending()) | |
| 619 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_WINDOW_REMOVED); | |
| 620 UpdateShelfVisibility(); | 530 UpdateShelfVisibility(); |
| 621 } | 531 } |
| 622 | 532 |
| 623 void WorkspaceManager::OnWorkspaceChildWindowVisibilityChanged( | 533 void WorkspaceManager::OnWorkspaceChildWindowVisibilityChanged( |
| 624 Workspace* workspace, | 534 Workspace* workspace, |
| 625 Window* child) { | 535 Window* child) { |
| 626 if (workspace->ShouldMoveToPending()) { | 536 if (child->TargetVisibility()) |
| 627 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_VISIBILITY_CHANGED); | 537 RearrangeVisibleWindowOnShow(child); |
| 628 } else { | 538 else |
| 629 if (child->TargetVisibility()) | 539 RearrangeVisibleWindowOnHideOrRemove(child); |
| 630 RearrangeVisibleWindowOnShow(child); | 540 if (workspace == active_workspace_) { |
| 631 else | 541 UpdateShelfVisibility(); |
| 632 RearrangeVisibleWindowOnHideOrRemove(child); | 542 FramePainter::UpdateSoloWindowHeader(child->GetRootWindow()); |
| 633 if (workspace == active_workspace_) { | |
| 634 UpdateShelfVisibility(); | |
| 635 FramePainter::UpdateSoloWindowHeader(child->GetRootWindow()); | |
| 636 } | |
| 637 } | 543 } |
| 638 } | 544 } |
| 639 | 545 |
| 640 void WorkspaceManager::OnWorkspaceWindowChildBoundsChanged( | 546 void WorkspaceManager::OnWorkspaceWindowChildBoundsChanged( |
| 641 Workspace* workspace, | 547 Workspace* workspace, |
| 642 Window* child) { | 548 Window* child) { |
| 643 if (workspace == active_workspace_) | 549 if (workspace == active_workspace_) |
| 644 UpdateShelfVisibility(); | 550 UpdateShelfVisibility(); |
| 645 } | 551 } |
| 646 | 552 |
| 647 void WorkspaceManager::OnWorkspaceWindowShowStateChanged( | 553 void WorkspaceManager::OnWorkspaceWindowShowStateChanged( |
| 648 Workspace* workspace, | 554 Workspace* workspace, |
| 649 Window* child, | 555 Window* child, |
| 650 ui::WindowShowState last_show_state, | 556 ui::WindowShowState last_show_state) { |
| 651 ui::Layer* old_layer) { | |
| 652 // |child| better still be in |workspace| else things have gone wrong. | 557 // |child| better still be in |workspace| else things have gone wrong. |
| 653 DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey)); | 558 DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey)); |
| 654 | 559 |
| 655 if (wm::IsWindowMinimized(child)) { | 560 if (!wm::IsWindowMinimized(child) && workspace != desktop_workspace()) { |
| 656 if (workspace->ShouldMoveToPending()) | 561 { |
| 657 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_MINIMIZED); | 562 base::AutoReset<bool> setter(&in_move_, true); |
| 658 DCHECK(!old_layer); | 563 ReparentWindow(child, desktop_workspace()->window(), NULL); |
| 659 } else { | |
| 660 // Set of cases to deal with: | |
| 661 // . More than one fullscreen window: move newly fullscreen window into | |
| 662 // own workspace. | |
| 663 // . One fullscreen window and not in a fullscreen workspace: move window | |
| 664 // into own workspace. | |
| 665 // . No fullscreen window and not in desktop: move to desktop and further | |
| 666 // any existing windows are stacked beneath |child|. | |
| 667 const bool is_active = wm::IsActiveWindow(child); | |
| 668 Workspace* new_workspace = NULL; | |
| 669 const int full_count = workspace->GetNumFullscreenWindows(); | |
| 670 base::TimeDelta duration = (old_layer && !wm::IsWindowFullscreen(child)) ? | |
| 671 GetCrossFadeDuration(old_layer->bounds(), child->bounds()) : | |
| 672 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); | |
| 673 if (full_count == 0) { | |
| 674 if (workspace != desktop_workspace()) { | |
| 675 { | |
| 676 base::AutoReset<bool> setter(&in_move_, true); | |
| 677 ReparentWindow(child, desktop_workspace()->window(), NULL); | |
| 678 } | |
| 679 DCHECK(!is_active || old_layer); | |
| 680 new_workspace = desktop_workspace(); | |
| 681 SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED); | |
| 682 MoveWorkspaceToPendingOrDelete(workspace, child, | |
| 683 SWITCH_MAXIMIZED_OR_RESTORED); | |
| 684 if (FindWorkspace(workspace) == workspaces_.end()) | |
| 685 workspace = NULL; | |
| 686 } | |
| 687 } else if ((full_count == 1 && workspace == desktop_workspace()) || | |
| 688 full_count > 1) { | |
| 689 new_workspace = CreateWorkspace(true); | |
| 690 pending_workspaces_.insert(new_workspace); | |
| 691 ReparentWindow(child, new_workspace->window(), NULL); | |
| 692 } | 564 } |
| 693 if (is_active && new_workspace) { | 565 SetActiveWorkspace(desktop_workspace(), SWITCH_MAXIMIZED_OR_RESTORED); |
| 694 // |old_layer| may be NULL if as part of processing | 566 MoveWorkspaceToPendingOrDelete(workspace, |
| 695 // WorkspaceLayoutManager::OnWindowPropertyChanged() the window is made | 567 child, |
| 696 // active. | 568 SWITCH_MAXIMIZED_OR_RESTORED); |
| 697 if (old_layer) { | |
| 698 SetActiveWorkspace(new_workspace, | |
| 699 full_count >= 2 ? | |
| 700 SWITCH_FULLSCREEN_FROM_FULLSCREEN_WORKSPACE : | |
| 701 SWITCH_MAXIMIZED_OR_RESTORED); | |
| 702 CrossFadeWindowBetweenWorkspaces(new_workspace->window(), child, | |
| 703 old_layer); | |
| 704 if (workspace == desktop_workspace() || | |
| 705 new_workspace == desktop_workspace()) { | |
| 706 FadeDesktop(child, duration); | |
| 707 } | |
| 708 } else { | |
| 709 SetActiveWorkspace(new_workspace, SWITCH_OTHER); | |
| 710 } | |
| 711 } else { | |
| 712 if (last_show_state == ui::SHOW_STATE_MINIMIZED) | |
| 713 SetUnminimizingWorkspace(new_workspace ? new_workspace : workspace); | |
| 714 DCHECK(!old_layer); | |
| 715 } | |
| 716 } | 569 } |
| 717 UpdateShelfVisibility(); | 570 UpdateShelfVisibility(); |
| 718 } | 571 } |
| 719 | 572 |
| 720 void WorkspaceManager::OnTrackedByWorkspaceChanged(Workspace* workspace, | 573 void WorkspaceManager::OnTrackedByWorkspaceChanged(Workspace* workspace, |
| 721 aura::Window* window) { | 574 aura::Window* window) { |
| 722 Workspace* new_workspace = NULL; | 575 if (workspace == active_workspace_) |
| 723 if (wm::IsWindowFullscreen(window)) { | |
| 724 if (workspace->is_fullscreen() && | |
| 725 workspace->GetNumFullscreenWindows() == 1) { | |
| 726 // If |window| is the only window in a fullscreen workspace then leave | |
| 727 // it there. Additionally animate it back to the origin. | |
| 728 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 729 // All bounds changes get routed through WorkspaceLayoutManager and since | |
| 730 // the window is fullscreen WorkspaceLayoutManager is going to force a | |
| 731 // value. In other words, it doesn't matter what we supply to SetBounds() | |
| 732 // here. | |
| 733 window->SetBounds(gfx::Rect()); | |
| 734 return; | |
| 735 } | |
| 736 new_workspace = CreateWorkspace(true); | |
| 737 pending_workspaces_.insert(new_workspace); | |
| 738 } else if (workspace->is_fullscreen()) { | |
| 739 new_workspace = desktop_workspace(); | |
| 740 } else { | |
| 741 return; | 576 return; |
| 742 } | 577 |
| 743 // If the window is active we need to make sure the destination Workspace | 578 // If the window is active we need to make sure the destination Workspace |
| 744 // window is showing. Otherwise the window will be parented to a hidden window | 579 // window is showing. Otherwise the window will be parented to a hidden window |
| 745 // and lose activation. | 580 // and lose activation. |
| 746 const bool is_active = wm::IsActiveWindow(window); | 581 const bool is_active = wm::IsActiveWindow(window); |
| 747 if (is_active) | 582 if (is_active) |
| 748 new_workspace->window()->Show(); | 583 workspace->window()->Show(); |
| 749 ReparentWindow(window, new_workspace->window(), NULL); | 584 ReparentWindow(window, workspace->window(), NULL); |
| 750 if (is_active) { | 585 if (is_active) |
| 751 SetActiveWorkspace(new_workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED); | 586 SetActiveWorkspace(workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED); |
| 752 } | |
| 753 } | 587 } |
| 754 | 588 |
| 755 } // namespace internal | 589 } // namespace internal |
| 756 } // namespace ash | 590 } // namespace ash |
| OLD | NEW |