1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/window_animations.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/window_util.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/auto_reset.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/views/background.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/views/widget/widget.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/wm/core/window_animations.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ash {
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// The opacity of the backdrop.
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kBackdropOpacity = 0.5f;
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WorkspaceBackdropDelegate::WorkspaceBackdropDelegate(aura::Window* container)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : background_(NULL),
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      container_(container),
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      in_restacking_(false) {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_ = new views::Widget;
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  views::Widget::InitParams params(
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  params.parent = container_;
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params.bounds = container_->GetBoundsInScreen();
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  params.layer_type = aura::WINDOW_LAYER_SOLID_COLOR;
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // To disallow the MRU list from picking this window up it should not be
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // activateable.
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->Init(params);
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Do not use the animation system. We don't want the bounds animation and
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // opacity needs to get set to |kBackdropOpacity|.
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ::wm::SetWindowVisibilityAnimationTransition(
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      background_->GetNativeView(),
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ::wm::ANIMATE_NONE);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->GetNativeView()->SetName("WorkspaceBackdropDelegate");
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->GetNativeView()->layer()->SetColor(SK_ColorBLACK);
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Make sure that the layer covers visibly everything - including the shelf.
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  background_->GetNativeView()->layer()->SetBounds(params.bounds);
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Show();
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  container_->AddObserver(this);
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WorkspaceBackdropDelegate::~WorkspaceBackdropDelegate() {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  container_->RemoveObserver(this);
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ::wm::ScopedHidingAnimationSettings hiding_settings(
5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      background_->GetNativeView());
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->Close();
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->GetNativeView()->layer()->SetOpacity(0.0f);
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnWindowBoundsChanged(
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    aura::Window* window,
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Rect& old_bounds,
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Rect& new_bounds) {
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The container size has changed and the layer needs to be adapt to it.
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AdjustToContainerBounds();
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnWindowAddedToLayout(aura::Window* child) {
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnWindowRemovedFromLayout(aura::Window* child) {
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnChildWindowVisibilityChanged(
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    aura::Window* child,
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool visible) {
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnWindowStackingChanged(aura::Window* window) {
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::OnPostWindowStateTypeChange(
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    wm::WindowState* window_state,
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    wm::WindowStateType old_type) {
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RestackBackdrop();
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WorkspaceBackdropDelegate::OnDisplayWorkAreaInsetsChanged() {
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AdjustToContainerBounds();
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::RestackBackdrop() {
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Avoid recursive calls.
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (in_restacking_)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::Window* window = GetCurrentTopWindow();
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!window) {
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Hide backdrop since no suitable window was found.
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    background_->Hide();
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (window == background_->GetNativeWindow() &&
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      background_->IsVisible()) {
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We are changing the order of windows which will cause recursion.
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::AutoReset<bool> lock(&in_restacking_, true);
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!background_->IsVisible())
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Show();
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Since the backdrop needs to be immediately behind the window and the
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // stacking functions only guarantee a "it's above or below", we need
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to re-arrange the two windows twice.
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  container_->StackChildAbove(background_->GetNativeView(), window);
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  container_->StackChildAbove(window, background_->GetNativeView());
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)aura::Window* WorkspaceBackdropDelegate::GetCurrentTopWindow() {
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const aura::Window::Windows& windows = container_->children();
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (aura::Window::Windows::const_reverse_iterator window_iter =
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           windows.rbegin();
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       window_iter != windows.rend(); ++window_iter) {
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    aura::Window* window = *window_iter;
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (window->TargetVisibility() &&
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        window->type() == ui::wm::WINDOW_TYPE_NORMAL &&
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ash::wm::CanActivateWindow(window))
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return window;
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return NULL;
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::AdjustToContainerBounds() {
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Cover the entire container window.
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect target_rect(gfx::Point(0, 0), container_->bounds().size());
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (target_rect != background_->GetNativeWindow()->bounds()) {
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // This needs to be instant.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        background_->GetNativeView()->layer()->GetAnimator());
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(0));
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    background_->GetNativeWindow()->SetBounds(target_rect);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!background_->IsVisible())
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity);
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WorkspaceBackdropDelegate::Show() {
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->GetNativeView()->layer()->SetOpacity(0.0f);
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->Show();
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::ScopedLayerAnimationSettings settings(
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      background_->GetNativeView()->layer()->GetAnimator());
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background_->GetNativeView()->layer()->SetOpacity(kBackdropOpacity);
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace ash
161