1 // Copyright (c) 2012 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.
5 #include "ash/wm/workspace/phantom_window_controller.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/wm/coordinate_conversion.h"
10 #include "third_party/skia/include/core/SkCanvas.h"
11 #include "ui/aura/window.h"
12 #include "ui/base/animation/slide_animation.h"
13 #include "ui/compositor/layer.h"
14 #include "ui/compositor/scoped_layer_animation_settings.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/skia_util.h"
17 #include "ui/views/painter.h"
18 #include "ui/views/view.h"
19 #include "ui/views/widget/widget.h"
25 // EdgePainter ----------------------------------------------------------------
29 // Paints the background of the phantom window for window snapping.
30 class EdgePainter
: public views::Painter
{
33 virtual ~EdgePainter();
36 virtual gfx::Size
GetMinimumSize() const OVERRIDE
;
37 virtual void Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) OVERRIDE
;
40 DISALLOW_COPY_AND_ASSIGN(EdgePainter
);
46 EdgePainter::EdgePainter() {
49 EdgePainter::~EdgePainter() {
52 gfx::Size
EdgePainter::GetMinimumSize() const {
56 void EdgePainter::Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) {
57 const int kInsetSize
= 4;
60 int w
= size
.width() - kInsetSize
* 2;
61 int h
= size
.height() - kInsetSize
* 2;
62 bool inset
= (w
> 0 && h
> 0);
70 paint
.setColor(SkColorSetARGB(100, 0, 0, 0));
71 paint
.setStyle(SkPaint::kFill_Style
);
72 paint
.setAntiAlias(true);
73 const int kRoundRectSize
= 4;
74 canvas
->sk_canvas()->drawRoundRect(
75 gfx::RectToSkRect(gfx::Rect(x
, y
, w
, h
)),
76 SkIntToScalar(kRoundRectSize
), SkIntToScalar(kRoundRectSize
), paint
);
80 paint
.setColor(SkColorSetARGB(200, 255, 255, 255));
81 paint
.setStyle(SkPaint::kStroke_Style
);
82 paint
.setStrokeWidth(SkIntToScalar(2));
83 canvas
->sk_canvas()->drawRoundRect(
84 gfx::RectToSkRect(gfx::Rect(x
, y
, w
, h
)), SkIntToScalar(kRoundRectSize
),
85 SkIntToScalar(kRoundRectSize
), paint
);
89 // PhantomWindowController ----------------------------------------------------
91 PhantomWindowController::PhantomWindowController(aura::Window
* window
)
93 phantom_below_window_(NULL
),
94 phantom_widget_(NULL
) {
97 PhantomWindowController::~PhantomWindowController() {
101 void PhantomWindowController::Show(const gfx::Rect
& bounds
) {
102 if (bounds
== bounds_
)
105 if (!phantom_widget_
) {
106 // Show the phantom at the bounds of the window. We'll animate to the target
108 start_bounds_
= window_
->GetBoundsInScreen();
109 CreatePhantomWidget(start_bounds_
);
111 start_bounds_
= phantom_widget_
->GetWindowBoundsInScreen();
113 animation_
.reset(new ui::SlideAnimation(this));
114 animation_
->SetTweenType(ui::Tween::EASE_IN
);
115 const int kAnimationDurationMS
= 200;
116 animation_
->SetSlideDuration(kAnimationDurationMS
);
120 void PhantomWindowController::Hide() {
122 phantom_widget_
->Close();
123 phantom_widget_
= NULL
;
126 bool PhantomWindowController::IsShowing() const {
127 return phantom_widget_
!= NULL
;
130 void PhantomWindowController::AnimationProgressed(
131 const ui::Animation
* animation
) {
132 phantom_widget_
->SetBounds(
133 animation
->CurrentValueBetween(start_bounds_
, bounds_
));
136 void PhantomWindowController::CreatePhantomWidget(const gfx::Rect
& bounds
) {
137 DCHECK(!phantom_widget_
);
138 phantom_widget_
= new views::Widget
;
139 views::Widget::InitParams
params(views::Widget::InitParams::TYPE_POPUP
);
140 params
.transparent
= true;
141 // PhantomWindowController is used by FrameMaximizeButton to highlight the
142 // launcher button. Put the phantom in the same window as the launcher so that
143 // the phantom is visible.
144 params
.parent
= Shell::GetContainer(wm::GetRootWindowMatching(bounds
),
145 kShellWindowId_ShelfContainer
);
146 params
.can_activate
= false;
147 params
.keep_on_top
= true;
148 phantom_widget_
->set_focus_on_creation(false);
149 phantom_widget_
->Init(params
);
150 phantom_widget_
->SetVisibilityChangedAnimationsEnabled(false);
151 phantom_widget_
->GetNativeWindow()->SetName("PhantomWindow");
152 phantom_widget_
->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow
);
153 views::View
* content_view
= new views::View
;
154 content_view
->set_background(
155 views::Background::CreateBackgroundPainter(true, new EdgePainter
));
156 phantom_widget_
->SetContentsView(content_view
);
157 phantom_widget_
->SetBounds(bounds
);
158 if (phantom_below_window_
)
159 phantom_widget_
->StackBelow(phantom_below_window_
);
161 phantom_widget_
->StackAbove(window_
);
163 // Show the widget after all the setups.
164 phantom_widget_
->Show();
166 // Fade the window in.
167 ui::Layer
* widget_layer
= phantom_widget_
->GetNativeWindow()->layer();
168 widget_layer
->SetOpacity(0);
169 ui::ScopedLayerAnimationSettings
scoped_setter(widget_layer
->GetAnimator());
170 widget_layer
->SetOpacity(1);
173 } // namespace internal