diff options
Diffstat (limited to 'ui/views/corewm/shadow_controller.cc')
-rw-r--r-- | ui/views/corewm/shadow_controller.cc | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/ui/views/corewm/shadow_controller.cc b/ui/views/corewm/shadow_controller.cc new file mode 100644 index 0000000..2e97aac --- /dev/null +++ b/ui/views/corewm/shadow_controller.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2012 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 "ui/views/corewm/shadow_controller.h" + +#include <utility> + +#include "base/command_line.h" +#include "base/logging.h" +#include "ui/aura/client/activation_client.h" +#include "ui/aura/env.h" +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" +#include "ui/compositor/layer.h" +#include "ui/views/corewm/shadow.h" +#include "ui/views/corewm/shadow_types.h" + +using std::make_pair; + +namespace views { +namespace corewm { + +namespace { + +ShadowType GetShadowTypeFromWindow(aura::Window* window) { + switch (window->type()) { + case aura::client::WINDOW_TYPE_NORMAL: + case aura::client::WINDOW_TYPE_PANEL: + case aura::client::WINDOW_TYPE_MENU: + case aura::client::WINDOW_TYPE_TOOLTIP: + return SHADOW_TYPE_RECTANGULAR; + default: + break; + } + return SHADOW_TYPE_NONE; +} + +bool ShouldUseSmallShadowForWindow(aura::Window* window) { + switch (window->type()) { + case aura::client::WINDOW_TYPE_MENU: + case aura::client::WINDOW_TYPE_TOOLTIP: + return true; + default: + break; + } + return false; +} + +// Returns the shadow style to be applied to |losing_active| when it is losing +// active to |gaining_active|. |gaining_active| may be of a type that hides when +// inactive, and as such we do not want to render |losing_active| as inactive. +Shadow::Style GetShadowStyleForWindowLosingActive( + aura::Window* losing_active, + aura::Window* gaining_active) { + if (gaining_active && aura::client::GetHideOnDeactivate(gaining_active)) { + aura::Window::Windows::const_iterator it = + std::find(losing_active->transient_children().begin(), + losing_active->transient_children().end(), + gaining_active); + if (it != losing_active->transient_children().end()) + return Shadow::STYLE_ACTIVE; + } + return Shadow::STYLE_INACTIVE; +} + +} // namespace + +ShadowController::ShadowController(aura::RootWindow* root_window) + : ALLOW_THIS_IN_INITIALIZER_LIST(observer_manager_(this)), + root_window_(root_window) { + aura::Env::GetInstance()->AddObserver(this); + // Watch for window activation changes. + aura::client::GetActivationClient(root_window_)->AddObserver(this); +} + +ShadowController::~ShadowController() { + aura::client::GetActivationClient(root_window_)->RemoveObserver(this); + aura::Env::GetInstance()->RemoveObserver(this); +} + +void ShadowController::OnWindowInitialized(aura::Window* window) { + observer_manager_.Add(window); + SetShadowType(window, GetShadowTypeFromWindow(window)); + HandlePossibleShadowVisibilityChange(window); +} + +void ShadowController::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + if (key == kShadowTypeKey) { + HandlePossibleShadowVisibilityChange(window); + return; + } +} + +void ShadowController::OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + Shadow* shadow = GetShadowForWindow(window); + if (shadow) + shadow->SetContentBounds(gfx::Rect(new_bounds.size())); +} + +void ShadowController::OnWindowDestroyed(aura::Window* window) { + window_shadows_.erase(window); + observer_manager_.Remove(window); +} + +void ShadowController::OnWindowActivated(aura::Window* gaining_active, + aura::Window* losing_active) { + if (gaining_active) { + Shadow* shadow = GetShadowForWindow(gaining_active); + if (shadow && !ShouldUseSmallShadowForWindow(gaining_active)) + shadow->SetStyle(Shadow::STYLE_ACTIVE); + } + if (losing_active) { + Shadow* shadow = GetShadowForWindow(losing_active); + if (shadow && !ShouldUseSmallShadowForWindow(losing_active)) { + shadow->SetStyle(GetShadowStyleForWindowLosingActive(losing_active, + gaining_active)); + } + } +} + +bool ShadowController::ShouldShowShadowForWindow(aura::Window* window) const { + const ShadowType type = GetShadowType(window); + switch (type) { + case SHADOW_TYPE_NONE: + return false; + case SHADOW_TYPE_RECTANGULAR: + return true; + default: + NOTREACHED() << "Unknown shadow type " << type; + return false; + } +} + +Shadow* ShadowController::GetShadowForWindow(aura::Window* window) { + WindowShadowMap::const_iterator it = window_shadows_.find(window); + return it != window_shadows_.end() ? it->second.get() : NULL; +} + +void ShadowController::HandlePossibleShadowVisibilityChange( + aura::Window* window) { + const bool should_show = ShouldShowShadowForWindow(window); + Shadow* shadow = GetShadowForWindow(window); + if (shadow) + shadow->layer()->SetVisible(should_show); + else if (should_show && !shadow) + CreateShadowForWindow(window); +} + +void ShadowController::CreateShadowForWindow(aura::Window* window) { + linked_ptr<Shadow> shadow(new Shadow()); + window_shadows_.insert(make_pair(window, shadow)); + + shadow->Init(ShouldUseSmallShadowForWindow(window) ? + Shadow::STYLE_SMALL : Shadow::STYLE_ACTIVE); + shadow->SetContentBounds(gfx::Rect(window->bounds().size())); + shadow->layer()->SetVisible(ShouldShowShadowForWindow(window)); + window->layer()->Add(shadow->layer()); +} + +} // namespace corewm +} // namespace views |