Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / athena / screen / modal_window_controller.cc
blob140b2c9abad726296da25ca6e1e58797858ba9e2
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"
16 namespace athena {
17 namespace {
19 DEFINE_OWNED_WINDOW_PROPERTY_KEY(ModalWindowController,
20 kModalWindowControllerKey,
21 nullptr);
23 } // namespace
25 // static
26 ModalWindowController* ModalWindowController::Get(aura::Window* container) {
27 ModalWindowController* controller =
28 container->GetProperty(kModalWindowControllerKey);
29 CHECK(controller);
30 return controller;
33 ModalWindowController::ModalWindowController(int priority)
34 : modal_container_(nullptr),
35 dimmer_window_(new aura::Window(nullptr)),
36 dimmed_(false) {
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() {
56 if (modal_container_)
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,
69 bool visible) {
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_)
96 return;
97 bool should_delete = true;
98 for (aura::Window* window : modal_container_->children()) {
99 if (window == dimmer_window_ || window == ignore)
100 continue;
101 should_delete = false;
102 if (window->TargetVisibility()) {
103 SetDimmed(true);
104 return;
107 SetDimmed(false);
109 if (should_delete) {
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
117 // available.
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)
131 return;
132 dimmed_ = dimmed;
134 const int kDimmAnimationDurationMs = 500;
135 if (dimmed) {
136 ui::ScopedLayerAnimationSettings settings(
137 dimmer_window_->layer()->GetAnimator());
138 settings.SetTransitionDuration(
139 base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs));
140 dimmer_window_->layer()->SetOpacity(kDimmedOpacity);
141 } else {
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