system_modal_container_layout_manager.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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/system_modal_container_layout_manager.h" 6 7#include "ash/shell.h" 8#include "ash/shell_delegate.h" 9#include "ash/shell_window_ids.h" 10#include "ash/wm/system_modal_container_event_filter.h" 11#include "ash/wm/window_animations.h" 12#include "ash/wm/window_util.h" 13#include "base/bind.h" 14#include "base/command_line.h" 15#include "ui/aura/client/aura_constants.h" 16#include "ui/aura/client/capture_client.h" 17#include "ui/aura/root_window.h" 18#include "ui/views/corewm/compound_event_filter.h" 19#include "ui/aura/window.h" 20#include "ui/base/events/event.h" 21#include "ui/base/ui_base_switches.h" 22#include "ui/compositor/layer.h" 23#include "ui/compositor/layer_animator.h" 24#include "ui/compositor/scoped_layer_animation_settings.h" 25#include "ui/gfx/screen.h" 26#include "ui/views/view.h" 27#include "ui/views/widget/widget.h" 28 29namespace ash { 30namespace internal { 31 32//////////////////////////////////////////////////////////////////////////////// 33// SystemModalContainerLayoutManager, public: 34 35SystemModalContainerLayoutManager::SystemModalContainerLayoutManager( 36 aura::Window* container) 37 : container_(container), 38 modal_background_(NULL) { 39} 40 41SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() { 42} 43 44//////////////////////////////////////////////////////////////////////////////// 45// SystemModalContainerLayoutManager, aura::LayoutManager implementation: 46 47void SystemModalContainerLayoutManager::OnWindowResized() { 48 if (modal_background_) { 49 // Note: we have to set the entire bounds with the screen offset. 50 modal_background_->SetBounds( 51 Shell::GetScreen()->GetDisplayNearestWindow(container_).bounds()); 52 } 53 if (!modal_windows_.empty()) { 54 aura::Window::Windows::iterator it = modal_windows_.begin(); 55 for (it = modal_windows_.begin(); it != modal_windows_.end(); ++it) { 56 gfx::Rect bounds = (*it)->bounds(); 57 bounds.AdjustToFit(container_->bounds()); 58 (*it)->SetBounds(bounds); 59 } 60 } 61} 62 63void SystemModalContainerLayoutManager::OnWindowAddedToLayout( 64 aura::Window* child) { 65 DCHECK((modal_background_ && child == modal_background_->GetNativeView()) || 66 child->type() == aura::client::WINDOW_TYPE_NORMAL || 67 child->type() == aura::client::WINDOW_TYPE_POPUP); 68 DCHECK( 69 container_->id() != internal::kShellWindowId_LockSystemModalContainer || 70 Shell::GetInstance()->delegate()->IsScreenLocked() || 71 !Shell::GetInstance()->delegate()->IsSessionStarted()); 72 73 child->AddObserver(this); 74 if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) 75 AddModalWindow(child); 76} 77 78void SystemModalContainerLayoutManager::OnWillRemoveWindowFromLayout( 79 aura::Window* child) { 80 child->RemoveObserver(this); 81 if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) 82 RemoveModalWindow(child); 83} 84 85void SystemModalContainerLayoutManager::OnWindowRemovedFromLayout( 86 aura::Window* child) { 87} 88 89void SystemModalContainerLayoutManager::OnChildWindowVisibilityChanged( 90 aura::Window* child, 91 bool visible) { 92} 93 94void SystemModalContainerLayoutManager::SetChildBounds( 95 aura::Window* child, 96 const gfx::Rect& requested_bounds) { 97 SetChildBoundsDirect(child, requested_bounds); 98} 99 100//////////////////////////////////////////////////////////////////////////////// 101// SystemModalContainerLayoutManager, aura::WindowObserver implementation: 102 103void SystemModalContainerLayoutManager::OnWindowPropertyChanged( 104 aura::Window* window, 105 const void* key, 106 intptr_t old) { 107 if (key != aura::client::kModalKey) 108 return; 109 110 if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) { 111 AddModalWindow(window); 112 } else if (static_cast<ui::ModalType>(old) != ui::MODAL_TYPE_NONE) { 113 RemoveModalWindow(window); 114 Shell::GetInstance()->OnModalWindowRemoved(window); 115 } 116} 117 118void SystemModalContainerLayoutManager::OnWindowDestroying( 119 aura::Window* window) { 120 if (modal_background_ && modal_background_->GetNativeView() == window) 121 modal_background_ = NULL; 122} 123 124 125//////////////////////////////////////////////////////////////////////////////// 126// SystemModalContainerLayoutManager, 127// SystemModalContainerEventFilter::Delegate implementation: 128 129bool SystemModalContainerLayoutManager::CanWindowReceiveEvents( 130 aura::Window* window) { 131 // We could get when we're at lock screen and there is modal window at 132 // system modal window layer which added event filter. 133 // Now this lock modal windows layer layout manager should not block events 134 // for windows at lock layer. 135 // See SystemModalContainerLayoutManagerTest.EventFocusContainers and 136 // http://crbug.com/157469 137 if (modal_windows_.empty()) 138 return true; 139 // This container can not handle events if the screen is locked and it is not 140 // above the lock screen layer (crbug.com/110920). 141 if (ash::Shell::GetInstance()->IsScreenLocked() && 142 container_->id() < ash::internal::kShellWindowId_LockScreenContainer) 143 return true; 144 return wm::GetActivatableWindow(window) == modal_window(); 145} 146 147bool SystemModalContainerLayoutManager::ActivateNextModalWindow() { 148 if (modal_windows_.empty()) 149 return false; 150 wm::ActivateWindow(modal_window()); 151 return true; 152} 153 154void SystemModalContainerLayoutManager::CreateModalBackground() { 155 if (!modal_background_) { 156 modal_background_ = new views::Widget; 157 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); 158 params.parent = container_; 159 params.bounds = Shell::GetScreen()->GetDisplayNearestWindow( 160 container_).bounds(); 161 modal_background_->Init(params); 162 modal_background_->GetNativeView()->SetName( 163 "SystemModalContainerLayoutManager.ModalBackground"); 164 views::View* contents_view = new views::View(); 165 contents_view->set_background(views::Background::CreateSolidBackground( 166 CommandLine::ForCurrentProcess()->HasSwitch( 167 switches::kEnableNewDialogStyle) ? SK_ColorWHITE : SK_ColorBLACK)); 168 modal_background_->SetContentsView(contents_view); 169 modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); 170 } 171 172 ui::ScopedLayerAnimationSettings settings( 173 modal_background_->GetNativeView()->layer()->GetAnimator()); 174 modal_background_->Show(); 175 modal_background_->GetNativeView()->layer()->SetOpacity(0.5f); 176 container_->StackChildAtTop(modal_background_->GetNativeView()); 177} 178 179void SystemModalContainerLayoutManager::DestroyModalBackground() { 180 // modal_background_ can be NULL when a root window is shutting down 181 // and OnWindowDestroying is called first. 182 if (modal_background_) { 183 ui::ScopedLayerAnimationSettings settings( 184 modal_background_->GetNativeView()->layer()->GetAnimator()); 185 modal_background_->Close(); 186 settings.AddObserver(views::corewm::CreateHidingWindowAnimationObserver( 187 modal_background_->GetNativeView())); 188 modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); 189 modal_background_ = NULL; 190 } 191} 192 193// static 194bool SystemModalContainerLayoutManager::IsModalBackground( 195 aura::Window* window) { 196 int id = window->parent()->id(); 197 if (id != internal::kShellWindowId_SystemModalContainer && 198 id != internal::kShellWindowId_LockSystemModalContainer) 199 return false; 200 SystemModalContainerLayoutManager* layout_manager = 201 static_cast<SystemModalContainerLayoutManager*>( 202 window->parent()->layout_manager()); 203 return layout_manager->modal_background_ && 204 layout_manager->modal_background_->GetNativeWindow() == window; 205} 206 207//////////////////////////////////////////////////////////////////////////////// 208// SystemModalContainerLayoutManager, private: 209 210void SystemModalContainerLayoutManager::AddModalWindow(aura::Window* window) { 211 if (modal_windows_.empty()) { 212 aura::Window* capture_window = aura::client::GetCaptureWindow(container_); 213 if (capture_window) 214 capture_window->ReleaseCapture(); 215 } 216 modal_windows_.push_back(window); 217 Shell::GetInstance()->CreateModalBackground(window); 218 window->parent()->StackChildAtTop(window); 219} 220 221void SystemModalContainerLayoutManager::RemoveModalWindow( 222 aura::Window* window) { 223 aura::Window::Windows::iterator it = 224 std::find(modal_windows_.begin(), modal_windows_.end(), window); 225 if (it != modal_windows_.end()) 226 modal_windows_.erase(it); 227} 228 229} // namespace internal 230} // namespace ash 231