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

Side by Side Diff: ash/common/wm/overview/window_selector_item.cc

Issue 2734653002: chromeos: Move files in //ash/common to //ash (Closed)
Patch Set: fix a11y tests, fix docs Created 3 years, 9 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
« no previous file with comments | « ash/common/wm/overview/window_selector_item.h ('k') | ash/common/wm/panels/OWNERS » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/common/wm/overview/window_selector_item.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "ash/common/material_design/material_design_controller.h"
11 #include "ash/common/metrics/user_metrics_action.h"
12 #include "ash/common/wm/overview/cleanup_animation_observer.h"
13 #include "ash/common/wm/overview/overview_animation_type.h"
14 #include "ash/common/wm/overview/scoped_overview_animation_settings.h"
15 #include "ash/common/wm/overview/scoped_overview_animation_settings_factory.h"
16 #include "ash/common/wm/overview/scoped_transform_overview_window.h"
17 #include "ash/common/wm/overview/window_selector.h"
18 #include "ash/common/wm/overview/window_selector_controller.h"
19 #include "ash/common/wm/window_state.h"
20 #include "ash/common/wm_shell.h"
21 #include "ash/common/wm_window.h"
22 #include "ash/public/cpp/shell_window_ids.h"
23 #include "ash/resources/vector_icons/vector_icons.h"
24 #include "ash/root_window_controller.h"
25 #include "ash/strings/grit/ash_strings.h"
26 #include "base/auto_reset.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/time/time.h"
30 #include "ui/base/l10n/l10n_util.h"
31 #include "ui/compositor/layer_animation_sequence.h"
32 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
33 #include "ui/gfx/animation/slide_animation.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/color_utils.h"
36 #include "ui/gfx/geometry/safe_integer_conversions.h"
37 #include "ui/gfx/paint_vector_icon.h"
38 #include "ui/gfx/transform_util.h"
39 #include "ui/strings/grit/ui_strings.h"
40 #include "ui/views/background.h"
41 #include "ui/views/border.h"
42 #include "ui/views/layout/box_layout.h"
43 #include "ui/views/window/non_client_view.h"
44 #include "ui/wm/core/shadow.h"
45 #include "ui/wm/core/window_util.h"
46
47 namespace ash {
48
49 namespace {
50
51 // In the conceptual overview table, the window margin is the space reserved
52 // around the window within the cell. This margin does not overlap so the
53 // closest distance between adjacent windows will be twice this amount.
54 static const int kWindowMargin = 5;
55
56 // Cover the transformed window including the gaps between the windows with a
57 // transparent shield to block the input events from reaching the transformed
58 // window while in overview.
59 static const int kWindowSelectorMargin = kWindowMargin * 2;
60
61 // Foreground label color.
62 static const SkColor kLabelColor = SK_ColorWHITE;
63
64 // TODO(tdanderson): Move this to a central location.
65 static const SkColor kCloseButtonColor = SK_ColorWHITE;
66
67 // Label background color once in overview mode.
68 static const SkColor kLabelBackgroundColor = SkColorSetARGB(25, 255, 255, 255);
69
70 // Label background color when exiting overview mode.
71 static const SkColor kLabelExitColor = SkColorSetARGB(255, 90, 90, 90);
72
73 // Corner radius for the selection tiles.
74 static int kLabelBackgroundRadius = 2;
75
76 // Horizontal padding for the label, on both sides.
77 static const int kHorizontalLabelPadding = 8;
78
79 // Height of an item header.
80 static const int kHeaderHeight = 32;
81
82 // Opacity for dimmed items.
83 static const float kDimmedItemOpacity = 0.5f;
84
85 // Opacity for fading out during closing a window.
86 static const float kClosingItemOpacity = 0.8f;
87
88 // Opacity for the item header.
89 static const float kHeaderOpacity =
90 (SkColorGetA(kLabelBackgroundColor) / 255.f);
91
92 // Duration it takes for the header to shift from opaque header color to
93 // |kLabelBackgroundColor|.
94 static const int kSelectorColorSlideMilliseconds = 240;
95
96 // Duration of background opacity transition for the selected label.
97 static const int kSelectorFadeInMilliseconds = 350;
98
99 // Duration of background opacity transition when exiting overview mode.
100 static const int kExitFadeInMilliseconds = 30;
101
102 // Before closing a window animate both the window and the caption to shrink by
103 // this fraction of size.
104 static const float kPreCloseScale = 0.02f;
105
106 // Convenience method to fade in a Window with predefined animation settings.
107 // Note: The fade in animation will occur after a delay where the delay is how
108 // long the lay out animations take.
109 void SetupFadeInAfterLayout(views::Widget* widget) {
110 WmWindow* window = WmWindow::Get(widget->GetNativeWindow());
111 window->SetOpacity(0.0f);
112 std::unique_ptr<ScopedOverviewAnimationSettings>
113 scoped_overview_animation_settings =
114 ScopedOverviewAnimationSettingsFactory::Get()
115 ->CreateOverviewAnimationSettings(
116 OverviewAnimationType::
117 OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN,
118 window);
119 window->SetOpacity(1.0f);
120 }
121
122 // A Button that has a listener and listens to mouse clicks on the visible part
123 // of an overview window.
124 class ShieldButton : public views::CustomButton {
125 public:
126 ShieldButton(views::ButtonListener* listener, const base::string16& name)
127 : views::CustomButton(listener) {
128 SetAccessibleName(name);
129 }
130 ~ShieldButton() override {}
131
132 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its
133 // |item_widget_| is allowed to stay around to complete any animations.
134 // Resetting the listener in all views that are targeted by events is
135 // necessary to prevent a crash when a user clicks on the fading out widget
136 // after the WindowSelectorItem has been destroyed.
137 void ResetListener() { listener_ = nullptr; }
138
139 protected:
140 // views::View:
141 const char* GetClassName() const override { return "ShieldButton"; }
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(ShieldButton);
145 };
146
147 } // namespace
148
149 WindowSelectorItem::OverviewCloseButton::OverviewCloseButton(
150 views::ButtonListener* listener)
151 : views::ImageButton(listener) {
152 SetImage(views::CustomButton::STATE_NORMAL,
153 gfx::CreateVectorIcon(kWindowControlCloseIcon, kCloseButtonColor));
154 SetImageAlignment(views::ImageButton::ALIGN_CENTER,
155 views::ImageButton::ALIGN_MIDDLE);
156 SetMinimumImageSize(gfx::Size(kHeaderHeight, kHeaderHeight));
157 }
158
159 WindowSelectorItem::OverviewCloseButton::~OverviewCloseButton() {}
160
161 // A View having rounded top corners and a specified background color which is
162 // only painted within the bounds defined by the rounded corners.
163 // This class coordinates the transitions of the overview mode header when
164 // entering the overview mode. Those animations are:
165 // - Opacity animation. The header is initially same color as the original
166 // window's header. It starts as transparent and is faded in. When the full
167 // opacity is reached the original header is hidden (which is nearly
168 // imperceptable because this view obscures the original header) and a color
169 // animation starts.
170 // - Color animation is used to change the color from the opaque color of the
171 // original window's header to semi-transparent color of the overview mode
172 // header (on entry to overview). It is also used on exit from overview to
173 // quickly change the color to a close opaque color in parallel with an
174 // opacity transition to mask the original header reappearing.
175 class WindowSelectorItem::RoundedContainerView
176 : public views::View,
177 public gfx::AnimationDelegate,
178 public ui::LayerAnimationObserver {
179 public:
180 RoundedContainerView(WindowSelectorItem* item,
181 WmWindow* item_window,
182 int corner_radius,
183 SkColor background)
184 : item_(item),
185 item_window_(item_window),
186 corner_radius_(corner_radius),
187 initial_color_(background),
188 target_color_(background),
189 current_value_(0),
190 layer_(nullptr),
191 animation_(new gfx::SlideAnimation(this)) {
192 SetPaintToLayer();
193 layer()->SetFillsBoundsOpaquely(false);
194 }
195
196 ~RoundedContainerView() override { StopObservingLayerAnimations(); }
197
198 void OnItemRestored() {
199 item_ = nullptr;
200 item_window_ = nullptr;
201 }
202
203 // Starts observing layer animations so that actions can be taken when
204 // particular animations (opacity) complete. It should only be called once
205 // when the initial fade in animation is started.
206 void ObserveLayerAnimations(ui::Layer* layer) {
207 DCHECK(!layer_);
208 layer_ = layer;
209 layer_->GetAnimator()->AddObserver(this);
210 }
211
212 // Stops observing layer animations
213 void StopObservingLayerAnimations() {
214 if (!layer_)
215 return;
216 layer_->GetAnimator()->RemoveObserver(this);
217 layer_ = nullptr;
218 }
219
220 // Used by tests to set animation state.
221 gfx::SlideAnimation* animation() { return animation_.get(); }
222
223 void set_color(SkColor target_color) { target_color_ = target_color; }
224
225 // Starts a color animation using |tween_type|. The animation will change the
226 // color from |initial_color_| to |target_color_| over |duration| specified
227 // in milliseconds.
228 // This animation can start once the implicit layer fade-in opacity animation
229 // is completed. It is used to transition color from the opaque original
230 // window header color to |kLabelBackgroundColor| on entry into overview mode
231 // and from |kLabelBackgroundColor| back to the original window header color
232 // on exit from the overview mode.
233 void AnimateColor(gfx::Tween::Type tween_type, int duration) {
234 DCHECK(!layer_); // layer animations should be completed.
235 animation_->SetSlideDuration(duration);
236 animation_->SetTweenType(tween_type);
237 animation_->Reset(0);
238 animation_->Show();
239
240 // Tests complete animations immediately. Emulate by invoking the callback.
241 if (ui::ScopedAnimationDurationScaleMode::duration_scale_mode() ==
242 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION) {
243 AnimationEnded(animation_.get());
244 }
245 }
246
247 // Changes the view opacity by animating its background color. The animation
248 // will change the alpha value in |target_color_| from its current value to
249 // |opacity| * 255 but preserve the RGB values.
250 void AnimateBackgroundOpacity(float opacity) {
251 animation_->SetSlideDuration(kSelectorFadeInMilliseconds);
252 animation_->SetTweenType(gfx::Tween::EASE_OUT);
253 animation_->Reset(0);
254 animation_->Show();
255 target_color_ = SkColorSetA(target_color_, opacity * 255);
256 }
257
258 // views::View:
259 void OnPaint(gfx::Canvas* canvas) override {
260 views::View::OnPaint(canvas);
261 SkScalar radius = SkIntToScalar(corner_radius_);
262 const SkScalar kRadius[8] = {radius, radius, radius, radius, 0, 0, 0, 0};
263 SkPath path;
264 gfx::Rect bounds(size());
265 path.addRoundRect(gfx::RectToSkRect(bounds), kRadius);
266
267 cc::PaintFlags flags;
268 flags.setAntiAlias(true);
269 canvas->ClipPath(path, true);
270
271 SkColor target_color = initial_color_;
272 if (target_color_ != target_color) {
273 target_color = color_utils::AlphaBlend(target_color_, initial_color_,
274 current_value_);
275 }
276 canvas->DrawColor(target_color);
277 }
278
279 const char* GetClassName() const override { return "RoundedContainerView"; }
280
281 private:
282 // gfx::AnimationDelegate:
283 void AnimationEnded(const gfx::Animation* animation) override {
284 initial_color_ = target_color_;
285 // Tabbed browser windows show the overview mode header behind the window
286 // during the initial animation. Once the initial fade-in completes and the
287 // overview header is fully exposed update stacking to keep the label above
288 // the item which prevents input events from reaching the window.
289 WmWindow* widget_window = WmWindow::Get(GetWidget()->GetNativeWindow());
290 if (widget_window && item_window_)
291 widget_window->GetParent()->StackChildAbove(widget_window, item_window_);
292 item_window_ = nullptr;
293 }
294
295 void AnimationProgressed(const gfx::Animation* animation) override {
296 current_value_ = animation_->CurrentValueBetween(0, 255);
297 SchedulePaint();
298 }
299
300 void AnimationCanceled(const gfx::Animation* animation) override {
301 item_window_ = nullptr;
302 initial_color_ = target_color_;
303 current_value_ = 255;
304 SchedulePaint();
305 }
306
307 // ui::LayerAnimationObserver:
308 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
309 if (0 != (sequence->properties() &
310 ui::LayerAnimationElement::AnimatableProperty::OPACITY)) {
311 if (item_)
312 item_->HideHeader();
313 StopObservingLayerAnimations();
314 AnimateColor(gfx::Tween::EASE_IN, kSelectorColorSlideMilliseconds);
315 }
316 }
317
318 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {
319 if (0 != (sequence->properties() &
320 ui::LayerAnimationElement::AnimatableProperty::OPACITY)) {
321 StopObservingLayerAnimations();
322 }
323 }
324
325 void OnLayerAnimationScheduled(
326 ui::LayerAnimationSequence* sequence) override {}
327
328 WindowSelectorItem* item_;
329 WmWindow* item_window_;
330 int corner_radius_;
331 SkColor initial_color_;
332 SkColor target_color_;
333 int current_value_;
334 ui::Layer* layer_;
335 std::unique_ptr<gfx::SlideAnimation> animation_;
336
337 DISALLOW_COPY_AND_ASSIGN(RoundedContainerView);
338 };
339
340 // A Container View that has a ShieldButton to listen to events. The
341 // ShieldButton covers most of the View except for the transparent gap between
342 // the windows and is visually transparent. The ShieldButton owns a background
343 // non-transparent view positioned at the ShieldButton top. The background view
344 // in its turn owns an item text label and a close button.
345 // The text label does not receive events, however the close button is higher in
346 // Z-order than its parent and receives events forwarding them to the same
347 // |listener| (i.e. WindowSelectorItem::ButtonPressed()).
348 class WindowSelectorItem::CaptionContainerView : public views::View {
349 public:
350 CaptionContainerView(ButtonListener* listener,
351 views::Label* label,
352 views::ImageButton* close_button,
353 WindowSelectorItem::RoundedContainerView* background)
354 : listener_button_(new ShieldButton(listener, label->text())),
355 background_(background),
356 label_(label),
357 close_button_(close_button) {
358 background_->AddChildView(label_);
359 background_->AddChildView(close_button_);
360 listener_button_->AddChildView(background_);
361 AddChildView(listener_button_);
362 }
363
364 ShieldButton* listener_button() { return listener_button_; }
365
366 protected:
367 // views::View:
368 void Layout() override {
369 // Position close button in the top right corner sized to its icon size and
370 // the label in the top left corner as tall as the button and extending to
371 // the button's left edge.
372 // The rest of this container view serves as a shield to prevent input
373 // events from reaching the transformed window in overview.
374 gfx::Rect bounds(GetLocalBounds());
375 bounds.Inset(kWindowSelectorMargin, kWindowSelectorMargin);
376 listener_button_->SetBoundsRect(bounds);
377
378 const int visible_height = close_button_->GetPreferredSize().height();
379 gfx::Rect background_bounds(gfx::Rect(bounds.size()));
380 background_bounds.set_height(visible_height);
381 background_->SetBoundsRect(background_bounds);
382
383 bounds = background_bounds;
384 bounds.Inset(kHorizontalLabelPadding, 0,
385 kHorizontalLabelPadding + visible_height, 0);
386 label_->SetBoundsRect(bounds);
387
388 bounds = background_bounds;
389 bounds.set_x(bounds.width() - visible_height);
390 bounds.set_width(visible_height);
391 close_button_->SetBoundsRect(bounds);
392 }
393
394 const char* GetClassName() const override { return "CaptionContainerView"; }
395
396 private:
397 ShieldButton* listener_button_;
398 WindowSelectorItem::RoundedContainerView* background_;
399 views::Label* label_;
400 views::ImageButton* close_button_;
401
402 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView);
403 };
404
405 WindowSelectorItem::WindowSelectorItem(WmWindow* window,
406 WindowSelector* window_selector)
407 : dimmed_(false),
408 root_window_(window->GetRootWindow()),
409 transform_window_(window),
410 in_bounds_update_(false),
411 selected_(false),
412 caption_container_view_(nullptr),
413 label_view_(nullptr),
414 close_button_(new OverviewCloseButton(this)),
415 window_selector_(window_selector),
416 background_view_(nullptr) {
417 CreateWindowLabel(window->GetTitle());
418 GetWindow()->aura_window()->AddObserver(this);
419 }
420
421 WindowSelectorItem::~WindowSelectorItem() {
422 GetWindow()->aura_window()->RemoveObserver(this);
423 }
424
425 WmWindow* WindowSelectorItem::GetWindow() {
426 return transform_window_.window();
427 }
428
429 void WindowSelectorItem::RestoreWindow() {
430 caption_container_view_->listener_button()->ResetListener();
431 close_button_->ResetListener();
432 transform_window_.RestoreWindow();
433 if (background_view_) {
434 background_view_->OnItemRestored();
435 background_view_ = nullptr;
436 }
437 UpdateHeaderLayout(
438 HeaderFadeInMode::EXIT,
439 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS);
440 }
441
442 void WindowSelectorItem::EnsureVisible() {
443 transform_window_.EnsureVisible();
444 }
445
446 void WindowSelectorItem::Shutdown() {
447 if (transform_window_.GetTopInset()) {
448 // Activating a window (even when it is the window that was active before
449 // overview) results in stacking it at the top. Maintain the label window
450 // stacking position above the item to make the header transformation more
451 // gradual upon exiting the overview mode.
452 WmWindow* widget_window = WmWindow::Get(item_widget_->GetNativeWindow());
453
454 // |widget_window| was originally created in the same container as the
455 // |transform_window_| but when closing overview the |transform_window_|
456 // could have been reparented if a drag was active. Only change stacking
457 // if the windows still belong to the same container.
458 if (widget_window->GetParent() == transform_window_.window()->GetParent()) {
459 widget_window->GetParent()->StackChildAbove(widget_window,
460 transform_window_.window());
461 }
462 }
463 if (background_view_) {
464 background_view_->OnItemRestored();
465 background_view_ = nullptr;
466 }
467 FadeOut(std::move(item_widget_));
468 }
469
470 void WindowSelectorItem::PrepareForOverview() {
471 transform_window_.PrepareForOverview();
472 UpdateHeaderLayout(HeaderFadeInMode::ENTER,
473 OverviewAnimationType::OVERVIEW_ANIMATION_NONE);
474 }
475
476 bool WindowSelectorItem::Contains(const WmWindow* target) const {
477 return transform_window_.Contains(target);
478 }
479
480 void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds,
481 OverviewAnimationType animation_type) {
482 if (in_bounds_update_)
483 return;
484 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true);
485 target_bounds_ = target_bounds;
486
487 gfx::Rect inset_bounds(target_bounds);
488 inset_bounds.Inset(kWindowMargin, kWindowMargin);
489 SetItemBounds(inset_bounds, animation_type);
490
491 // SetItemBounds is called before UpdateHeaderLayout so the header can
492 // properly use the updated windows bounds.
493 UpdateHeaderLayout(HeaderFadeInMode::UPDATE, animation_type);
494 }
495
496 void WindowSelectorItem::SetSelected(bool selected) {
497 selected_ = selected;
498 background_view_->AnimateBackgroundOpacity(selected ? 0.f : kHeaderOpacity);
499 }
500
501 void WindowSelectorItem::SendAccessibleSelectionEvent() {
502 caption_container_view_->listener_button()->NotifyAccessibilityEvent(
503 ui::AX_EVENT_SELECTION, true);
504 }
505
506 void WindowSelectorItem::CloseWindow() {
507 gfx::Rect inset_bounds(target_bounds_);
508 inset_bounds.Inset(target_bounds_.width() * kPreCloseScale,
509 target_bounds_.height() * kPreCloseScale);
510 OverviewAnimationType animation_type =
511 OverviewAnimationType::OVERVIEW_ANIMATION_CLOSING_SELECTOR_ITEM;
512 // Scale down both the window and label.
513 SetBounds(inset_bounds, animation_type);
514 // First animate opacity to an intermediate value concurrently with the
515 // scaling animation.
516 AnimateOpacity(kClosingItemOpacity, animation_type);
517
518 // Fade out the window and the label, effectively hiding them.
519 AnimateOpacity(0.0,
520 OverviewAnimationType::OVERVIEW_ANIMATION_CLOSE_SELECTOR_ITEM);
521 transform_window_.Close();
522 }
523
524 void WindowSelectorItem::HideHeader() {
525 transform_window_.HideHeader();
526 }
527
528 void WindowSelectorItem::OnMinimizedStateChanged() {
529 transform_window_.UpdateMirrorWindowForMinimizedState();
530 }
531
532 void WindowSelectorItem::SetDimmed(bool dimmed) {
533 dimmed_ = dimmed;
534 SetOpacity(dimmed ? kDimmedItemOpacity : 1.0f);
535 }
536
537 void WindowSelectorItem::ButtonPressed(views::Button* sender,
538 const ui::Event& event) {
539 if (sender == close_button_) {
540 WmShell::Get()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW_CLOSE_BUTTON);
541 CloseWindow();
542 return;
543 }
544 CHECK(sender == caption_container_view_->listener_button());
545 window_selector_->SelectWindow(this);
546 }
547
548 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) {
549 window->RemoveObserver(this);
550 transform_window_.OnWindowDestroyed();
551 }
552
553 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) {
554 // TODO(flackr): Maybe add the new title to a vector of titles so that we can
555 // filter any of the titles the window had while in the overview session.
556 label_view_->SetText(window->GetTitle());
557 UpdateAccessibilityName();
558 }
559
560 float WindowSelectorItem::GetItemScale(const gfx::Size& size) {
561 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMargin);
562 return ScopedTransformOverviewWindow::GetItemScale(
563 transform_window_.GetTargetBoundsInScreen().size(), inset_size,
564 transform_window_.GetTopInset(),
565 close_button_->GetPreferredSize().height());
566 }
567
568 gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const {
569 return transform_window_.GetTargetBoundsInScreen();
570 }
571
572 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
573 OverviewAnimationType animation_type) {
574 DCHECK(root_window_ == GetWindow()->GetRootWindow());
575 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen();
576
577 // Avoid division by zero by ensuring screen bounds is not empty.
578 gfx::Size screen_size(screen_rect.size());
579 screen_size.SetToMax(gfx::Size(1, 1));
580 screen_rect.set_size(screen_size);
581
582 const int top_view_inset = transform_window_.GetTopInset();
583 const int title_height = close_button_->GetPreferredSize().height();
584 gfx::Rect selector_item_bounds =
585 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
586 screen_rect, target_bounds, top_view_inset, title_height);
587 gfx::Transform transform = ScopedTransformOverviewWindow::GetTransformForRect(
588 screen_rect, selector_item_bounds);
589 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
590 transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
591 transform_window_.SetTransform(root_window_, transform);
592 }
593
594 void WindowSelectorItem::SetOpacity(float opacity) {
595 item_widget_->SetOpacity(opacity);
596 if (background_view_) {
597 background_view_->AnimateBackgroundOpacity(
598 selected_ ? 0.f : kHeaderOpacity * opacity);
599 }
600 transform_window_.SetOpacity(opacity);
601 }
602
603 void WindowSelectorItem::CreateWindowLabel(const base::string16& title) {
604 background_view_ = new RoundedContainerView(this, transform_window_.window(),
605 kLabelBackgroundRadius,
606 transform_window_.GetTopColor());
607 // |background_view_| will get added as a child to CaptionContainerView.
608 views::Widget::InitParams params_label;
609 params_label.type = views::Widget::InitParams::TYPE_POPUP;
610 params_label.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
611 params_label.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
612 params_label.visible_on_all_workspaces = true;
613 params_label.layer_type = ui::LAYER_NOT_DRAWN;
614 params_label.name = "OverviewModeLabel";
615 params_label.activatable =
616 views::Widget::InitParams::Activatable::ACTIVATABLE_DEFAULT;
617 params_label.accept_events = true;
618 item_widget_.reset(new views::Widget);
619 root_window_->GetRootWindowController()
620 ->ConfigureWidgetInitParamsForContainer(
621 item_widget_.get(),
622 transform_window_.window()->GetParent()->GetShellWindowId(),
623 &params_label);
624 item_widget_->set_focus_on_creation(false);
625 item_widget_->Init(params_label);
626 WmWindow* widget_window = WmWindow::Get(item_widget_->GetNativeWindow());
627 if (transform_window_.GetTopInset()) {
628 // For windows with headers the overview header fades in above the
629 // original window header.
630 widget_window->GetParent()->StackChildAbove(widget_window,
631 transform_window_.window());
632 } else {
633 // For tabbed windows the overview header slides from behind. The stacking
634 // is then corrected when the animation completes.
635 widget_window->GetParent()->StackChildBelow(widget_window,
636 transform_window_.window());
637 }
638 label_view_ = new views::Label(title);
639 label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
640 label_view_->SetAutoColorReadabilityEnabled(false);
641 label_view_->SetEnabledColor(kLabelColor);
642 // Tell the label what color it will be drawn onto. It will use whether the
643 // background color is opaque or transparent to decide whether to use
644 // subpixel rendering. Does not actually set the label's background color.
645 label_view_->SetBackgroundColor(kLabelBackgroundColor);
646
647 caption_container_view_ = new CaptionContainerView(
648 this, label_view_, close_button_, background_view_);
649 item_widget_->SetContentsView(caption_container_view_);
650 label_view_->SetVisible(false);
651 item_widget_->SetOpacity(0);
652 item_widget_->Show();
653 item_widget_->GetLayer()->SetMasksToBounds(false);
654 }
655
656 void WindowSelectorItem::UpdateHeaderLayout(
657 HeaderFadeInMode mode,
658 OverviewAnimationType animation_type) {
659 gfx::Rect transformed_window_bounds = root_window_->ConvertRectFromScreen(
660 transform_window_.GetTransformedBounds());
661
662 gfx::Rect label_rect(close_button_->GetPreferredSize());
663 label_rect.set_width(transformed_window_bounds.width());
664 // For tabbed windows the initial bounds of the caption are set such that it
665 // appears to be "growing" up from the window content area.
666 label_rect.set_y(
667 (mode != HeaderFadeInMode::ENTER || transform_window_.GetTopInset())
668 ? -label_rect.height()
669 : 0);
670 if (background_view_) {
671 if (mode == HeaderFadeInMode::ENTER) {
672 background_view_->ObserveLayerAnimations(item_widget_->GetLayer());
673 background_view_->set_color(kLabelBackgroundColor);
674 // The color will be animated only once the label widget is faded in.
675 } else if (mode == HeaderFadeInMode::EXIT) {
676 // Normally the observer is disconnected when the fade-in animations
677 // complete but some tests invoke animations with |NON_ZERO_DURATION|
678 // without waiting for completion so do it here.
679 background_view_->StopObservingLayerAnimations();
680 // Make the header visible above the window. It will be faded out when
681 // the Shutdown() is called.
682 background_view_->AnimateColor(gfx::Tween::EASE_OUT,
683 kExitFadeInMilliseconds);
684 background_view_->set_color(kLabelExitColor);
685 }
686 }
687 if (!label_view_->visible()) {
688 label_view_->SetVisible(true);
689 SetupFadeInAfterLayout(item_widget_.get());
690 }
691 WmWindow* widget_window = WmWindow::Get(item_widget_->GetNativeWindow());
692 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings =
693 ScopedOverviewAnimationSettingsFactory::Get()
694 ->CreateOverviewAnimationSettings(animation_type, widget_window);
695 // |widget_window| covers both the transformed window and the header
696 // as well as the gap between the windows to prevent events from reaching
697 // the window including its sizing borders.
698 if (mode != HeaderFadeInMode::ENTER) {
699 label_rect.set_height(close_button_->GetPreferredSize().height() +
700 transformed_window_bounds.height());
701 }
702 label_rect.Inset(-kWindowSelectorMargin, -kWindowSelectorMargin);
703 widget_window->SetBounds(label_rect);
704 gfx::Transform label_transform;
705 label_transform.Translate(transformed_window_bounds.x(),
706 transformed_window_bounds.y());
707 widget_window->SetTransform(label_transform);
708 }
709
710 void WindowSelectorItem::AnimateOpacity(float opacity,
711 OverviewAnimationType animation_type) {
712 DCHECK_GE(opacity, 0.f);
713 DCHECK_LE(opacity, 1.f);
714 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
715 transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
716 transform_window_.SetOpacity(opacity);
717
718 const float header_opacity = selected_ ? 0.f : kHeaderOpacity * opacity;
719 WmWindow* widget_window = WmWindow::Get(item_widget_->GetNativeWindow());
720 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings_label =
721 ScopedOverviewAnimationSettingsFactory::Get()
722 ->CreateOverviewAnimationSettings(animation_type, widget_window);
723 widget_window->SetOpacity(header_opacity);
724 }
725
726 void WindowSelectorItem::UpdateAccessibilityName() {
727 caption_container_view_->listener_button()->SetAccessibleName(
728 GetWindow()->GetTitle());
729 }
730
731 void WindowSelectorItem::FadeOut(std::unique_ptr<views::Widget> widget) {
732 widget->SetOpacity(1.f);
733
734 // Fade out the widget. This animation continues past the lifetime of |this|.
735 WmWindow* widget_window = WmWindow::Get(widget->GetNativeWindow());
736 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings =
737 ScopedOverviewAnimationSettingsFactory::Get()
738 ->CreateOverviewAnimationSettings(
739 OverviewAnimationType::
740 OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT,
741 widget_window);
742 // CleanupAnimationObserver will delete itself (and the widget) when the
743 // opacity animation is complete.
744 // Ownership over the observer is passed to the window_selector_->delegate()
745 // which has longer lifetime so that animations can continue even after the
746 // overview mode is shut down.
747 views::Widget* widget_ptr = widget.get();
748 std::unique_ptr<CleanupAnimationObserver> observer(
749 new CleanupAnimationObserver(std::move(widget)));
750 animation_settings->AddObserver(observer.get());
751 window_selector_->delegate()->AddDelayedAnimationObserver(
752 std::move(observer));
753 widget_ptr->SetOpacity(0.f);
754 }
755
756 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() {
757 return background_view_ ? background_view_->animation() : nullptr;
758 }
759
760 WmWindow* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() {
761 return transform_window_.GetOverviewWindowForMinimizedState();
762 }
763
764 } // namespace ash
OLDNEW
« no previous file with comments | « ash/common/wm/overview/window_selector_item.h ('k') | ash/common/wm/panels/OWNERS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698