Home | History | Annotate | Download | only in overview
      1 // Copyright 2013 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/overview/window_selector_panels.h"
      6 
      7 #include "ash/screen_ash.h"
      8 #include "ash/shell.h"
      9 #include "ash/shell_window_ids.h"
     10 #include "ash/wm/overview/scoped_transform_overview_window.h"
     11 #include "ash/wm/panels/panel_layout_manager.h"
     12 #include "ui/aura/client/screen_position_client.h"
     13 #include "ui/aura/window.h"
     14 #include "ui/compositor/layer.h"
     15 #include "ui/compositor/layer_animation_observer.h"
     16 #include "ui/compositor/layer_animation_sequence.h"
     17 #include "ui/views/widget/widget.h"
     18 
     19 namespace ash {
     20 
     21 namespace {
     22 
     23 const int kPanelCalloutFadeInDurationMilliseconds = 50;
     24 
     25 // This class extends ScopedTransformOverviewMode to hide and show the callout
     26 // widget for a panel window when entering / leaving overview mode.
     27 class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
     28  public:
     29   ScopedTransformPanelWindow(aura::Window* window);
     30   virtual ~ScopedTransformPanelWindow();
     31 
     32   // ScopedTransformOverviewWindow overrides:
     33   virtual void PrepareForOverview() OVERRIDE;
     34 
     35  private:
     36   // Returns the callout widget for the transformed panel.
     37   views::Widget* GetCalloutWidget();
     38 
     39   // Restores the callout visibility.
     40   void RestoreCallout();
     41 
     42   // Trigger relayout
     43   void Relayout();
     44 
     45   bool callout_visible_;
     46 
     47   DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
     48 };
     49 
     50 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
     51     : ScopedTransformOverviewWindow(window) {
     52 }
     53 
     54 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
     55   // window() will be NULL if the window was destroyed.
     56   if (window())
     57     RestoreCallout();
     58 }
     59 
     60 void ScopedTransformPanelWindow::PrepareForOverview() {
     61   ScopedTransformOverviewWindow::PrepareForOverview();
     62   GetCalloutWidget()->GetLayer()->SetOpacity(0.0f);
     63 }
     64 
     65 views::Widget* ScopedTransformPanelWindow::GetCalloutWidget() {
     66   DCHECK(window()->parent()->id() == internal::kShellWindowId_PanelContainer);
     67   internal::PanelLayoutManager* panel_layout_manager =
     68       static_cast<internal::PanelLayoutManager*>(
     69           window()->parent()->layout_manager());
     70   return panel_layout_manager->GetCalloutWidgetForPanel(window());
     71 }
     72 
     73 void ScopedTransformPanelWindow::RestoreCallout() {
     74   scoped_ptr<ui::LayerAnimationSequence> sequence(
     75       new ui::LayerAnimationSequence);
     76   ui::LayerAnimationElement::AnimatableProperties paused_properties;
     77   paused_properties.insert(ui::LayerAnimationElement::OPACITY);
     78   sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
     79       paused_properties, base::TimeDelta::FromMilliseconds(
     80           ScopedTransformOverviewWindow::kTransitionMilliseconds)));
     81   sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(1,
     82       base::TimeDelta::FromMilliseconds(
     83           kPanelCalloutFadeInDurationMilliseconds)));
     84   GetCalloutWidget()->GetLayer()->GetAnimator()->StartAnimation(
     85       sequence.release());
     86 }
     87 
     88 }  // namespace
     89 
     90 WindowSelectorPanels::WindowSelectorPanels() {
     91 }
     92 
     93 WindowSelectorPanels::~WindowSelectorPanels() {
     94 }
     95 
     96 void WindowSelectorPanels::AddWindow(aura::Window* window) {
     97   transform_windows_.push_back(new ScopedTransformPanelWindow(window));
     98 }
     99 
    100 aura::Window* WindowSelectorPanels::GetRootWindow() {
    101   return transform_windows_.front()->window()->GetRootWindow();
    102 }
    103 
    104 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
    105   for (WindowList::const_iterator iter = transform_windows_.begin();
    106        iter != transform_windows_.end(); ++iter) {
    107     if ((*iter)->window() == window)
    108       return true;
    109   }
    110   return false;
    111 }
    112 
    113 aura::Window* WindowSelectorPanels::TargetedWindow(const aura::Window* target) {
    114   for (WindowList::const_iterator iter = transform_windows_.begin();
    115        iter != transform_windows_.end(); ++iter) {
    116     if ((*iter)->Contains(target))
    117       return (*iter)->window();
    118   }
    119   return NULL;
    120 }
    121 
    122 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
    123   for (WindowList::iterator iter = transform_windows_.begin();
    124        iter != transform_windows_.end(); ++iter) {
    125     if ((*iter)->Contains(window)) {
    126       (*iter)->RestoreWindowOnExit();
    127       break;
    128     }
    129   }
    130 }
    131 
    132 aura::Window* WindowSelectorPanels::SelectionWindow() {
    133   return transform_windows_.front()->window();
    134 }
    135 
    136 void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
    137   for (WindowList::iterator iter = transform_windows_.begin();
    138        iter != transform_windows_.end(); ++iter) {
    139     if ((*iter)->window() == window) {
    140       (*iter)->OnWindowDestroyed();
    141       transform_windows_.erase(iter);
    142       break;
    143     }
    144   }
    145 }
    146 
    147 bool WindowSelectorPanels::empty() const {
    148   return transform_windows_.empty();
    149 }
    150 
    151 void WindowSelectorPanels::PrepareForOverview() {
    152   for (WindowList::iterator iter = transform_windows_.begin();
    153        iter != transform_windows_.end(); ++iter) {
    154     (*iter)->PrepareForOverview();
    155   }
    156 }
    157 
    158 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
    159                                          const gfx::Rect& target_bounds,
    160                                          bool animate) {
    161   gfx::Rect bounding_rect;
    162   for (WindowList::iterator iter = transform_windows_.begin();
    163        iter != transform_windows_.end(); ++iter) {
    164     bounding_rect.Union((*iter)->GetBoundsInScreen());
    165   }
    166   set_bounds(ScopedTransformOverviewWindow::
    167       ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
    168   gfx::Transform bounding_transform =
    169       ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
    170                                                          bounds());
    171   for (WindowList::iterator iter = transform_windows_.begin();
    172        iter != transform_windows_.end(); ++iter) {
    173     gfx::Transform transform;
    174     gfx::Rect bounds = (*iter)->GetBoundsInScreen();
    175     transform.Translate(bounding_rect.x() - bounds.x(),
    176                         bounding_rect.y() - bounds.y());
    177     transform.PreconcatTransform(bounding_transform);
    178     transform.Translate(bounds.x() - bounding_rect.x(),
    179                         bounds.y() - bounding_rect.y());
    180     (*iter)->SetTransform(root_window, transform, animate);
    181   }
    182 }
    183 
    184 }  // namespace ash
    185