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 |