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_util.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/overview/transparent_activate_window_button.h"
     12 #include "ash/wm/panels/panel_layout_manager.h"
     13 #include "ash/wm/window_util.h"
     14 #include "ui/aura/window.h"
     15 #include "ui/compositor/layer.h"
     16 #include "ui/compositor/layer_animation_observer.h"
     17 #include "ui/compositor/layer_animation_sequence.h"
     18 #include "ui/views/controls/button/button.h"
     19 
     20 namespace ash {
     21 
     22 namespace {
     23 
     24 // This class extends ScopedTransformOverviewMode to hide and show the callout
     25 // widget for a panel window when entering / leaving overview mode, as well as
     26 // to add a transparent button for each panel window.
     27 class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
     28  public:
     29   explicit ScopedTransformPanelWindow(aura::Window* window);
     30   virtual ~ScopedTransformPanelWindow();
     31 
     32   // ScopedTransformOverviewWindow overrides:
     33   virtual void PrepareForOverview() OVERRIDE;
     34 
     35   virtual void SetTransform(
     36       aura::Window* root_window,
     37       const gfx::Transform& transform,
     38       bool animate) OVERRIDE;
     39 
     40  private:
     41   // Returns the panel window bounds after the transformation.
     42   gfx::Rect GetTransformedBounds();
     43 
     44   scoped_ptr<TransparentActivateWindowButton> window_button_;
     45 
     46   DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
     47 };
     48 
     49 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
     50     : ScopedTransformOverviewWindow(window) {
     51 }
     52 
     53 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
     54 }
     55 
     56 void ScopedTransformPanelWindow::PrepareForOverview() {
     57   ScopedTransformOverviewWindow::PrepareForOverview();
     58   window_button_.reset(new TransparentActivateWindowButton(window()));
     59 }
     60 
     61 void ScopedTransformPanelWindow::SetTransform(
     62     aura::Window* root_window,
     63     const gfx::Transform& transform,
     64     bool animate) {
     65   ScopedTransformOverviewWindow::SetTransform(root_window, transform, animate);
     66   window_button_->SetBounds(GetTransformedBounds());
     67 }
     68 
     69 gfx::Rect ScopedTransformPanelWindow::GetTransformedBounds() {
     70   gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
     71           window()->GetRootWindow(), window()->layer()->bounds()));
     72   gfx::Transform new_transform;
     73   new_transform.Translate(bounds.x(),
     74                           bounds.y());
     75   new_transform.PreconcatTransform(window()->layer()->GetTargetTransform());
     76   new_transform.Translate(-bounds.x(),
     77                           -bounds.y());
     78   new_transform.TransformRect(&bounds);
     79   return ToEnclosingRect(bounds);
     80 }
     81 
     82 }  // namespace
     83 
     84 WindowSelectorPanels::WindowSelectorPanels(aura::Window* panels_root_window)
     85     : panels_root_window_(panels_root_window) {
     86   static_cast<PanelLayoutManager*>(
     87       Shell::GetContainer(panels_root_window_, kShellWindowId_PanelContainer)->
     88           layout_manager())->SetShowCalloutWidgets(false);
     89 }
     90 
     91 WindowSelectorPanels::~WindowSelectorPanels() {
     92   static_cast<PanelLayoutManager*>(
     93       Shell::GetContainer(panels_root_window_, kShellWindowId_PanelContainer)->
     94           layout_manager())->SetShowCalloutWidgets(true);
     95 }
     96 
     97 void WindowSelectorPanels::AddWindow(aura::Window* window) {
     98   DCHECK(window->GetRootWindow() == panels_root_window_);
     99   transform_windows_.push_back(new ScopedTransformPanelWindow(window));
    100 }
    101 
    102 aura::Window* WindowSelectorPanels::GetRootWindow() {
    103   return transform_windows_.front()->window()->GetRootWindow();
    104 }
    105 
    106 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
    107   for (WindowList::const_iterator iter = transform_windows_.begin();
    108        iter != transform_windows_.end(); ++iter) {
    109     if ((*iter)->window() == window)
    110       return true;
    111   }
    112   return false;
    113 }
    114 
    115 bool WindowSelectorPanels::Contains(const aura::Window* target) {
    116   for (WindowList::const_iterator iter = transform_windows_.begin();
    117        iter != transform_windows_.end(); ++iter) {
    118     if ((*iter)->Contains(target))
    119       return true;
    120   }
    121   return false;
    122 }
    123 
    124 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
    125   for (WindowList::iterator iter = transform_windows_.begin();
    126        iter != transform_windows_.end(); ++iter) {
    127     if ((*iter)->Contains(window)) {
    128       (*iter)->RestoreWindowOnExit();
    129       break;
    130     }
    131   }
    132 }
    133 
    134 aura::Window* WindowSelectorPanels::SelectionWindow() {
    135   return transform_windows_.front()->window();
    136 }
    137 
    138 void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
    139   for (WindowList::iterator iter = transform_windows_.begin();
    140        iter != transform_windows_.end(); ++iter) {
    141     if ((*iter)->window() == window) {
    142       (*iter)->OnWindowDestroyed();
    143       transform_windows_.erase(iter);
    144       break;
    145     }
    146   }
    147   WindowSelectorItem::RemoveWindow(window);
    148 }
    149 
    150 bool WindowSelectorPanels::empty() const {
    151   return transform_windows_.empty();
    152 }
    153 
    154 void WindowSelectorPanels::PrepareForOverview() {
    155   // |panel_windows| will hold all the windows in the panel container, sorted
    156   // according to their stacking order.
    157   const aura::Window::Windows panels =
    158       transform_windows_[0]->window()->parent()->children();
    159 
    160   // Call PrepareForOverview() in the reverse stacking order so that the
    161   // transparent windows that handle the events are in the correct stacking
    162   // order.
    163   size_t transformed_windows = 0;
    164   for (aura::Window::Windows::const_reverse_iterator iter = panels.rbegin();
    165       iter != panels.rend(); iter++) {
    166     for (size_t j = 0; j < transform_windows_.size(); ++j) {
    167       if (transform_windows_[j]->window() == (*iter)) {
    168         transform_windows_[j]->PrepareForOverview();
    169         transformed_windows++;
    170       }
    171     }
    172   }
    173   DCHECK(transformed_windows == transform_windows_.size());
    174 }
    175 
    176 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
    177                                          const gfx::Rect& target_bounds,
    178                                          bool animate) {
    179   gfx::Rect bounding_rect;
    180   for (WindowList::iterator iter = transform_windows_.begin();
    181        iter != transform_windows_.end(); ++iter) {
    182     bounding_rect.Union((*iter)->GetBoundsInScreen());
    183   }
    184   set_bounds(ScopedTransformOverviewWindow::
    185       ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
    186   gfx::Transform bounding_transform =
    187       ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
    188                                                          bounds());
    189   for (WindowList::iterator iter = transform_windows_.begin();
    190        iter != transform_windows_.end(); ++iter) {
    191     gfx::Transform transform;
    192     gfx::Rect bounds = (*iter)->GetBoundsInScreen();
    193     transform.Translate(bounding_rect.x() - bounds.x(),
    194                         bounding_rect.y() - bounds.y());
    195     transform.PreconcatTransform(bounding_transform);
    196     transform.Translate(bounds.x() - bounding_rect.x(),
    197                         bounds.y() - bounding_rect.y());
    198     (*iter)->SetTransform(root_window, transform, animate);
    199   }
    200 }
    201 
    202 }  // namespace ash
    203