root/ash/wm/system_modal_container_layout_manager.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. modal_background_
  2. OnWindowResized
  3. OnWindowAddedToLayout
  4. OnWillRemoveWindowFromLayout
  5. OnWindowRemovedFromLayout
  6. OnChildWindowVisibilityChanged
  7. SetChildBounds
  8. OnWindowPropertyChanged
  9. OnWindowDestroying
  10. CanWindowReceiveEvents
  11. ActivateNextModalWindow
  12. CreateModalBackground
  13. DestroyModalBackground
  14. IsModalBackground
  15. AddModalWindow
  16. RemoveModalWindow

// 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 "ash/wm/system_modal_container_layout_manager.h"

#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/system_modal_container_event_filter.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_util.h"
#include "base/bind.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event.h"
#include "ui/gfx/screen.h"
#include "ui/views/background.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/compound_event_filter.h"

namespace ash {

////////////////////////////////////////////////////////////////////////////////
// SystemModalContainerLayoutManager, public:

SystemModalContainerLayoutManager::SystemModalContainerLayoutManager(
    aura::Window* container)
    : container_(container),
      modal_background_(NULL) {
}

SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() {
}

////////////////////////////////////////////////////////////////////////////////
// SystemModalContainerLayoutManager, aura::LayoutManager implementation:

void SystemModalContainerLayoutManager::OnWindowResized() {
  if (modal_background_) {
    // Note: we have to set the entire bounds with the screen offset.
    modal_background_->SetBounds(
        Shell::GetScreen()->GetDisplayNearestWindow(container_).bounds());
  }
  if (!modal_windows_.empty()) {
    aura::Window::Windows::iterator it = modal_windows_.begin();
    for (it = modal_windows_.begin(); it != modal_windows_.end(); ++it) {
      gfx::Rect bounds = (*it)->bounds();
      bounds.AdjustToFit(container_->bounds());
      (*it)->SetBounds(bounds);
    }
  }
}

void SystemModalContainerLayoutManager::OnWindowAddedToLayout(
    aura::Window* child) {
  DCHECK((modal_background_ && child == modal_background_->GetNativeView()) ||
         child->type() == ui::wm::WINDOW_TYPE_NORMAL ||
         child->type() == ui::wm::WINDOW_TYPE_POPUP);
  DCHECK(
      container_->id() != kShellWindowId_LockSystemModalContainer ||
      Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked());

  child->AddObserver(this);
  if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE)
    AddModalWindow(child);
}

void SystemModalContainerLayoutManager::OnWillRemoveWindowFromLayout(
    aura::Window* child) {
  child->RemoveObserver(this);
  if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE)
    RemoveModalWindow(child);
}

void SystemModalContainerLayoutManager::OnWindowRemovedFromLayout(
    aura::Window* child) {
}

void SystemModalContainerLayoutManager::OnChildWindowVisibilityChanged(
    aura::Window* child,
    bool visible) {
}

void SystemModalContainerLayoutManager::SetChildBounds(
    aura::Window* child,
    const gfx::Rect& requested_bounds) {
  SetChildBoundsDirect(child, requested_bounds);
}

////////////////////////////////////////////////////////////////////////////////
// SystemModalContainerLayoutManager, aura::WindowObserver implementation:

void SystemModalContainerLayoutManager::OnWindowPropertyChanged(
    aura::Window* window,
    const void* key,
    intptr_t old) {
  if (key != aura::client::kModalKey)
    return;

  if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) {
    AddModalWindow(window);
  } else if (static_cast<ui::ModalType>(old) != ui::MODAL_TYPE_NONE) {
    RemoveModalWindow(window);
    Shell::GetInstance()->OnModalWindowRemoved(window);
  }
}

void SystemModalContainerLayoutManager::OnWindowDestroying(
    aura::Window* window) {
  if (modal_background_ && modal_background_->GetNativeView() == window)
    modal_background_ = NULL;
}

bool SystemModalContainerLayoutManager::CanWindowReceiveEvents(
    aura::Window* window) {
  // We could get when we're at lock screen and there is modal window at
  // system modal window layer which added event filter.
  // Now this lock modal windows layer layout manager should not block events
  // for windows at lock layer.
  // See SystemModalContainerLayoutManagerTest.EventFocusContainers and
  // http://crbug.com/157469
  if (modal_windows_.empty())
    return true;
  // This container can not handle events if the screen is locked and it is not
  // above the lock screen layer (crbug.com/110920).
  if (Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked() &&
      container_->id() < ash::kShellWindowId_LockScreenContainer)
    return true;
  return wm::GetActivatableWindow(window) == modal_window();
}

bool SystemModalContainerLayoutManager::ActivateNextModalWindow() {
  if (modal_windows_.empty())
    return false;
  wm::ActivateWindow(modal_window());
  return true;
}

void SystemModalContainerLayoutManager::CreateModalBackground() {
  if (!modal_background_) {
    modal_background_ = new views::Widget;
    views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
    params.parent = container_;
    params.bounds = Shell::GetScreen()->GetDisplayNearestWindow(
        container_).bounds();
    modal_background_->Init(params);
    modal_background_->GetNativeView()->SetName(
        "SystemModalContainerLayoutManager.ModalBackground");
    views::View* contents_view = new views::View();
    // TODO(jamescook): This could be SK_ColorWHITE for the new dialog style.
    contents_view->set_background(
        views::Background::CreateSolidBackground(SK_ColorBLACK));
    modal_background_->SetContentsView(contents_view);
    modal_background_->GetNativeView()->layer()->SetOpacity(0.0f);
  }

  ui::ScopedLayerAnimationSettings settings(
      modal_background_->GetNativeView()->layer()->GetAnimator());
  // Show should not be called with a target opacity of 0. We therefore start
  // the fade to show animation before Show() is called.
  modal_background_->GetNativeView()->layer()->SetOpacity(0.5f);
  modal_background_->Show();
  container_->StackChildAtTop(modal_background_->GetNativeView());
}

void SystemModalContainerLayoutManager::DestroyModalBackground() {
  // modal_background_ can be NULL when a root window is shutting down
  // and OnWindowDestroying is called first.
  if (modal_background_) {
    ::wm::ScopedHidingAnimationSettings settings(
        modal_background_->GetNativeView());
    modal_background_->Close();
    modal_background_->GetNativeView()->layer()->SetOpacity(0.0f);
    modal_background_ = NULL;
  }
}

// static
bool SystemModalContainerLayoutManager::IsModalBackground(
    aura::Window* window) {
  int id = window->parent()->id();
  if (id != kShellWindowId_SystemModalContainer &&
      id != kShellWindowId_LockSystemModalContainer)
    return false;
  SystemModalContainerLayoutManager* layout_manager =
      static_cast<SystemModalContainerLayoutManager*>(
          window->parent()->layout_manager());
  return layout_manager->modal_background_ &&
      layout_manager->modal_background_->GetNativeWindow() == window;
}

////////////////////////////////////////////////////////////////////////////////
// SystemModalContainerLayoutManager, private:

void SystemModalContainerLayoutManager::AddModalWindow(aura::Window* window) {
  if (modal_windows_.empty()) {
    aura::Window* capture_window = aura::client::GetCaptureWindow(container_);
    if (capture_window)
      capture_window->ReleaseCapture();
  }
  modal_windows_.push_back(window);
  Shell::GetInstance()->CreateModalBackground(window);
  window->parent()->StackChildAtTop(window);
}

void SystemModalContainerLayoutManager::RemoveModalWindow(
    aura::Window* window) {
  aura::Window::Windows::iterator it =
      std::find(modal_windows_.begin(), modal_windows_.end(), window);
  if (it != modal_windows_.end())
    modal_windows_.erase(it);
}

}  // namespace ash

/* [<][>][^][v][top][bottom][index][help] */