Chromium Code Reviews| Index: athena/screen/modal_window_controller.cc |
| diff --git a/athena/screen/modal_window_controller.cc b/athena/screen/modal_window_controller.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2e421837b80018273bcff1c5dcd23c04f7e2ab10 |
| --- /dev/null |
| +++ b/athena/screen/modal_window_controller.cc |
| @@ -0,0 +1,145 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "athena/screen/modal_window_controller.h" |
| + |
| +#include "athena/screen/public/screen_manager.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/aura/window_property.h" |
| +#include "ui/compositor/layer.h" |
| +#include "ui/compositor/layer_animation_observer.h" |
| +#include "ui/compositor/scoped_layer_animation_settings.h" |
| +#include "ui/wm/core/window_animations.h" |
| + |
| +namespace athena { |
| +namespace { |
| + |
| +DEFINE_OWNED_WINDOW_PROPERTY_KEY(ModalWindowController, |
| + kModalWindowControllerKey, |
| + NULL); |
| + |
| +} // namespace |
| + |
| +// static |
| +ModalWindowController* ModalWindowController::Get(aura::Window* container) { |
| + ModalWindowController* controller = |
| + container->GetProperty(kModalWindowControllerKey); |
| + CHECK(controller); |
| + return controller; |
| +} |
| + |
| +ModalWindowController::ModalWindowController(int priority) |
| + : modal_container_(new aura::Window(NULL)), |
| + dimmer_window_(new aura::Window(NULL)), |
| + dimmed_(false) { |
| + ScreenManager::ContainerParams params("ModalContainer", priority); |
| + params.can_activate_children = true; |
| + params.block_events = true; |
| + modal_container_ = ScreenManager::Get()->CreateContainer(params); |
| + modal_container_->SetProperty(kModalWindowControllerKey, this); |
| + |
| + dimmer_window_->SetType(ui::wm::WINDOW_TYPE_NORMAL); |
| + dimmer_window_->Init(aura::WINDOW_LAYER_SOLID_COLOR); |
| + dimmer_window_->layer()->SetColor(SK_ColorBLACK); |
| + dimmer_window_->layer()->SetOpacity(0.0f); |
| + dimmer_window_->Show(); |
| + |
| + modal_container_->AddChild(dimmer_window_); |
| + modal_container_->AddObserver(this); |
| + |
| + UpdateDimmerWindowBounds(); |
| +} |
| + |
| +ModalWindowController::~ModalWindowController() { |
| + if (modal_container_) |
| + modal_container_->RemoveObserver(this); |
| +} |
| + |
| +void ModalWindowController::OnWindowAdded(aura::Window* child) { |
| + DCHECK_NE(child, dimmer_window_); |
| + if (IsChildWindow(child)) { |
| + child->AddObserver(this); |
| + UpdateDimming(NULL); |
| + } |
| +} |
| + |
| +void ModalWindowController::OnWindowVisibilityChanged(aura::Window* window, |
| + bool visible) { |
| + if (IsChildWindow(window) && window != dimmer_window_) |
|
Jun Mukai
2014/10/17 17:29:53
IsChildWindow already checks window != dimmer_wind
oshima
2014/10/17 18:20:04
thank you for catching this. Done.
|
| + UpdateDimming(NULL); |
| +} |
| + |
| +void ModalWindowController::OnWindowBoundsChanged(aura::Window* window, |
| + const gfx::Rect& old_bounds, |
| + const gfx::Rect& new_bounds) { |
| + if (window == modal_container_) |
| + UpdateDimmerWindowBounds(); |
| +} |
| + |
| +void ModalWindowController::OnWindowDestroyed(aura::Window* window) { |
| + UpdateDimming(window); |
| +} |
| + |
| +bool ModalWindowController::IsChildWindow(aura::Window* child) const { |
| + return child->parent() == modal_container_ && child != dimmer_window_; |
| +} |
| + |
| +void ModalWindowController::UpdateDimmerWindowBounds() { |
| + gfx::Rect bounds(modal_container_->bounds().size()); |
| + dimmer_window_->SetBounds(bounds); |
| +} |
| + |
| +void ModalWindowController::UpdateDimming(aura::Window* ignore) { |
| + if (!modal_container_ || !dimmer_window_) |
| + return; |
| + bool should_delete = true; |
| + for (aura::Window* window : modal_container_->children()) { |
| + if (window == dimmer_window_ || window == ignore) |
| + continue; |
| + should_delete = false; |
| + if (window->TargetVisibility()) { |
| + SetDimmed(true); |
| + return; |
| + } |
| + } |
| + SetDimmed(false); |
| + |
| + if (should_delete) { |
| + // Remove the container from root so that the container becomes |
| + // invisible, but don't delete it until next event execution |
| + // because the call stack may still have and use the pointer. |
| + modal_container_->RemoveObserver(this); |
| + modal_container_->parent()->RemoveChild(modal_container_); |
| + base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, modal_container_); |
| + modal_container_ = NULL; |
| + dimmer_window_ = NULL; |
| + } |
| +} |
| + |
| +void ModalWindowController::SetDimmed(bool dimmed) { |
| + const float kDimmedOpacity = 0.4f; |
| + |
| + if (!dimmer_window_ || dimmed_ == dimmed) |
| + return; |
| + dimmed_ = dimmed; |
| + |
| + const int kDimmAnimationDurationMs = 500; |
| + if (dimmed) { |
| + ui::ScopedLayerAnimationSettings settings( |
| + dimmer_window_->layer()->GetAnimator()); |
| + settings.SetTransitionDuration( |
| + base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs)); |
| + dimmer_window_->layer()->SetOpacity(kDimmedOpacity); |
| + } else { |
| + // Detach the animation layer so that we can remove the container |
| + // immediately. |
|
Jun Mukai
2014/10/17 17:29:53
It seems not detaching at all?
oshima
2014/10/17 18:20:04
ScopedLayerAnimationSettings does. Updated the com
|
| + wm::ScopedHidingAnimationSettings settings(modal_container_); |
| + settings.layer_animation_settings()->SetTransitionDuration( |
| + base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs)); |
| + modal_container_->layer()->SetOpacity(0.0f); |
| + } |
| +} |
| + |
| +} // namespace athena |