workspace_backdrop_delegate.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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. 4 5#include "ash/wm/maximize_mode/workspace_backdrop_delegate.h" 6 7#include "ash/wm/window_animations.h" 8#include "ash/wm/window_util.h" 9#include "base/auto_reset.h" 10#include "ui/aura/window.h" 11#include "ui/compositor/layer.h" 12#include "ui/compositor/scoped_layer_animation_settings.h" 13#include "ui/views/background.h" 14#include "ui/views/widget/widget.h" 15#include "ui/wm/core/window_util.h" 16 17namespace ash { 18 19namespace internal { 20 21namespace { 22 23// The opacity of the backdrop. 24const float kBackdropOpacity = 0.5f; 25 26} // namespace 27 28WorkspaceBackdropDelegate::WorkspaceBackdropDelegate(aura::Window* container) 29 : background_(NULL), 30 container_(container), 31 in_restacking_(false) { 32 background_ = new views::Widget; 33 views::Widget::InitParams params( 34 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 35 params.parent = container_; 36 params.bounds = container_->bounds(); 37 params.layer_type = aura::WINDOW_LAYER_SOLID_COLOR; 38 // To disallow the MRU list from picking this window up it should not be 39 // activateable. 40 params.can_activate = false; 41 background_->Init(params); 42 background_->GetNativeView()->SetName("WorkspaceBackdropDelegate"); 43 background_->GetNativeView()->layer()->SetColor(SK_ColorBLACK); 44 Show(); 45 RestackBackdrop(); 46 container_->AddObserver(this); 47} 48 49WorkspaceBackdropDelegate::~WorkspaceBackdropDelegate() { 50 container_->RemoveObserver(this); 51 ui::ScopedLayerAnimationSettings settings( 52 background_->GetNativeView()->layer()->GetAnimator()); 53 background_->Close(); 54 settings.AddObserver(::wm::CreateHidingWindowAnimationObserver( 55 background_->GetNativeView())); 56 background_->GetNativeView()->layer()->SetOpacity(0.0f); 57} 58 59void WorkspaceBackdropDelegate::OnWindowBoundsChanged( 60 aura::Window* window, 61 const gfx::Rect& old_bounds, 62 const gfx::Rect& new_bounds) { 63 // The container size has changed and the layer needs to be adapt to it. 64 AdjustToContainerBounds(); 65} 66 67void WorkspaceBackdropDelegate::OnWindowAddedToLayout(aura::Window* child) { 68 RestackBackdrop(); 69} 70 71void WorkspaceBackdropDelegate::OnWindowRemovedFromLayout(aura::Window* child) { 72 RestackBackdrop(); 73} 74 75void WorkspaceBackdropDelegate::OnChildWindowVisibilityChanged( 76 aura::Window* child, 77 bool visible) { 78 RestackBackdrop(); 79} 80 81void WorkspaceBackdropDelegate::OnWindowStackingChanged(aura::Window* window) { 82 RestackBackdrop(); 83} 84 85void WorkspaceBackdropDelegate::OnPostWindowStateTypeChange( 86 wm::WindowState* window_state, 87 wm::WindowStateType old_type) { 88 RestackBackdrop(); 89} 90 91void WorkspaceBackdropDelegate::RestackBackdrop() { 92 // Avoid recursive calls. 93 if (in_restacking_) 94 return; 95 96 aura::Window* window = GetCurrentTopWindow(); 97 if (!window) { 98 // Hide backdrop since no suitable window was found. 99 background_->Hide(); 100 return; 101 } 102 if (window == background_->GetNativeWindow() && 103 background_->IsVisible()) { 104 return; 105 } 106 // We are changing the order of windows which will cause recursion. 107 base::AutoReset<bool> lock(&in_restacking_, true); 108 if (!background_->IsVisible()) 109 Show(); 110 // Since the backdrop needs to be immediately behind the window and the 111 // stacking functions only guarantee a "it's above or below", we need 112 // to re-arrange the two windows twice. 113 container_->StackChildAbove(background_->GetNativeView(), window); 114 container_->StackChildAbove(window, background_->GetNativeView()); 115} 116 117aura::Window* WorkspaceBackdropDelegate::GetCurrentTopWindow() { 118 const aura::Window::Windows& windows = container_->children(); 119 for (aura::Window::Windows::const_reverse_iterator window_iter = 120 windows.rbegin(); 121 window_iter != windows.rend(); ++window_iter) { 122 aura::Window* window = *window_iter; 123 if (window->TargetVisibility() && 124 window->type() == ui::wm::WINDOW_TYPE_NORMAL && 125 ash::wm::CanActivateWindow(window)) 126 return window; 127 } 128 return NULL; 129} 130 131void WorkspaceBackdropDelegate::AdjustToContainerBounds() { 132 // Cover the entire container window. 133 gfx::Rect target_rect(gfx::Point(0, 0), container_->bounds().size()); 134 if (target_rect != background_->GetNativeWindow()->bounds()) { 135 // This needs to be instant. 136 ui::ScopedLayerAnimationSettings settings( 137 background_->GetNativeView()->layer()->GetAnimator()); 138 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(0)); 139 background_->GetNativeWindow()->SetBounds(target_rect); 140 if (!background_->IsVisible()) 141 background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity); 142 } 143} 144 145void WorkspaceBackdropDelegate::Show() { 146 background_->GetNativeView()->layer()->SetOpacity(0.0f); 147 background_->Show(); 148 ui::ScopedLayerAnimationSettings settings( 149 background_->GetNativeView()->layer()->GetAnimator()); 150 background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity); 151} 152 153} // namespace internal 154} // namespace ash 155