Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Side by Side Diff: ash/wm/workspace/workspace_manager2.cc

Issue 11293014: Renames Workspace*2 -> Workspace*. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/wm/workspace/workspace_manager2.h ('k') | ash/wm/workspace/workspace_manager2_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ash/wm/workspace/workspace_manager2.h"
6
7 #include <algorithm>
8 #include <functional>
9
10 #include "ash/ash_switches.h"
11 #include "ash/root_window_controller.h"
12 #include "ash/shell.h"
13 #include "ash/shell_window_ids.h"
14 #include "ash/wm/base_layout_manager.h"
15 #include "ash/wm/property_util.h"
16 #include "ash/wm/shelf_layout_manager.h"
17 #include "ash/wm/window_animations.h"
18 #include "ash/wm/window_properties.h"
19 #include "ash/wm/window_util.h"
20 #include "ash/wm/workspace/auto_window_management.h"
21 #include "ash/wm/workspace/desktop_background_fade_controller.h"
22 #include "ash/wm/workspace/workspace_animations.h"
23 #include "ash/wm/workspace/workspace_layout_manager2.h"
24 #include "ash/wm/workspace/workspace2.h"
25 #include "base/auto_reset.h"
26 #include "base/command_line.h"
27 #include "base/logging.h"
28 #include "base/stl_util.h"
29 #include "ui/aura/client/aura_constants.h"
30 #include "ui/aura/root_window.h"
31 #include "ui/aura/window.h"
32 #include "ui/aura/window_property.h"
33 #include "ui/base/ui_base_types.h"
34 #include "ui/compositor/layer.h"
35 #include "ui/compositor/layer_animator.h"
36 #include "ui/compositor/scoped_layer_animation_settings.h"
37 #include "ui/views/widget/widget.h"
38
39 DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::Workspace2*);
40 DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ASH_EXPORT, ui::WindowShowState);
41
42 using aura::Window;
43
44 namespace ash {
45 namespace internal {
46
47 DEFINE_WINDOW_PROPERTY_KEY(Workspace2*, kWorkspaceKey, NULL);
48
49 namespace {
50
51 // Duration for fading out the desktop background when maximizing.
52 const int kCrossFadeSwitchTimeMS = 700;
53
54 // Amount of time to pause before animating anything. Only used during initial
55 // animation (when logging in).
56 const int kInitialPauseTimeMS = 750;
57
58 // Changes the parent of |window| and all its transient children to
59 // |new_parent|. If |stack_beneach| is non-NULL all the windows are stacked
60 // beneath it.
61 void ReparentWindow(Window* window,
62 Window* new_parent,
63 Window* stack_beneath) {
64 window->SetParent(new_parent);
65 if (stack_beneath)
66 new_parent->StackChildBelow(window, stack_beneath);
67 for (size_t i = 0; i < window->transient_children().size(); ++i)
68 ReparentWindow(window->transient_children()[i], new_parent, stack_beneath);
69 }
70
71 } // namespace
72
73 // Workspace -------------------------------------------------------------------
74
75 // LayoutManager installed on the parent window of all the Workspace window (eg
76 // |WorkspaceManager2::contents_view_|).
77 class WorkspaceManager2::LayoutManagerImpl : public BaseLayoutManager {
78 public:
79 explicit LayoutManagerImpl(WorkspaceManager2* workspace_manager)
80 : BaseLayoutManager(workspace_manager->contents_view_->GetRootWindow()),
81 workspace_manager_(workspace_manager) {
82 }
83 virtual ~LayoutManagerImpl() {}
84
85 // Overridden from BaseWorkspaceLayoutManager:
86 virtual void OnWindowResized() OVERRIDE {
87 for (size_t i = 0; i < window()->children().size(); ++i)
88 window()->children()[i]->SetBounds(gfx::Rect(window()->bounds().size()));
89 }
90 virtual void OnWindowAddedToLayout(Window* child) OVERRIDE {
91 // Only workspaces should be added as children.
92 DCHECK((child->id() == kShellWindowId_WorkspaceContainer) ||
93 workspace_manager_->creating_fade_);
94 child->SetBounds(gfx::Rect(window()->bounds().size()));
95 }
96
97 private:
98 aura::Window* window() { return workspace_manager_->contents_view_; }
99
100 WorkspaceManager2* workspace_manager_;
101
102 DISALLOW_COPY_AND_ASSIGN(LayoutManagerImpl);
103 };
104
105 // WorkspaceManager2 -----------------------------------------------------------
106
107 WorkspaceManager2::WorkspaceManager2(Window* contents_view)
108 : contents_view_(contents_view),
109 active_workspace_(NULL),
110 shelf_(NULL),
111 in_move_(false),
112 ALLOW_THIS_IN_INITIALIZER_LIST(
113 clear_unminimizing_workspace_factory_(this)),
114 unminimizing_workspace_(NULL),
115 app_terminating_(false),
116 creating_fade_(false) {
117 // Clobber any existing event filter.
118 contents_view->SetEventFilter(NULL);
119 // |contents_view| takes ownership of LayoutManagerImpl.
120 contents_view->SetLayoutManager(new LayoutManagerImpl(this));
121 active_workspace_ = CreateWorkspace(false);
122 workspaces_.push_back(active_workspace_);
123 active_workspace_->window()->Show();
124 Shell::GetInstance()->AddShellObserver(this);
125 }
126
127 WorkspaceManager2::~WorkspaceManager2() {
128 Shell::GetInstance()->RemoveShellObserver(this);
129 // Release the windows, they'll be destroyed when |contents_view_| is
130 // destroyed.
131 std::for_each(workspaces_.begin(), workspaces_.end(),
132 std::mem_fun(&Workspace2::ReleaseWindow));
133 std::for_each(pending_workspaces_.begin(), pending_workspaces_.end(),
134 std::mem_fun(&Workspace2::ReleaseWindow));
135 std::for_each(to_delete_.begin(), to_delete_.end(),
136 std::mem_fun(&Workspace2::ReleaseWindow));
137 STLDeleteElements(&workspaces_);
138 STLDeleteElements(&pending_workspaces_);
139 STLDeleteElements(&to_delete_);
140 }
141
142 // static
143 bool WorkspaceManager2::IsMaximized(Window* window) {
144 return IsMaximizedState(window->GetProperty(aura::client::kShowStateKey));
145 }
146
147 // static
148 bool WorkspaceManager2::IsMaximizedState(ui::WindowShowState state) {
149 return state == ui::SHOW_STATE_MAXIMIZED ||
150 state == ui::SHOW_STATE_FULLSCREEN;
151 }
152
153 // static
154 bool WorkspaceManager2::WillRestoreMaximized(Window* window) {
155 return wm::IsWindowMinimized(window) &&
156 IsMaximizedState(window->GetProperty(internal::kRestoreShowStateKey));
157 }
158
159 WorkspaceWindowState WorkspaceManager2::GetWindowState() const {
160 if (!shelf_)
161 return WORKSPACE_WINDOW_STATE_DEFAULT;
162
163 const bool is_active_maximized = active_workspace_->is_maximized();
164 const gfx::Rect shelf_bounds(shelf_->GetIdealBounds());
165 const Window::Windows& windows(active_workspace_->window()->children());
166 bool window_overlaps_launcher = false;
167 bool has_maximized_window = false;
168 for (Window::Windows::const_iterator i = windows.begin();
169 i != windows.end(); ++i) {
170 if (GetIgnoredByShelf(*i))
171 continue;
172 ui::Layer* layer = (*i)->layer();
173 if (!layer->GetTargetVisibility() || layer->GetTargetOpacity() == 0.0f)
174 continue;
175 // Ignore maximized/fullscreen windows if we're in the desktop. Such a state
176 // is transitory and means we haven't yet switched. If we did consider such
177 // windows we'll return the wrong thing, which can lead to prematurely
178 // changing the launcher state and clobbering restore bounds.
179 if (is_active_maximized) {
180 if (wm::IsWindowMaximized(*i)) {
181 // An untracked window may still be fullscreen so we keep iterating when
182 // we hit a maximized window.
183 has_maximized_window = true;
184 } else if (wm::IsWindowFullscreen(*i)) {
185 return WORKSPACE_WINDOW_STATE_FULL_SCREEN;
186 }
187 }
188 if (!window_overlaps_launcher && (*i)->bounds().Intersects(shelf_bounds))
189 window_overlaps_launcher = true;
190 }
191 if (has_maximized_window)
192 return WORKSPACE_WINDOW_STATE_MAXIMIZED;
193
194 return window_overlaps_launcher ?
195 WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF :
196 WORKSPACE_WINDOW_STATE_DEFAULT;
197 }
198
199 void WorkspaceManager2::SetShelf(ShelfLayoutManager* shelf) {
200 shelf_ = shelf;
201 }
202
203 void WorkspaceManager2::SetActiveWorkspaceByWindow(Window* window) {
204 Workspace2* workspace = FindBy(window);
205 if (!workspace)
206 return;
207
208 if (workspace != active_workspace_) {
209 // A window is being made active. In the following cases we reparent to
210 // the active desktop:
211 // . The window is not tracked by workspace code. This is used for tab
212 // dragging. Since tab dragging needs to happen in the active workspace we
213 // have to reparent the window (otherwise the window you dragged the tab
214 // out of would disappear since the workspace changed). Since this case is
215 // only transiently used (property reset on input release) we don't worry
216 // about window state. In fact we can't consider window state here as we
217 // have to allow dragging of a maximized window to work in this case.
218 // . The window persists across all workspaces. For example, the task
219 // manager is in the desktop worskpace and the current workspace is
220 // maximized. If we swapped to the desktop you would lose context. Instead
221 // we reparent. The exception to this is if the window is maximized (it
222 // needs its own workspace then) or we're in the process of maximizing. If
223 // we're in the process of maximizing the window needs its own workspace.
224 if (!GetTrackedByWorkspace(window) ||
225 (GetPersistsAcrossAllWorkspaces(window) && !IsMaximized(window) &&
226 !(wm::IsWindowMinimized(window) && WillRestoreMaximized(window)))) {
227 ReparentWindow(window, active_workspace_->window(), NULL);
228 } else {
229 SetActiveWorkspace(workspace, SWITCH_WINDOW_MADE_ACTIVE,
230 base::TimeDelta());
231 }
232 }
233 if (workspace->is_maximized() && IsMaximized(window)) {
234 // Clicking on the maximized window in a maximized workspace. Force all
235 // other windows to drop to the desktop.
236 MoveChildrenToDesktop(workspace->window(), NULL);
237 }
238 }
239
240 Window* WorkspaceManager2::GetParentForNewWindow(Window* window) {
241 // Try to put windows with transient parents in the same workspace as their
242 // transient parent.
243 if (window->transient_parent() && !IsMaximized(window)) {
244 Workspace2* workspace = FindBy(window->transient_parent());
245 if (workspace)
246 return workspace->window();
247 // Fall through to normal logic.
248 }
249
250 if (!GetTrackedByWorkspace(window))
251 return active_workspace_->window();
252
253 if (IsMaximized(window)) {
254 // Wait for the window to be made active before showing the workspace.
255 Workspace2* workspace = CreateWorkspace(true);
256 pending_workspaces_.insert(workspace);
257 return workspace->window();
258 }
259
260 if (!GetTrackedByWorkspace(window) || GetPersistsAcrossAllWorkspaces(window))
261 return active_workspace_->window();
262
263 return desktop_workspace()->window();
264 }
265
266 void WorkspaceManager2::DoInitialAnimation() {
267 if (active_workspace_->is_maximized()) {
268 RootWindowController* root_controller = GetRootWindowController(
269 contents_view_->GetRootWindow());
270 if (root_controller) {
271 aura::Window* background = root_controller->GetContainer(
272 kShellWindowId_DesktopBackgroundContainer);
273 background->Show();
274 ShowOrHideDesktopBackground(background, SWITCH_INITIAL,
275 base::TimeDelta(), false);
276 }
277 }
278 ShowWorkspace(active_workspace_, active_workspace_, SWITCH_INITIAL);
279 }
280
281 void WorkspaceManager2::OnAppTerminating() {
282 app_terminating_ = true;
283 }
284
285 void WorkspaceManager2::UpdateShelfVisibility() {
286 if (shelf_)
287 shelf_->UpdateVisibilityState();
288 }
289
290 Workspace2* WorkspaceManager2::FindBy(Window* window) const {
291 while (window) {
292 Workspace2* workspace = window->GetProperty(kWorkspaceKey);
293 if (workspace)
294 return workspace;
295 window = window->parent();
296 }
297 return NULL;
298 }
299
300 void WorkspaceManager2::SetActiveWorkspace(Workspace2* workspace,
301 SwitchReason reason,
302 base::TimeDelta duration) {
303 DCHECK(workspace);
304 if (active_workspace_ == workspace)
305 return;
306
307 pending_workspaces_.erase(workspace);
308
309 // Adjust the z-order. No need to adjust the z-order for the desktop since
310 // it always stays at the bottom.
311 if (workspace != desktop_workspace() &&
312 FindWorkspace(workspace) == workspaces_.end()) {
313 contents_view_->StackChildAbove(workspace->window(),
314 workspaces_.back()->window());
315 workspaces_.push_back(workspace);
316 }
317
318 Workspace2* last_active = active_workspace_;
319 active_workspace_ = workspace;
320
321 // The display work-area may have changed while |workspace| was not the active
322 // workspace. Give it a chance to adjust its state for the new work-area.
323 active_workspace_->workspace_layout_manager()->
324 OnDisplayWorkAreaInsetsChanged();
325
326 const bool is_unminimizing_maximized_window =
327 unminimizing_workspace_ && unminimizing_workspace_ == active_workspace_ &&
328 active_workspace_->is_maximized();
329 if (is_unminimizing_maximized_window) {
330 // If we're unminimizing a window it needs to be on the top, otherwise you
331 // won't see the animation.
332 contents_view_->StackChildAtTop(active_workspace_->window());
333 } else if (active_workspace_->is_maximized() && last_active->is_maximized()) {
334 // When switching between maximized windows we need the last active
335 // workspace on top of the new, otherwise the animations won't look
336 // right. Since only one workspace is visible at a time stacking order of
337 // the workspace windows ultimately doesn't matter.
338 contents_view_->StackChildAtTop(last_active->window());
339 }
340
341 UpdateShelfVisibility();
342
343 // NOTE: duration supplied to this method is only used for desktop background.
344 HideWorkspace(last_active, reason, is_unminimizing_maximized_window);
345 ShowWorkspace(workspace, last_active, reason);
346
347 RootWindowController* root_controller = GetRootWindowController(
348 contents_view_->GetRootWindow());
349 if (root_controller) {
350 aura::Window* background = root_controller->GetContainer(
351 kShellWindowId_DesktopBackgroundContainer);
352 if (last_active == desktop_workspace()) {
353 ShowOrHideDesktopBackground(background, reason, duration, false);
354 } else if (active_workspace_ == desktop_workspace() && !app_terminating_) {
355 ShowOrHideDesktopBackground(background, reason, duration, true);
356 }
357 }
358 }
359
360 WorkspaceManager2::Workspaces::iterator
361 WorkspaceManager2::FindWorkspace(Workspace2* workspace) {
362 return std::find(workspaces_.begin(), workspaces_.end(), workspace);
363 }
364
365 Workspace2* WorkspaceManager2::CreateWorkspace(bool maximized) {
366 return new Workspace2(this, contents_view_, maximized);
367 }
368
369 void WorkspaceManager2::MoveWorkspaceToPendingOrDelete(
370 Workspace2* workspace,
371 Window* stack_beneath,
372 SwitchReason reason) {
373 // We're all ready moving windows.
374 if (in_move_)
375 return;
376
377 DCHECK_NE(desktop_workspace(), workspace);
378
379 if (workspace == active_workspace_)
380 SelectNextWorkspace(reason);
381
382 AutoReset<bool> setter(&in_move_, true);
383
384 MoveChildrenToDesktop(workspace->window(), stack_beneath);
385
386 {
387 Workspaces::iterator workspace_i(FindWorkspace(workspace));
388 if (workspace_i != workspaces_.end())
389 workspaces_.erase(workspace_i);
390 }
391
392 if (workspace->window()->children().empty()) {
393 if (workspace == unminimizing_workspace_)
394 unminimizing_workspace_ = NULL;
395 pending_workspaces_.erase(workspace);
396 ScheduleDelete(workspace);
397 } else {
398 pending_workspaces_.insert(workspace);
399 }
400 }
401
402 void WorkspaceManager2::MoveChildrenToDesktop(aura::Window* window,
403 aura::Window* stack_beneath) {
404 // Build the list of windows to move. Exclude maximized/fullscreen and windows
405 // with transient parents.
406 Window::Windows to_move;
407 for (size_t i = 0; i < window->children().size(); ++i) {
408 Window* child = window->children()[i];
409 if (!child->transient_parent() && !IsMaximized(child) &&
410 !WillRestoreMaximized(child)) {
411 to_move.push_back(child);
412 }
413 }
414 // Move the windows, but make sure the window is still a child of |window|
415 // (moving may cascade and cause other windows to move).
416 for (size_t i = 0; i < to_move.size(); ++i) {
417 if (std::find(window->children().begin(), window->children().end(),
418 to_move[i]) != window->children().end()) {
419 ReparentWindow(to_move[i], desktop_workspace()->window(),
420 stack_beneath);
421 }
422 }
423 }
424
425 void WorkspaceManager2::SelectNextWorkspace(SwitchReason reason) {
426 DCHECK_NE(active_workspace_, desktop_workspace());
427
428 Workspaces::const_iterator workspace_i(FindWorkspace(active_workspace_));
429 Workspaces::const_iterator next_workspace_i(workspace_i + 1);
430 if (next_workspace_i != workspaces_.end())
431 SetActiveWorkspace(*next_workspace_i, reason, base::TimeDelta());
432 else
433 SetActiveWorkspace(*(workspace_i - 1), reason, base::TimeDelta());
434 }
435
436 void WorkspaceManager2::ScheduleDelete(Workspace2* workspace) {
437 to_delete_.insert(workspace);
438 delete_timer_.Stop();
439 delete_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this,
440 &WorkspaceManager2::ProcessDeletion);
441 }
442
443 void WorkspaceManager2::SetUnminimizingWorkspace(Workspace2* workspace) {
444 // The normal sequence of unminimizing a window is: Show() the window, which
445 // triggers changing the kShowStateKey to NORMAL and lastly the window is made
446 // active. This means at the time the window is unminimized we don't know if
447 // the workspace it is in is going to become active. To track this
448 // |unminimizing_workspace_| is set at the time we unminimize and a task is
449 // schedule to reset it. This way when we get the activate we know we're in
450 // the process unminimizing and can do the right animation.
451 unminimizing_workspace_ = workspace;
452 if (unminimizing_workspace_) {
453 MessageLoop::current()->PostTask(
454 FROM_HERE,
455 base::Bind(&WorkspaceManager2::SetUnminimizingWorkspace,
456 clear_unminimizing_workspace_factory_.GetWeakPtr(),
457 static_cast<Workspace2*>(NULL)));
458 }
459 }
460
461 void WorkspaceManager2::FadeDesktop(aura::Window* window,
462 base::TimeDelta duration) {
463 if (CommandLine::ForCurrentProcess()->HasSwitch(
464 ash::switches::kAshWindowAnimationsDisabled) ||
465 ui::LayerAnimator::disable_animations_for_test())
466 return;
467
468 AutoReset<bool> reseter(&creating_fade_, true);
469 DesktopBackgroundFadeController::Direction direction;
470 aura::Window* parent = NULL;
471 aura::Window* stack_above = NULL;
472 if (active_workspace_ == desktop_workspace()) {
473 direction = DesktopBackgroundFadeController::FADE_IN;
474 parent = desktop_workspace()->window();
475 stack_above = window;
476 } else {
477 direction = DesktopBackgroundFadeController::FADE_OUT;
478 parent = contents_view_;
479 stack_above = desktop_workspace()->window();
480 DCHECK_EQ(kCrossFadeSwitchTimeMS, (int)duration.InMilliseconds());
481 duration = base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS);
482 }
483 desktop_fade_controller_.reset(
484 new DesktopBackgroundFadeController(
485 parent, stack_above, duration, direction));
486 }
487
488 void WorkspaceManager2::ShowOrHideDesktopBackground(
489 aura::Window* window,
490 SwitchReason reason,
491 base::TimeDelta duration,
492 bool show) const {
493 WorkspaceAnimationDetails details;
494 details.animate = true;
495 details.direction = show ? WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN;
496 details.animate_scale = reason != SWITCH_MAXIMIZED_OR_RESTORED;
497 details.duration = duration;
498 if (reason == SWITCH_INITIAL)
499 details.pause_time_ms = kInitialPauseTimeMS;
500 if (show)
501 ash::internal::ShowWorkspace(window, details);
502 else
503 ash::internal::HideWorkspace(window, details);
504 }
505
506 void WorkspaceManager2::ShowWorkspace(
507 Workspace2* workspace,
508 Workspace2* last_active,
509 SwitchReason reason) const {
510 WorkspaceAnimationDetails details;
511 details.direction =
512 (last_active == desktop_workspace() || reason == SWITCH_INITIAL) ?
513 WORKSPACE_ANIMATE_DOWN : WORKSPACE_ANIMATE_UP;
514
515 switch (reason) {
516 case SWITCH_WINDOW_MADE_ACTIVE:
517 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED:
518 case SWITCH_WINDOW_REMOVED:
519 case SWITCH_VISIBILITY_CHANGED:
520 case SWITCH_MINIMIZED:
521 details.animate = details.animate_scale = true;
522 details.animate_opacity = last_active == desktop_workspace();
523 break;
524
525 case SWITCH_INITIAL:
526 details.animate = details.animate_opacity = details.animate_scale = true;
527 details.pause_time_ms = kInitialPauseTimeMS;
528 break;
529
530 // Remaining cases require no animation.
531 default:
532 break;
533 }
534 ash::internal::ShowWorkspace(workspace->window(), details);
535 }
536
537 void WorkspaceManager2::HideWorkspace(
538 Workspace2* workspace,
539 SwitchReason reason,
540 bool is_unminimizing_maximized_window) const {
541 WorkspaceAnimationDetails details;
542 details.direction = active_workspace_ == desktop_workspace() ?
543 WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN;
544 switch (reason) {
545 case SWITCH_WINDOW_MADE_ACTIVE:
546 case SWITCH_TRACKED_BY_WORKSPACE_CHANGED:
547 details.animate_opacity =
548 ((active_workspace_ == desktop_workspace() ||
549 workspace != desktop_workspace()) &&
550 !is_unminimizing_maximized_window);
551 details.animate_scale = true;
552 details.animate = true;
553 break;
554
555 case SWITCH_MAXIMIZED_OR_RESTORED:
556 if (active_workspace_->is_maximized()) {
557 // Delay the hide until the animation is done.
558 details.duration =
559 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS);
560 details.animate = true;
561 }
562 break;
563
564 // Remaining cases require no animation.
565 default:
566 break;
567 }
568 ash::internal::HideWorkspace(workspace->window(), details);
569 }
570
571 void WorkspaceManager2::ProcessDeletion() {
572 std::set<Workspace2*> to_delete;
573 to_delete.swap(to_delete_);
574 for (std::set<Workspace2*>::iterator i = to_delete.begin();
575 i != to_delete.end(); ++i) {
576 Workspace2* workspace = *i;
577 if (workspace->window()->layer()->children().empty()) {
578 delete workspace->ReleaseWindow();
579 delete workspace;
580 } else {
581 to_delete_.insert(workspace);
582 }
583 }
584 if (!to_delete_.empty()) {
585 delete_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this,
586 &WorkspaceManager2::ProcessDeletion);
587 }
588 }
589
590 void WorkspaceManager2::OnWindowAddedToWorkspace(Workspace2* workspace,
591 Window* child) {
592 child->SetProperty(kWorkspaceKey, workspace);
593 // Do nothing (other than updating shelf visibility) as the right parent was
594 // chosen by way of GetParentForNewWindow() or we explicitly moved the window
595 // to the workspace.
596 if (workspace == active_workspace_)
597 UpdateShelfVisibility();
598
599 RearrangeVisibleWindowOnShow(child);
600 }
601
602 void WorkspaceManager2::OnWillRemoveWindowFromWorkspace(Workspace2* workspace,
603 Window* child) {
604 if (child->TargetVisibility())
605 RearrangeVisibleWindowOnHideOrRemove(child);
606 child->ClearProperty(kWorkspaceKey);
607 }
608
609 void WorkspaceManager2::OnWindowRemovedFromWorkspace(Workspace2* workspace,
610 Window* child) {
611 if (workspace->ShouldMoveToPending())
612 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_WINDOW_REMOVED);
613 }
614
615 void WorkspaceManager2::OnWorkspaceChildWindowVisibilityChanged(
616 Workspace2* workspace,
617 Window* child) {
618 if (workspace->ShouldMoveToPending()) {
619 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_VISIBILITY_CHANGED);
620 } else {
621 if (child->TargetVisibility())
622 RearrangeVisibleWindowOnShow(child);
623 else
624 RearrangeVisibleWindowOnHideOrRemove(child);
625 if (workspace == active_workspace_)
626 UpdateShelfVisibility();
627 }
628 }
629
630 void WorkspaceManager2::OnWorkspaceWindowChildBoundsChanged(
631 Workspace2* workspace,
632 Window* child) {
633 if (workspace == active_workspace_)
634 UpdateShelfVisibility();
635 }
636
637 void WorkspaceManager2::OnWorkspaceWindowShowStateChanged(
638 Workspace2* workspace,
639 Window* child,
640 ui::WindowShowState last_show_state,
641 ui::Layer* old_layer) {
642 // |child| better still be in |workspace| else things have gone wrong.
643 DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey));
644 if (wm::IsWindowMinimized(child)) {
645 if (workspace->ShouldMoveToPending())
646 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_MINIMIZED);
647 DCHECK(!old_layer);
648 } else {
649 // Set of cases to deal with:
650 // . More than one maximized window: move newly maximized window into
651 // own workspace.
652 // . One maximized window and not in a maximized workspace: move window
653 // into own workspace.
654 // . No maximized window and not in desktop: move to desktop and further
655 // any existing windows are stacked beneath |child|.
656 const bool is_active = wm::IsActiveWindow(child);
657 Workspace2* new_workspace = NULL;
658 const int max_count = workspace->GetNumMaximizedWindows();
659 base::TimeDelta duration = old_layer && !IsMaximized(child) ?
660 GetCrossFadeDuration(old_layer->bounds(), child->bounds()) :
661 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS);
662 if (max_count == 0) {
663 if (workspace != desktop_workspace()) {
664 {
665 AutoReset<bool> setter(&in_move_, true);
666 ReparentWindow(child, desktop_workspace()->window(), NULL);
667 }
668 DCHECK(!is_active || old_layer);
669 new_workspace = desktop_workspace();
670 SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED,
671 duration);
672 MoveWorkspaceToPendingOrDelete(workspace, child,
673 SWITCH_MAXIMIZED_OR_RESTORED);
674 if (FindWorkspace(workspace) == workspaces_.end())
675 workspace = NULL;
676 }
677 } else if ((max_count == 1 && workspace == desktop_workspace()) ||
678 max_count > 1) {
679 new_workspace = CreateWorkspace(true);
680 pending_workspaces_.insert(new_workspace);
681 ReparentWindow(child, new_workspace->window(), NULL);
682 }
683 if (is_active && new_workspace) {
684 // |old_layer| may be NULL if as part of processing
685 // WorkspaceLayoutManager2::OnWindowPropertyChanged() the window is made
686 // active.
687 if (old_layer) {
688 SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED,
689 duration);
690 CrossFadeWindowBetweenWorkspaces(new_workspace->window(), child,
691 old_layer);
692 if (workspace == desktop_workspace() ||
693 new_workspace == desktop_workspace()) {
694 FadeDesktop(child, duration);
695 }
696 } else {
697 SetActiveWorkspace(new_workspace, SWITCH_OTHER, base::TimeDelta());
698 }
699 } else {
700 if (last_show_state == ui::SHOW_STATE_MINIMIZED)
701 SetUnminimizingWorkspace(new_workspace ? new_workspace : workspace);
702 DCHECK(!old_layer);
703 }
704 }
705 UpdateShelfVisibility();
706 }
707
708 void WorkspaceManager2::OnTrackedByWorkspaceChanged(Workspace2* workspace,
709 aura::Window* window) {
710 Workspace2* new_workspace = NULL;
711 if (IsMaximized(window)) {
712 new_workspace = CreateWorkspace(true);
713 pending_workspaces_.insert(new_workspace);
714 } else if (workspace->is_maximized()) {
715 new_workspace = desktop_workspace();
716 } else {
717 return;
718 }
719 // If the window is active we need to make sure the destination Workspace
720 // window is showing. Otherwise the window will be parented to a hidden window
721 // and lose activation.
722 const bool is_active = wm::IsActiveWindow(window);
723 if (is_active)
724 new_workspace->window()->Show();
725 ReparentWindow(window, new_workspace->window(), NULL);
726 if (is_active) {
727 SetActiveWorkspace(new_workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED,
728 base::TimeDelta());
729 }
730 }
731
732 } // namespace internal
733 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_manager2.h ('k') | ash/wm/workspace/workspace_manager2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698