1 // Copyright 2014 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.
5 #include "athena/screen/modal_window_controller.h"
7 #include "athena/screen/public/screen_manager.h"
8 #include "base/message_loop/message_loop.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_property.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/compositor/layer_animation_observer.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h"
14 #include "ui/wm/core/window_animations.h"
19 DEFINE_OWNED_WINDOW_PROPERTY_KEY(ModalWindowController
,
20 kModalWindowControllerKey
,
26 ModalWindowController
* ModalWindowController::Get(aura::Window
* container
) {
27 ModalWindowController
* controller
=
28 container
->GetProperty(kModalWindowControllerKey
);
33 ModalWindowController::ModalWindowController(int priority
)
34 : modal_container_(nullptr),
35 dimmer_window_(new aura::Window(nullptr)),
37 ScreenManager::ContainerParams
params("ModalContainer", priority
);
38 params
.can_activate_children
= true;
39 params
.block_events
= true;
40 modal_container_
= ScreenManager::Get()->CreateContainer(params
);
41 modal_container_
->SetProperty(kModalWindowControllerKey
, this);
43 dimmer_window_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
44 dimmer_window_
->Init(aura::WINDOW_LAYER_SOLID_COLOR
);
45 dimmer_window_
->layer()->SetColor(SK_ColorBLACK
);
46 dimmer_window_
->layer()->SetOpacity(0.0f
);
47 dimmer_window_
->Show();
49 modal_container_
->AddChild(dimmer_window_
);
50 modal_container_
->AddObserver(this);
52 UpdateDimmerWindowBounds();
55 ModalWindowController::~ModalWindowController() {
57 modal_container_
->RemoveObserver(this);
60 void ModalWindowController::OnWindowAdded(aura::Window
* child
) {
61 DCHECK_NE(child
, dimmer_window_
);
62 if (IsChildWindow(child
)) {
63 child
->AddObserver(this);
64 UpdateDimming(nullptr);
68 void ModalWindowController::OnWindowVisibilityChanged(aura::Window
* window
,
70 if (IsChildWindow(window
))
71 UpdateDimming(nullptr);
74 void ModalWindowController::OnWindowBoundsChanged(aura::Window
* window
,
75 const gfx::Rect
& old_bounds
,
76 const gfx::Rect
& new_bounds
) {
77 if (window
== modal_container_
)
78 UpdateDimmerWindowBounds();
81 void ModalWindowController::OnWindowDestroyed(aura::Window
* window
) {
82 UpdateDimming(window
);
85 bool ModalWindowController::IsChildWindow(aura::Window
* child
) const {
86 return child
->parent() == modal_container_
&& child
!= dimmer_window_
;
89 void ModalWindowController::UpdateDimmerWindowBounds() {
90 gfx::Rect
bounds(modal_container_
->bounds().size());
91 dimmer_window_
->SetBounds(bounds
);
94 void ModalWindowController::UpdateDimming(aura::Window
* ignore
) {
95 if (!modal_container_
|| !dimmer_window_
)
97 bool should_delete
= true;
98 for (aura::Window
* window
: modal_container_
->children()) {
99 if (window
== dimmer_window_
|| window
== ignore
)
101 should_delete
= false;
102 if (window
->TargetVisibility()) {
110 // Remove the container from root so that the container becomes
111 // invisible, but don't delete it until next event execution
112 // because the call stack may still have and use the pointer.
113 modal_container_
->RemoveObserver(this);
115 // Hide the window before removing it, so the focus manager which will run
116 // in RemoveChild handler can know that this container is no longer
118 modal_container_
->Hide();
120 modal_container_
->parent()->RemoveChild(modal_container_
);
121 base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE
, modal_container_
);
122 modal_container_
= nullptr;
123 dimmer_window_
= nullptr;
127 void ModalWindowController::SetDimmed(bool dimmed
) {
128 const float kDimmedOpacity
= 0.4f
;
130 if (!dimmer_window_
|| dimmed_
== dimmed
)
134 const int kDimmAnimationDurationMs
= 500;
136 ui::ScopedLayerAnimationSettings
settings(
137 dimmer_window_
->layer()->GetAnimator());
138 settings
.SetTransitionDuration(
139 base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs
));
140 dimmer_window_
->layer()->SetOpacity(kDimmedOpacity
);
142 // ScopedHidingAnimationSettings will detach the animating and
143 // recreate layers for the container so that animation can continue
144 // even if the container is removed immediately.
145 wm::ScopedHidingAnimationSettings
settings(modal_container_
);
146 settings
.layer_animation_settings()->SetTransitionDuration(
147 base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs
));
148 modal_container_
->layer()->SetOpacity(0.0f
);
152 } // namespace athena