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_controller.h"
6
7 #include <utility>
8
9 #include "ash/public/cpp/shell_window_ids.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/shelf/shelf.h"
12 #include "ash/shell.h"
13 #include "ash/wm/desks/desks_util.h"
14 #include "ash/wm/fullscreen_window_finder.h"
15 #include "ash/wm/mru_window_tracker.h"
16 #include "ash/wm/overview/overview_controller.h"
17 #include "ash/wm/window_animations.h"
18 #include "ash/wm/window_state.h"
19 #include "ash/wm/workspace/backdrop_controller.h"
20 #include "ash/wm/workspace/workspace_event_handler.h"
21 #include "ash/wm/workspace/workspace_layout_manager.h"
22 #include "ui/aura/window.h"
23 #include "ui/compositor/layer.h"
24 #include "ui/compositor/scoped_layer_animation_settings.h"
25 #include "ui/wm/core/window_animations.h"
26
27 // Defines a window property to store a WorkspaceController in the properties of
28 // virtual desks container windows.
29 ASH_EXPORT extern const aura::WindowProperty<ash::WorkspaceController*>* const
30 kWorkspaceController;
31
32 DEFINE_UI_CLASS_PROPERTY_TYPE(ash::WorkspaceController*)
33
34 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ash::WorkspaceController,
35 kWorkspaceController,
36 nullptr)
37
38 namespace ash {
39 namespace {
40
41 // Amount of time to pause before animating anything. Only used during initial
42 // animation (when logging in).
43 const int kInitialPauseTimeMS = 750;
44
45 // The duration of the animation that occurs on first login.
46 const int kInitialAnimationDurationMS = 200;
47
48 } // namespace
49
WorkspaceController(aura::Window * viewport)50 WorkspaceController::WorkspaceController(aura::Window* viewport)
51 : viewport_(viewport),
52 event_handler_(std::make_unique<WorkspaceEventHandler>(viewport)),
53 layout_manager_(new WorkspaceLayoutManager(viewport)) {
54 viewport_->AddObserver(this);
55 ::wm::SetWindowVisibilityAnimationTransition(viewport_, ::wm::ANIMATE_NONE);
56 viewport_->SetLayoutManager(layout_manager_);
57 }
58
~WorkspaceController()59 WorkspaceController::~WorkspaceController() {
60 if (!viewport_)
61 return;
62
63 viewport_->RemoveObserver(this);
64 viewport_->SetLayoutManager(nullptr);
65 }
66
GetWindowState() const67 WorkspaceWindowState WorkspaceController::GetWindowState() const {
68 if (!viewport_)
69 return WorkspaceWindowState::kDefault;
70
71 // Always use DEFAULT state in overview mode so that work area stays
72 // the same regardles of the window we have.
73 // The |overview_controller| can be null during shutdown.
74 if (Shell::Get()->overview_controller() &&
75 Shell::Get()->overview_controller()->InOverviewSession()) {
76 return WorkspaceWindowState::kDefault;
77 }
78
79 const aura::Window* fullscreen =
80 GetWindowForFullscreenModeForContext(viewport_);
81 if (fullscreen)
82 return WorkspaceWindowState::kFullscreen;
83
84 auto mru_list =
85 Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal(
86 kActiveDesk);
87
88 for (aura::Window* window : mru_list) {
89 if (window->GetRootWindow() != viewport_->GetRootWindow())
90 continue;
91 WindowState* window_state = WindowState::Get(window);
92 if (window->layer() && !window->layer()->GetTargetVisibility())
93 continue;
94 if (window_state->IsMaximized())
95 return WorkspaceWindowState::kMaximized;
96 }
97 return WorkspaceWindowState::kDefault;
98 }
99
DoInitialAnimation()100 void WorkspaceController::DoInitialAnimation() {
101 viewport_->Show();
102
103 ui::Layer* layer = viewport_->layer();
104 layer->SetOpacity(0.0f);
105 SetTransformForScaleAnimation(layer, LAYER_SCALE_ANIMATION_ABOVE);
106
107 // In order for pause to work we need to stop animations.
108 layer->GetAnimator()->StopAnimating();
109
110 {
111 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
112
113 settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
114 layer->GetAnimator()->SchedulePauseForProperties(
115 base::TimeDelta::FromMilliseconds(kInitialPauseTimeMS),
116 ui::LayerAnimationElement::TRANSFORM |
117 ui::LayerAnimationElement::OPACITY |
118 ui::LayerAnimationElement::BRIGHTNESS |
119 ui::LayerAnimationElement::VISIBILITY);
120 settings.SetTweenType(gfx::Tween::EASE_OUT);
121 settings.SetTransitionDuration(
122 base::TimeDelta::FromMilliseconds(kInitialAnimationDurationMS));
123 layer->SetTransform(gfx::Transform());
124 layer->SetOpacity(1.0f);
125 }
126 }
127
OnWindowDestroying(aura::Window * window)128 void WorkspaceController::OnWindowDestroying(aura::Window* window) {
129 DCHECK_EQ(window, viewport_);
130 viewport_->RemoveObserver(this);
131 viewport_ = nullptr;
132 // Destroy |event_handler_| too as it depends upon |window|.
133 event_handler_.reset();
134 layout_manager_ = nullptr;
135 }
136
SetWorkspaceController(aura::Window * desk_container,WorkspaceController * workspace_controller)137 void SetWorkspaceController(aura::Window* desk_container,
138 WorkspaceController* workspace_controller) {
139 DCHECK(desk_container);
140 DCHECK(desks_util::IsDeskContainer(desk_container));
141
142 if (workspace_controller)
143 desk_container->SetProperty(kWorkspaceController, workspace_controller);
144 else
145 desk_container->ClearProperty(kWorkspaceController);
146 }
147
GetWorkspaceController(aura::Window * desk_container)148 WorkspaceController* GetWorkspaceController(aura::Window* desk_container) {
149 DCHECK(desk_container);
150 DCHECK(desks_util::IsDeskContainer(desk_container));
151
152 return desk_container->GetProperty(kWorkspaceController);
153 }
154
GetWorkspaceControllerForContext(aura::Window * context)155 WorkspaceController* GetWorkspaceControllerForContext(aura::Window* context) {
156 DCHECK(!context->IsRootWindow());
157
158 // Find the desk container to which |context| belongs.
159 while (context && !desks_util::IsDeskContainer(context))
160 context = context->parent();
161
162 if (!context)
163 return nullptr;
164
165 return GetWorkspaceController(context);
166 }
167
GetActiveWorkspaceController(aura::Window * root)168 WorkspaceController* GetActiveWorkspaceController(aura::Window* root) {
169 DCHECK(root->IsRootWindow());
170
171 return GetWorkspaceController(
172 desks_util::GetActiveDeskContainerForRoot(root));
173 }
174
175 } // namespace ash
176