OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/workspace/phantom_window_controller.h" | 5 #include "ash/wm/workspace/phantom_window_controller.h" |
6 | 6 |
7 #include "ash/ash_switches.h" | |
7 #include "ash/shell.h" | 8 #include "ash/shell.h" |
8 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
9 #include "ash/wm/coordinate_conversion.h" | 10 #include "ash/wm/coordinate_conversion.h" |
11 #include "grit/ash_resources.h" | |
10 #include "third_party/skia/include/core/SkCanvas.h" | 12 #include "third_party/skia/include/core/SkCanvas.h" |
11 #include "ui/aura/root_window.h" | 13 #include "ui/aura/root_window.h" |
12 #include "ui/aura/window.h" | 14 #include "ui/aura/window.h" |
13 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
14 #include "ui/compositor/scoped_layer_animation_settings.h" | 16 #include "ui/compositor/scoped_layer_animation_settings.h" |
15 #include "ui/gfx/animation/slide_animation.h" | |
16 #include "ui/gfx/canvas.h" | 17 #include "ui/gfx/canvas.h" |
17 #include "ui/gfx/skia_util.h" | 18 #include "ui/gfx/skia_util.h" |
18 #include "ui/views/background.h" | 19 #include "ui/views/background.h" |
19 #include "ui/views/painter.h" | 20 #include "ui/views/painter.h" |
20 #include "ui/views/view.h" | 21 #include "ui/views/view.h" |
21 #include "ui/views/widget/widget.h" | 22 #include "ui/views/widget/widget.h" |
22 | 23 |
23 namespace ash { | 24 namespace ash { |
24 namespace internal { | 25 namespace internal { |
25 | 26 |
27 namespace { | |
28 | |
29 // The duration of the bounds change animation. | |
30 const int kBoundsChangeAnimationDurationMs = 200; | |
31 | |
32 // The duration of the fade in animation to show the phantom window. | |
33 const int kShowAnimationDurationMs = 200; | |
34 | |
35 // The duration of the fade out animation to hide the phantom window. | |
36 const int kHideAnimationDurationMs = 100; | |
37 | |
38 // The amount of pixels that the shadow should extend past the window bounds | |
39 // when using the alternate caption button style. | |
40 const int kShadowThickness = 55; | |
41 | |
42 // Converts the bounds of a phantom window without a shadow to those of a | |
43 // phantom window with a shadow. | |
44 gfx::Rect GetBoundsWithShadow(const gfx::Rect& bounds) { | |
45 gfx::Rect bounds_with_shadow(bounds); | |
46 // Phantom windows have a shadow solely when using the alternate caption | |
47 // button style. | |
48 if (switches::UseAlternateFrameCaptionButtonStyle()) | |
49 bounds_with_shadow.Inset(-kShadowThickness, -kShadowThickness); | |
50 return bounds_with_shadow; | |
51 } | |
52 | |
53 // Starts an animation of |widget| to |new_bounds_in_screen|. No-op if |widget| | |
54 // is NULL. | |
55 void AnimateToBounds(views::Widget* widget, | |
56 const gfx::Rect& new_bounds_in_screen) { | |
57 if (!widget) | |
58 return; | |
59 | |
60 ui::Layer* layer = widget->GetNativeWindow()->layer(); | |
61 ui::ScopedLayerAnimationSettings scoped_setter( | |
62 layer->GetAnimator()); | |
63 scoped_setter.SetTweenType(gfx::Tween::EASE_IN); | |
64 scoped_setter.SetPreemptionStrategy( | |
65 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
sky
2013/12/19 21:25:43
Why do you want strategy?
pkotwicz
2013/12/20 01:57:20
I think that IMMEDIATELY_ANIMATE_TO_NEW_TARGET sho
| |
66 scoped_setter.SetTransitionDuration( | |
67 base::TimeDelta::FromMilliseconds(kBoundsChangeAnimationDurationMs)); | |
68 widget->SetBounds(new_bounds_in_screen); | |
69 } | |
70 | |
71 // Starts a fade in or fade out animation of |widget|. No-op if |widget| is | |
72 // NULL. | |
73 void AnimateToVisibility(views::Widget* widget, bool new_visibility) { | |
sky
2013/12/19 21:25:43
Seems like this is the same as an AnimationType of
pkotwicz
2013/12/20 01:57:20
kChildWindowVisibilityChangesAnimatedKey is false
sky
2014/01/06 17:30:05
Can't you temporarily enable animations when you c
| |
74 if (!widget) | |
75 return; | |
76 | |
77 if (new_visibility) | |
78 widget->Show(); | |
79 | |
80 int animation_duration_ms = new_visibility ? | |
81 kShowAnimationDurationMs : kHideAnimationDurationMs; | |
82 | |
83 ui::Layer* layer = widget->GetNativeWindow()->layer(); | |
84 ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator()); | |
85 scoped_setter.SetPreemptionStrategy( | |
86 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
87 scoped_setter.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | |
88 animation_duration_ms)); | |
89 if (!new_visibility) | |
90 widget->Hide(); | |
pkotwicz
2013/12/18 19:16:47
Changed so that Hide() gets called before setting
Mr4D (OOO till 08-26)
2013/12/19 17:56:55
I just checked with sky and all you would need to
pkotwicz
2013/12/19 18:18:22
I am unsure if I understand. I need to call both u
| |
91 layer->SetOpacity(new_visibility ? 1.0f : 0.0f); | |
92 } | |
93 | |
26 // EdgePainter ---------------------------------------------------------------- | 94 // EdgePainter ---------------------------------------------------------------- |
27 | 95 |
28 namespace { | |
29 | |
30 // Paints the background of the phantom window for window snapping. | 96 // Paints the background of the phantom window for window snapping. |
31 class EdgePainter : public views::Painter { | 97 class EdgePainter : public views::Painter { |
32 public: | 98 public: |
33 EdgePainter(); | 99 EdgePainter(); |
34 virtual ~EdgePainter(); | 100 virtual ~EdgePainter(); |
35 | 101 |
36 // views::Painter: | 102 // views::Painter: |
37 virtual gfx::Size GetMinimumSize() const OVERRIDE; | 103 virtual gfx::Size GetMinimumSize() const OVERRIDE; |
38 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE; | 104 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE; |
39 | 105 |
40 private: | 106 private: |
41 DISALLOW_COPY_AND_ASSIGN(EdgePainter); | 107 DISALLOW_COPY_AND_ASSIGN(EdgePainter); |
42 }; | 108 }; |
43 | 109 |
44 } // namespace | |
45 | |
46 | |
47 EdgePainter::EdgePainter() { | 110 EdgePainter::EdgePainter() { |
48 } | 111 } |
49 | 112 |
50 EdgePainter::~EdgePainter() { | 113 EdgePainter::~EdgePainter() { |
51 } | 114 } |
52 | 115 |
53 gfx::Size EdgePainter::GetMinimumSize() const { | 116 gfx::Size EdgePainter::GetMinimumSize() const { |
54 return gfx::Size(); | 117 return gfx::Size(); |
55 } | 118 } |
56 | 119 |
(...skipping 22 matching lines...) Expand all Loading... | |
79 return; | 142 return; |
80 | 143 |
81 paint.setColor(SkColorSetARGB(200, 255, 255, 255)); | 144 paint.setColor(SkColorSetARGB(200, 255, 255, 255)); |
82 paint.setStyle(SkPaint::kStroke_Style); | 145 paint.setStyle(SkPaint::kStroke_Style); |
83 paint.setStrokeWidth(SkIntToScalar(2)); | 146 paint.setStrokeWidth(SkIntToScalar(2)); |
84 canvas->sk_canvas()->drawRoundRect( | 147 canvas->sk_canvas()->drawRoundRect( |
85 gfx::RectToSkRect(gfx::Rect(x, y, w, h)), SkIntToScalar(kRoundRectSize), | 148 gfx::RectToSkRect(gfx::Rect(x, y, w, h)), SkIntToScalar(kRoundRectSize), |
86 SkIntToScalar(kRoundRectSize), paint); | 149 SkIntToScalar(kRoundRectSize), paint); |
87 } | 150 } |
88 | 151 |
152 } // namespace | |
89 | 153 |
90 // PhantomWindowController ---------------------------------------------------- | 154 // PhantomWindowController ---------------------------------------------------- |
91 | 155 |
92 PhantomWindowController::PhantomWindowController(aura::Window* window) | 156 PhantomWindowController::PhantomWindowController(aura::Window* window) |
93 : window_(window), | 157 : window_(window), |
94 phantom_below_window_(NULL), | 158 phantom_below_window_(NULL), |
95 phantom_widget_(NULL), | 159 target_visibility_(false) { |
96 phantom_widget_start_(NULL) { | |
97 } | 160 } |
98 | 161 |
99 PhantomWindowController::~PhantomWindowController() { | 162 PhantomWindowController::~PhantomWindowController() { |
100 Hide(); | |
101 } | 163 } |
102 | 164 |
103 void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { | 165 void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { |
104 if (bounds_in_screen == bounds_in_screen_) | 166 if (GetBoundsWithShadow(bounds_in_screen) == target_bounds_in_screen_ && |
167 target_visibility_) { | |
105 return; | 168 return; |
106 bounds_in_screen_ = bounds_in_screen; | 169 } |
107 aura::Window* target_root = wm::GetRootWindowMatching(bounds_in_screen); | 170 if (target_phantom_widget_ && |
108 // Show the phantom at the current bounds of the window. We'll animate to the | 171 !target_phantom_widget_->GetNativeView()->layer()->IsDrawn()) { |
pkotwicz
2013/12/18 19:16:47
I made the phantom window start animating from |wi
| |
109 // target bounds. If phantom exists, update the start bounds. | 172 target_phantom_widget_.reset(); |
110 if (!phantom_widget_) | 173 start_phantom_widget_.reset(); |
111 start_bounds_ = window_->GetBoundsInScreen(); | 174 } |
175 StartFade(true); | |
176 | |
177 target_bounds_in_screen_ = GetBoundsWithShadow(bounds_in_screen); | |
178 gfx::Rect start_bounds; | |
179 if (!target_phantom_widget_) | |
180 start_bounds = GetBoundsWithShadow(window_->GetBoundsInScreen()); | |
pkotwicz
2013/12/18 19:16:47
Fixed when GetBoundsWithShadow() is called. In the
| |
112 else | 181 else |
113 start_bounds_ = phantom_widget_->GetWindowBoundsInScreen(); | 182 start_bounds = target_phantom_widget_->GetWindowBoundsInScreen(); |
114 if (phantom_widget_ && | 183 |
115 phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) { | 184 aura::Window* target_root = |
116 phantom_widget_->Close(); | 185 wm::GetRootWindowMatching(target_bounds_in_screen_); |
117 phantom_widget_ = NULL; | 186 if (!target_phantom_widget_ || |
187 target_phantom_widget_->GetNativeWindow()->GetRootWindow() != | |
188 target_root) { | |
189 target_phantom_widget_.reset( | |
190 CreatePhantomWidget(target_root, start_bounds)); | |
118 } | 191 } |
119 if (!phantom_widget_) | 192 AnimateToBounds(target_phantom_widget_.get(), target_bounds_in_screen_); |
120 phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_); | |
121 | 193 |
122 // Create a secondary widget in a second screen if start_bounds_ lie at least | 194 // Create a secondary widget in a second screen if |start_bounds| lies at |
123 // partially in that other screen. This allows animations to start or restart | 195 // least partially in another screen. This allows animations to start or |
124 // in one root window and progress into another root. | 196 // restart in one root window and progress to another root. |
125 aura::Window* start_root = wm::GetRootWindowMatching(start_bounds_); | 197 aura::Window* start_root = wm::GetRootWindowMatching(start_bounds); |
126 if (start_root == target_root) { | 198 if (start_root == target_root) { |
127 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 199 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
128 for (size_t i = 0; i < root_windows.size(); ++i) { | 200 for (size_t i = 0; i < root_windows.size(); ++i) { |
129 if (root_windows[i] != target_root && | 201 if (root_windows[i] != target_root && |
130 root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) { | 202 root_windows[i]->GetBoundsInScreen().Intersects(start_bounds)) { |
131 start_root = root_windows[i]; | 203 start_root = root_windows[i]; |
132 break; | 204 break; |
133 } | 205 } |
134 } | 206 } |
135 } | 207 } |
136 if (phantom_widget_start_ && | 208 if (start_root == target_root) { |
137 (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root | 209 start_phantom_widget_.reset(); |
138 || start_root == target_root)) { | 210 } else { |
139 phantom_widget_start_->Close(); | 211 if (!start_phantom_widget_ || |
140 phantom_widget_start_ = NULL; | 212 start_phantom_widget_->GetNativeWindow()->GetRootWindow() != |
213 start_root) { | |
214 start_phantom_widget_.reset( | |
215 CreatePhantomWidget(start_root, start_bounds)); | |
216 } | |
217 AnimateToBounds(start_phantom_widget_.get(), target_bounds_in_screen_); | |
141 } | 218 } |
142 if (!phantom_widget_start_ && start_root != target_root) | 219 } |
143 phantom_widget_start_ = CreatePhantomWidget(start_root, start_bounds_); | |
144 | 220 |
145 animation_.reset(new gfx::SlideAnimation(this)); | 221 void PhantomWindowController::StartFadeOut() { |
146 animation_->SetTweenType(gfx::Tween::EASE_IN); | 222 StartFade(false); |
147 const int kAnimationDurationMS = 200; | |
148 animation_->SetSlideDuration(kAnimationDurationMS); | |
149 animation_->Show(); | |
150 } | 223 } |
151 | 224 |
152 void PhantomWindowController::Hide() { | 225 void PhantomWindowController::Hide() { |
153 if (phantom_widget_) | 226 target_visibility_ = false; |
154 phantom_widget_->Close(); | 227 target_phantom_widget_.reset(); |
155 phantom_widget_ = NULL; | 228 start_phantom_widget_.reset(); |
156 if (phantom_widget_start_) | |
157 phantom_widget_start_->Close(); | |
158 phantom_widget_start_ = NULL; | |
159 } | 229 } |
160 | 230 |
161 bool PhantomWindowController::IsShowing() const { | 231 bool PhantomWindowController::IsShowing() const { |
162 return phantom_widget_ != NULL; | 232 return target_visibility_; |
163 } | |
164 | |
165 void PhantomWindowController::AnimationProgressed( | |
166 const gfx::Animation* animation) { | |
167 const gfx::Rect current_bounds = | |
168 animation->CurrentValueBetween(start_bounds_, bounds_in_screen_); | |
169 if (phantom_widget_start_) | |
170 phantom_widget_start_->SetBounds(current_bounds); | |
171 phantom_widget_->SetBounds(current_bounds); | |
172 } | 233 } |
173 | 234 |
174 views::Widget* PhantomWindowController::CreatePhantomWidget( | 235 views::Widget* PhantomWindowController::CreatePhantomWidget( |
175 aura::Window* root_window, | 236 aura::Window* root_window, |
176 const gfx::Rect& bounds_in_screen) { | 237 const gfx::Rect& bounds_in_screen) { |
177 views::Widget* phantom_widget = new views::Widget; | 238 views::Widget* phantom_widget = new views::Widget; |
178 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); | 239 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
179 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 240 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
180 // PhantomWindowController is used by FrameMaximizeButton to highlight the | 241 // PhantomWindowController is used by FrameMaximizeButton to highlight the |
181 // launcher button. Put the phantom in the same window as the launcher so that | 242 // launcher button. Put the phantom in the same window as the launcher so that |
182 // the phantom is visible. | 243 // the phantom is visible. |
183 params.parent = Shell::GetContainer(root_window, | 244 params.parent = Shell::GetContainer(root_window, |
184 kShellWindowId_ShelfContainer); | 245 kShellWindowId_ShelfContainer); |
185 params.can_activate = false; | 246 params.can_activate = false; |
186 params.keep_on_top = true; | 247 params.keep_on_top = true; |
248 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
187 phantom_widget->set_focus_on_creation(false); | 249 phantom_widget->set_focus_on_creation(false); |
188 phantom_widget->Init(params); | 250 phantom_widget->Init(params); |
189 phantom_widget->SetVisibilityChangedAnimationsEnabled(false); | 251 phantom_widget->SetVisibilityChangedAnimationsEnabled(false); |
190 phantom_widget->GetNativeWindow()->SetName("PhantomWindow"); | 252 phantom_widget->GetNativeWindow()->SetName("PhantomWindow"); |
191 phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); | 253 phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); |
192 views::View* content_view = new views::View; | |
193 content_view->set_background( | |
194 views::Background::CreateBackgroundPainter(true, new EdgePainter)); | |
195 phantom_widget->SetContentsView(content_view); | |
196 phantom_widget->SetBounds(bounds_in_screen); | 254 phantom_widget->SetBounds(bounds_in_screen); |
197 if (phantom_below_window_) | 255 if (phantom_below_window_) |
198 phantom_widget->StackBelow(phantom_below_window_); | 256 phantom_widget->StackBelow(phantom_below_window_); |
199 else | 257 else |
200 phantom_widget->StackAbove(window_); | 258 phantom_widget->StackAbove(window_); |
201 | 259 |
202 // Show the widget after all the setups. | 260 views::Painter* background_painter; |
203 phantom_widget->Show(); | 261 if (switches::UseAlternateFrameCaptionButtonStyle()) { |
262 const int kImages[] = IMAGE_GRID(IDR_AURA_PHANTOM_WINDOW); | |
263 background_painter = views::Painter::CreateImageGridPainter(kImages); | |
264 } else { | |
265 background_painter = new EdgePainter; | |
266 } | |
267 views::View* content_view = new views::View; | |
268 content_view->set_background( | |
269 views::Background::CreateBackgroundPainter(true, background_painter)); | |
270 phantom_widget->SetContentsView(content_view); | |
204 | 271 |
205 // Fade the window in. | 272 // Fade the window in. |
206 ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer(); | 273 ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer(); |
207 widget_layer->SetOpacity(0); | 274 widget_layer->SetOpacity(0); |
208 ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator()); | 275 AnimateToVisibility(phantom_widget, true); |
209 widget_layer->SetOpacity(1); | |
210 return phantom_widget; | 276 return phantom_widget; |
211 } | 277 } |
212 | 278 |
279 void PhantomWindowController::StartFade(bool fade_in) { | |
280 if (target_visibility_ != fade_in) { | |
281 target_visibility_ = fade_in; | |
282 AnimateToVisibility(target_phantom_widget_.get(), target_visibility_); | |
283 AnimateToVisibility(start_phantom_widget_.get(), target_visibility_); | |
284 } | |
285 } | |
286 | |
213 } // namespace internal | 287 } // namespace internal |
214 } // namespace ash | 288 } // namespace ash |
OLD | NEW |