Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / wm / overview / window_selector_window.cc
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_window.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 "grit/ash_resources.h"
12 #include "ui/aura/window.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/compositor/scoped_layer_animation_settings.h"
15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/transform.h"
17 #include "ui/views/controls/button/image_button.h"
18 #include "ui/views/widget/widget.h"
19
20 namespace ash {
21
22 namespace {
23
24 views::Widget* CreateCloseWindowButton(aura::Window* root_window,
25                                        views::ButtonListener* listener) {
26   views::Widget* widget = new views::Widget;
27   views::Widget::InitParams params;
28   params.type = views::Widget::InitParams::TYPE_POPUP;
29   params.can_activate = false;
30   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
31   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
32   params.parent =
33       Shell::GetContainer(root_window, ash::kShellWindowId_OverlayContainer);
34   widget->set_focus_on_creation(false);
35   widget->Init(params);
36   views::ImageButton* button = new views::ImageButton(listener);
37   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
38   button->SetImage(views::CustomButton::STATE_NORMAL,
39       rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE));
40   button->SetImage(views::CustomButton::STATE_HOVERED,
41       rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_H));
42   button->SetImage(views::CustomButton::STATE_PRESSED,
43       rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_P));
44   widget->SetContentsView(button);
45   widget->SetSize(rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE)->size());
46   widget->Show();
47   return widget;
48 }
49
50 }  // namespace
51
52 WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
53     : transform_window_(window) {
54 }
55
56 WindowSelectorWindow::~WindowSelectorWindow() {
57 }
58
59 aura::Window* WindowSelectorWindow::GetRootWindow() {
60   return transform_window_.window()->GetRootWindow();
61 }
62
63 bool WindowSelectorWindow::HasSelectableWindow(const aura::Window* window) {
64   return transform_window_.window() == window;
65 }
66
67 aura::Window* WindowSelectorWindow::TargetedWindow(const aura::Window* target) {
68   if (transform_window_.Contains(target))
69     return transform_window_.window();
70   return NULL;
71 }
72
73 void WindowSelectorWindow::RestoreWindowOnExit(aura::Window* window) {
74   transform_window_.RestoreWindowOnExit();
75 }
76
77 aura::Window* WindowSelectorWindow::SelectionWindow() {
78   return transform_window_.window();
79 }
80
81 void WindowSelectorWindow::RemoveWindow(const aura::Window* window) {
82   DCHECK_EQ(transform_window_.window(), window);
83   transform_window_.OnWindowDestroyed();
84   // Remove the close button now so that the exited mouse event which is
85   // delivered to the destroyed button as it is destroyed does not happen while
86   // this item is being removed from the list of windows in overview.
87   close_button_.reset();
88 }
89
90 bool WindowSelectorWindow::empty() const {
91   return transform_window_.window() == NULL;
92 }
93
94 void WindowSelectorWindow::PrepareForOverview() {
95   transform_window_.PrepareForOverview();
96 }
97
98 void WindowSelectorWindow::SetItemBounds(aura::Window* root_window,
99                                          const gfx::Rect& target_bounds,
100                                          bool animate) {
101   gfx::Rect src_rect = transform_window_.GetBoundsInScreen();
102   set_bounds(ScopedTransformOverviewWindow::
103         ShrinkRectToFitPreservingAspectRatio(src_rect, target_bounds));
104   transform_window_.SetTransform(root_window,
105       ScopedTransformOverviewWindow::GetTransformForRect(src_rect, bounds()),
106       animate);
107   // TODO move close button management to WindowSelectorItem, so that we can
108   // also handle panels.
109   // See http://crbug.com/352143
110   UpdateCloseButtonBounds(root_window, animate);
111 }
112
113 void WindowSelectorWindow::ButtonPressed(views::Button* sender,
114                          const ui::Event& event) {
115   views::Widget::GetTopLevelWidgetForNativeView(
116       transform_window_.window())->Close();
117 }
118
119 void WindowSelectorWindow::UpdateCloseButtonBounds(aura::Window* root_window,
120                                                    bool animate) {
121   gfx::Rect align_bounds(
122       ScreenUtil::ConvertRectFromScreen(root_window, bounds()));
123   gfx::Transform close_button_transform;
124   close_button_transform.Translate(align_bounds.right(), align_bounds.y());
125
126   // If the root window has changed, force the close button to be recreated
127   // and faded in on the new root window.
128   if (close_button_ &&
129       close_button_->GetNativeWindow()->GetRootWindow() != root_window) {
130     close_button_.reset();
131   }
132
133   if (!close_button_) {
134     close_button_.reset(CreateCloseWindowButton(root_window, this));
135     gfx::Rect close_button_rect(close_button_->GetNativeWindow()->bounds());
136     // Align the center of the button with position (0, 0) so that the
137     // translate transform does not need to take the button dimensions into
138     // account.
139     close_button_rect.set_x(-close_button_rect.width() / 2);
140     close_button_rect.set_y(-close_button_rect.height() / 2);
141     close_button_->GetNativeWindow()->SetBounds(close_button_rect);
142     close_button_->GetNativeWindow()->SetTransform(close_button_transform);
143     // The close button is initialized when entering overview, fade the button
144     // in after the window should be in place.
145     ui::Layer* layer = close_button_->GetNativeWindow()->layer();
146     layer->SetOpacity(0);
147     layer->GetAnimator()->StopAnimating();
148     layer->GetAnimator()->SchedulePauseForProperties(
149         base::TimeDelta::FromMilliseconds(
150             ScopedTransformOverviewWindow::kTransitionMilliseconds),
151         ui::LayerAnimationElement::OPACITY);
152     {
153       ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
154       settings.SetPreemptionStrategy(
155           ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
156       settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
157             WindowSelectorItem::kFadeInMilliseconds));
158       layer->SetOpacity(1);
159     }
160   } else {
161     if (animate) {
162       ui::ScopedLayerAnimationSettings settings(
163           close_button_->GetNativeWindow()->layer()->GetAnimator());
164       settings.SetPreemptionStrategy(
165           ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
166       settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
167           ScopedTransformOverviewWindow::kTransitionMilliseconds));
168       close_button_->GetNativeWindow()->SetTransform(close_button_transform);
169     } else {
170       close_button_->GetNativeWindow()->SetTransform(close_button_transform);
171     }
172   }
173 }
174
175 }  // namespace ash