Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: ash/frame/caption_buttons/frame_caption_button_container_view.cc

Issue 271913002: Animate window control changes in TouchView (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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/frame/caption_buttons/frame_caption_button_container_view.h" 5 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <map>
8 9
9 #include "ash/ash_switches.h" 10 #include "ash/ash_switches.h"
10 #include "ash/frame/caption_buttons/alternate_frame_size_button.h" 11 #include "ash/frame/caption_buttons/alternate_frame_size_button.h"
11 #include "ash/frame/caption_buttons/frame_caption_button.h" 12 #include "ash/frame/caption_buttons/frame_caption_button.h"
12 #include "ash/frame/caption_buttons/frame_maximize_button.h" 13 #include "ash/frame/caption_buttons/frame_maximize_button.h"
13 #include "ash/metrics/user_metrics_recorder.h" 14 #include "ash/metrics/user_metrics_recorder.h"
14 #include "ash/shell.h" 15 #include "ash/shell.h"
15 #include "grit/ui_strings.h" // Accessibility names 16 #include "grit/ui_strings.h" // Accessibility names
16 #include "ui/base/hit_test.h" 17 #include "ui/base/hit_test.h"
17 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/compositor/layer.h"
18 #include "ui/compositor/scoped_animation_duration_scale_mode.h" 20 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
21 #include "ui/compositor/scoped_layer_animation_settings.h"
22 #include "ui/gfx/animation/tween.h"
19 #include "ui/gfx/canvas.h" 23 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/insets.h" 24 #include "ui/gfx/insets.h"
21 #include "ui/gfx/point.h" 25 #include "ui/gfx/point.h"
22 #include "ui/views/widget/widget.h" 26 #include "ui/views/widget/widget.h"
23 #include "ui/views/widget/widget_delegate.h" 27 #include "ui/views/widget/widget_delegate.h"
24 28
25 namespace ash { 29 namespace ash {
26 30
27 namespace { 31 namespace {
28 32
33 // Visual design parameters for animating the transition to maximize mode.
34 // When the size button hides we delay sliding the minimize button into its
35 // location. Also used to delay showing the size button so that the minimize
36 // button slides out of that position.
37 const int kAnimationDelayMs = 100;
38 const int kMinimizeSlideDurationMs = 500;
39 const int kSizeFadeDurationMs = 250;
40
29 // Converts |point| from |src| to |dst| and hittests against |dst|. 41 // Converts |point| from |src| to |dst| and hittests against |dst|.
30 bool ConvertPointToViewAndHitTest(const views::View* src, 42 bool ConvertPointToViewAndHitTest(const views::View* src,
31 const views::View* dst, 43 const views::View* dst,
32 const gfx::Point& point) { 44 const gfx::Point& point) {
33 gfx::Point converted(point); 45 gfx::Point converted(point);
34 views::View::ConvertPointToTarget(src, dst, &converted); 46 views::View::ConvertPointToTarget(src, dst, &converted);
35 return dst->HitTestPoint(converted); 47 return dst->HitTestPoint(converted);
36 } 48 }
37 49
38 } // namespace 50 } // namespace
39 51
40 // static 52 // static
41 const char FrameCaptionButtonContainerView::kViewClassName[] = 53 const char FrameCaptionButtonContainerView::kViewClassName[] =
42 "FrameCaptionButtonContainerView"; 54 "FrameCaptionButtonContainerView";
43 55
44 FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( 56 FrameCaptionButtonContainerView::FrameCaptionButtonContainerView(
45 views::Widget* frame, 57 views::Widget* frame,
46 MinimizeAllowed minimize_allowed) 58 MinimizeAllowed minimize_allowed)
47 : frame_(frame), 59 : frame_(frame),
48 minimize_button_(NULL), 60 minimize_button_(NULL),
49 size_button_(NULL), 61 size_button_(NULL),
50 close_button_(NULL) { 62 close_button_(NULL) {
51 bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle(); 63 bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle();
52 64
65 SetPaintToLayer(true);
66 SetFillsBoundsOpaquely(false);
67
53 // Insert the buttons left to right. 68 // Insert the buttons left to right.
54 minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE); 69 minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE);
55 minimize_button_->SetAccessibleName( 70 minimize_button_->SetAccessibleName(
56 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); 71 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE));
57 // Hide |minimize_button_| when using the non-alternate button style because 72 // Hide |minimize_button_| when using the non-alternate button style because
58 // |size_button_| is capable of minimizing in this case. 73 // |size_button_| is capable of minimizing in this case.
59 minimize_button_->SetVisible( 74 minimize_button_->SetVisible(
60 minimize_allowed == MINIMIZE_ALLOWED && 75 minimize_allowed == MINIMIZE_ALLOWED &&
61 (alternate_style || !frame_->widget_delegate()->CanMaximize())); 76 (alternate_style || !frame_->widget_delegate()->CanMaximize()));
77 minimize_button_->SetPaintToLayer(true);
78 minimize_button_->SetFillsBoundsOpaquely(false);
62 AddChildView(minimize_button_); 79 AddChildView(minimize_button_);
63 80
64 if (alternate_style) 81 if (alternate_style)
65 size_button_ = new AlternateFrameSizeButton(this, frame, this); 82 size_button_ = new AlternateFrameSizeButton(this, frame, this);
66 else 83 else
67 size_button_ = new FrameMaximizeButton(this, frame); 84 size_button_ = new FrameMaximizeButton(this, frame);
68 size_button_->SetAccessibleName( 85 size_button_->SetAccessibleName(
69 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); 86 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
87 size_button_->SetPaintToLayer(true);
88 size_button_->SetFillsBoundsOpaquely(false);
70 UpdateSizeButtonVisibility(false); 89 UpdateSizeButtonVisibility(false);
71 AddChildView(size_button_); 90 AddChildView(size_button_);
72 91
73 close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE); 92 close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE);
74 close_button_->SetAccessibleName( 93 close_button_->SetAccessibleName(
75 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); 94 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
95 close_button_->SetPaintToLayer(true);
96 close_button_->SetFillsBoundsOpaquely(false);
76 AddChildView(close_button_); 97 AddChildView(close_button_);
77 } 98 }
78 99
79 FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() { 100 FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() {
80 } 101 }
81 102
82 FrameMaximizeButton* 103 FrameMaximizeButton*
83 FrameCaptionButtonContainerView::GetOldStyleSizeButton() { 104 FrameCaptionButtonContainerView::GetOldStyleSizeButton() {
84 return switches::UseAlternateFrameCaptionButtonStyle() ? 105 return switches::UseAlternateFrameCaptionButtonStyle() ?
85 NULL : static_cast<FrameMaximizeButton*>(size_button_); 106 NULL : static_cast<FrameMaximizeButton*>(size_button_);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 } 157 }
137 158
138 void FrameCaptionButtonContainerView::UpdateSizeButtonVisibility( 159 void FrameCaptionButtonContainerView::UpdateSizeButtonVisibility(
139 bool force_hidden) { 160 bool force_hidden) {
140 // TODO(flackr): Refactor the Maximize Mode notifications. Currently 161 // TODO(flackr): Refactor the Maximize Mode notifications. Currently
141 // UpdateSizeButtonVisibilty requires a force_hidden parameter. This is 162 // UpdateSizeButtonVisibilty requires a force_hidden parameter. This is
142 // because Shell::IsMaximizeWindowManagerEnabled is still false at the 163 // because Shell::IsMaximizeWindowManagerEnabled is still false at the
143 // time when ShellObserver::OnMaximizeModeStarted is called. This prevents 164 // time when ShellObserver::OnMaximizeModeStarted is called. This prevents
144 // this method from performing that check, and instead relies on the calling 165 // this method from performing that check, and instead relies on the calling
145 // code to tell it to force being hidden. 166 // code to tell it to force being hidden.
146 size_button_->SetVisible( 167
147 !force_hidden && frame_->widget_delegate()->CanMaximize()); 168 bool visible = !force_hidden && frame_->widget_delegate()->CanMaximize();
169
170 // Turning visibility off prevents animations from rendering. Setting the
171 // size button visibility to false will occur after the animation.
172 if (visible)
173 size_button_->SetVisible(visible);
174
175 ui::ScopedLayerAnimationSettings settings(
176 size_button_->layer()->GetAnimator());
177 settings.SetTransitionDuration(
178 base::TimeDelta::FromMilliseconds(kSizeFadeDurationMs));
179 settings.SetPreemptionStrategy(
180 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
181
182 if (visible) {
183 settings.SetTweenType(gfx::Tween::EASE_OUT);
184 // Delay fade in so that the minimize button has begun its sliding
185 // animation.
186 size_button_->layer()->GetAnimator()->SchedulePauseForProperties(
187 base::TimeDelta::FromMilliseconds(kAnimationDelayMs),
188 ui::LayerAnimationElement::OPACITY);
189 size_button_->layer()->SetOpacity(1.0f);
190 } else {
191 settings.SetTweenType(gfx::Tween::EASE_IN);
192 // Observer will call size_button_->SetVisible(false) upon completion of
193 // the animation.
194 // TODO(jonross): avoid the delayed SetVisible(false) call by acquring
195 // the size_button's layer before making it invisible. That layer can then
196 // be animated and deleted upon completion of the animation. See
197 // LayerOwner::RecreateLayer
198 settings.AddObserver(this);
199 size_button_->layer()->SetOpacity(0.0f);
200 size_button_->layer()->SetVisible(false);
201 }
148 } 202 }
149 203
150 gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { 204 gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() {
151 int width = 0; 205 int width = 0;
152 for (int i = 0; i < child_count(); ++i) { 206 for (int i = 0; i < child_count(); ++i) {
153 views::View* child = child_at(i); 207 views::View* child = child_at(i);
154 if (child->visible()) 208 if (child->visible())
155 width += child_at(i)->GetPreferredSize().width(); 209 width += child_at(i)->GetPreferredSize().width();
156 } 210 }
157 return gfx::Size(width, close_button_->GetPreferredSize().height()); 211 return gfx::Size(width, close_button_->GetPreferredSize().height());
158 } 212 }
159 213
160 void FrameCaptionButtonContainerView::Layout() { 214 void FrameCaptionButtonContainerView::Layout() {
161 int x = 0; 215 scoped_ptr<ui::ScopedLayerAnimationSettings> animation;
162 for (int i = 0; i < child_count(); ++i) { 216 bool previous_child_animating = false;
217 bool previous_child_target_visibility = false;
218 int x = width();
219 for (int i = child_count() - 1; i >= 0; --i) {
163 views::View* child = child_at(i); 220 views::View* child = child_at(i);
164 if (!child->visible()) 221 bool child_animating = child->layer()->GetAnimator()->is_animating();
222 bool child_target_visibility = child->layer()->GetTargetVisibility();
223 if (!child->visible() ||
224 (child_animating && !child_target_visibility)) {
225 previous_child_animating = child_animating;
226 previous_child_target_visibility = child_target_visibility;
165 continue; 227 continue;
228 }
166 229
167 gfx::Size size = child->GetPreferredSize(); 230 gfx::Size size = child->GetPreferredSize();
231 // Animate the button if the previous button is currently animating
232 // its visibility.
233 if (previous_child_animating) {
234 if (previous_child_target_visibility) {
235 child->SetBounds(x, 0, size.width(), size.height());
flackr 2014/05/09 15:44:23 Couldn't this accidentally restart the slide anima
236 } else {
237 // Delay sliding to where the previous button was located.
238 child->layer()->GetAnimator()->SchedulePauseForProperties(
239 base::TimeDelta::FromMilliseconds(kAnimationDelayMs),
240 ui::LayerAnimationElement::BOUNDS);
241 }
242
243 ui::ScopedLayerAnimationSettings* settings =
244 new ui::ScopedLayerAnimationSettings(child->layer()->GetAnimator());
flackr 2014/05/09 15:44:23 This goes out of scope before the call to child->S
jonross 2014/05/09 18:41:10 It's stored in a scoped_ptr on 250, stays in scope
245 settings->SetTransitionDuration(
246 base::TimeDelta::FromMilliseconds(kMinimizeSlideDurationMs));
247 settings->SetPreemptionStrategy(
248 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
249 settings->SetTweenType(gfx::Tween::EASE_OUT);
250 animation.reset(settings);
251 previous_child_target_visibility = child->layer()->GetTargetVisibility();
flackr 2014/05/09 15:44:23 This seems redundant with line 257
252 }
253 x -= size.width();
168 child->SetBounds(x, 0, size.width(), size.height()); 254 child->SetBounds(x, 0, size.width(), size.height());
169 x += size.width(); 255
256 previous_child_animating = child->layer()->GetAnimator()->is_animating();
257 previous_child_target_visibility = child->layer()->GetTargetVisibility();
170 } 258 }
171 } 259 }
172 260
173 const char* FrameCaptionButtonContainerView::GetClassName() const { 261 const char* FrameCaptionButtonContainerView::GetClassName() const {
174 return kViewClassName; 262 return kViewClassName;
175 } 263 }
176 264
177 void FrameCaptionButtonContainerView::SetButtonIcon(FrameCaptionButton* button, 265 void FrameCaptionButtonContainerView::SetButtonIcon(FrameCaptionButton* button,
178 CaptionButtonIcon icon, 266 CaptionButtonIcon icon,
179 Animate animate) { 267 Animate animate) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 } 299 }
212 300
213 // Abort any animations of the button icons. 301 // Abort any animations of the button icons.
214 SetButtonsToNormal(ANIMATE_NO); 302 SetButtonsToNormal(ANIMATE_NO);
215 303
216 ash::UserMetricsAction action = 304 ash::UserMetricsAction action =
217 ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE; 305 ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE;
218 if (sender == minimize_button_) { 306 if (sender == minimize_button_) {
219 frame_->Minimize(); 307 frame_->Minimize();
220 } else if (sender == size_button_) { 308 } else if (sender == size_button_) {
221 if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen. 309 if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen.
222 frame_->SetFullscreen(false); 310 frame_->SetFullscreen(false);
223 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN; 311 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN;
224 } else if (frame_->IsMaximized()) { 312 } else if (frame_->IsMaximized()) {
225 frame_->Restore(); 313 frame_->Restore();
226 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE; 314 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE;
227 } else { 315 } else {
228 frame_->Maximize(); 316 frame_->Maximize();
229 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE; 317 action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE;
230 } 318 }
231 } else if(sender == close_button_) { 319 } else if (sender == close_button_) {
232 frame_->Close(); 320 frame_->Close();
233 action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK; 321 action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK;
234 } else { 322 } else {
235 return; 323 return;
236 } 324 }
237 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(action); 325 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(action);
238 } 326 }
239 327
240 bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const { 328 bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const {
241 return minimize_button_->visible(); 329 return minimize_button_->visible();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 FrameCaptionButton* button = buttons[i]; 386 FrameCaptionButton* button = buttons[i];
299 views::Button::ButtonState new_state = views::Button::STATE_NORMAL; 387 views::Button::ButtonState new_state = views::Button::STATE_NORMAL;
300 if (button == to_hover) 388 if (button == to_hover)
301 new_state = views::Button::STATE_HOVERED; 389 new_state = views::Button::STATE_HOVERED;
302 else if (button == to_press) 390 else if (button == to_press)
303 new_state = views::Button::STATE_PRESSED; 391 new_state = views::Button::STATE_PRESSED;
304 button->SetState(new_state); 392 button->SetState(new_state);
305 } 393 }
306 } 394 }
307 395
396 void FrameCaptionButtonContainerView::OnImplicitAnimationsCompleted() {
397 DCHECK(!size_button_->layer()->GetTargetVisibility());
398 size_button_->SetVisible(false);
399 // TODO(jonross): currently we need to delay telling the parent about the
400 // size change from visibility. When the size changes this forces a relayout
401 // and we want to animate both the bounds of FrameCaptionButtonContainerView
402 // along with that of its children. However when the parent is currently
403 // having its bounds changed this leads to strange animations where this view
404 // renders outside of its parents. Create a more specific animation where
405 // height and y are immediately fixed, and where we only animate width and x.
406 PreferredSizeChanged();
407 }
408
308 FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds() 409 FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds()
309 : icon_image_id(-1), 410 : icon_image_id(-1),
310 inactive_icon_image_id(-1), 411 inactive_icon_image_id(-1),
311 hovered_background_image_id(-1), 412 hovered_background_image_id(-1),
312 pressed_background_image_id(-1) { 413 pressed_background_image_id(-1) {
313 } 414 }
314 415
315 FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds( 416 FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds(
316 int icon_id, 417 int icon_id,
317 int inactive_icon_id, 418 int inactive_icon_id,
318 int hovered_background_id, 419 int hovered_background_id,
319 int pressed_background_id) 420 int pressed_background_id)
320 : icon_image_id(icon_id), 421 : icon_image_id(icon_id),
321 inactive_icon_image_id(inactive_icon_id), 422 inactive_icon_image_id(inactive_icon_id),
322 hovered_background_image_id(hovered_background_id), 423 hovered_background_image_id(hovered_background_id),
323 pressed_background_image_id(pressed_background_id) { 424 pressed_background_image_id(pressed_background_id) {
324 } 425 }
325 426
326 FrameCaptionButtonContainerView::ButtonIconIds::~ButtonIconIds() { 427 FrameCaptionButtonContainerView::ButtonIconIds::~ButtonIconIds() {
327 } 428 }
328 429
329 } // namespace ash 430 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698