toast_contents_view.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/toast_contents_view.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/compiler_specific.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/weak_ptr.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/animation/animation_delegate.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/animation/slide_animation.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/display.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/screen.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/message_center.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/notification.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/message_popup_collection.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/message_view.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/view.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/widget/widget.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace message_center {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The width of a toast before animated reveal and after closing.
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kClosedToastWidth = 5;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// FadeIn/Out look a bit better if they are slightly longer then default slide.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kFadeInOutDuration = 200;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace.
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Size ToastContentsView::GetToastSizeForView(views::View* view) {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int width = kNotificationWidth + view->GetInsets().width();
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return gfx::Size(width, view->GetHeightForWidth(width));
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ToastContentsView::ToastContentsView(
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const Notification* notification,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WeakPtr<MessagePopupCollection> collection,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessageCenter* message_center)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : collection_(collection),
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      message_center_(message_center),
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      id_(notification->id()),
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      is_animating_bounds_(false),
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      is_closing_(false),
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closing_animation_(NULL) {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(collection_);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  set_notify_enter_exit_on_child(true);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Sets the transparent background. Then, when the message view is slid out,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the whole toast seems to slide although the actual bound of the widget
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // remains. This is hacky but easier to keep the consistency.
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  set_background(views::Background::CreateSolidBackground(0, 0, 0, 0));
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_.reset(new ui::SlideAnimation(this));
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->SetSlideDuration(kFadeInOutDuration);
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is destroyed when the toast window closes.
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ToastContentsView::~ToastContentsView() {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::Widget* ToastContentsView::CreateWidget(gfx::NativeView parent) {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::Widget::InitParams params(
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      views::Widget::InitParams::TYPE_POPUP);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.keep_on_top = true;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (parent)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.parent = parent;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.top_level = true;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.delegate = this;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::Widget* widget = new views::Widget();
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  widget->set_focus_on_creation(false);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  widget->Init(params);
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return widget;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::SetContents(MessageView* view) {
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool already_has_contents = child_count() > 0;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RemoveAllChildViews(true);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddChildView(view);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  preferred_size_ = GetToastSizeForView(view);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Layout();
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If it has the contents already, this invocation means an update of the
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // popup toast, and the new contents should be read through a11y feature.
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (already_has_contents)
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::RevealWithAnimation(gfx::Point origin) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Place/move the toast widgets. Currently it stacks the widgets from the
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // right-bottom of the work area.
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(mukai): allow to specify the placement policy from outside of this
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // class. The policy should be specified from preference on Windows, or
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the launcher alignment on ChromeOS.
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  origin_ = gfx::Point(origin.x() - preferred_size_.width(),
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       origin.y() - preferred_size_.height());
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect stable_bounds(origin_, preferred_size_);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetBoundsInstantly(GetClosedToastBounds(stable_bounds));
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartFadeIn();
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetBoundsWithAnimation(stable_bounds);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::CloseWithAnimation(bool mark_as_shown) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_closing_)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  is_closing_ = true;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (collection_)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    collection_->RemoveToast(this);
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (mark_as_shown)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    message_center_->MarkSinglePopupAsShown(id(), false);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartFadeOut();
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::SetBoundsInstantly(gfx::Rect new_bounds) {
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (new_bounds == bounds())
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  origin_ = new_bounds.origin();
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GetWidget())
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetWidget()->SetBounds(new_bounds);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::SetBoundsWithAnimation(gfx::Rect new_bounds) {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (new_bounds == bounds())
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  origin_ = new_bounds.origin();
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GetWidget())
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This picks up the current bounds, so if there was a previous animation
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // half-done, the next one will pick up from the current location.
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This is the only place that should query current location of the Widget
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // on screen, the rest should refer to the bounds_.
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  animated_bounds_start_ = GetWidget()->GetWindowBoundsInScreen();
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  animated_bounds_end_ = new_bounds;
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (collection_)
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    collection_->IncrementDeferCounter();
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (bounds_animation_.get())
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bounds_animation_->Stop();
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bounds_animation_.reset(new ui::SlideAnimation(this));
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bounds_animation_->Show();
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::StartFadeIn() {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The decrement is done in OnBoundsAnimationEndedOrCancelled callback.
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (collection_)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    collection_->IncrementDeferCounter();
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Stop();
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetWidget()->SetOpacity(0);
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetWidget()->Show();
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Reset(0);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Show();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ToastContentsView::StartFadeOut() {
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The decrement is done in OnBoundsAnimationEndedOrCancelled callback.
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (collection_)
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    collection_->IncrementDeferCounter();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Stop();
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  closing_animation_ = (is_closing_ ? fade_animation_.get() : NULL);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Reset(1);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fade_animation_->Hide();
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnBoundsAnimationEndedOrCancelled(
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ui::Animation* animation) {
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_closing_ && closing_animation_ == animation && GetWidget()) {
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    views::Widget* widget = GetWidget();
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(USE_AURA)
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(dewittj): This is a workaround to prevent a nasty bug where
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // closing a transparent widget doesn't actually remove the window,
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // causing entire areas of the screen to become unresponsive to clicks.
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // See crbug.com/243469
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    widget->Hide();
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# if defined(OS_WIN)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    widget->SetOpacity(0xFF);
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# endif
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    widget->Close();
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // This cannot be called before GetWidget()->Close(). Decrementing defer count
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // will invoke update, which may invoke another close animation with
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // incrementing defer counter. Close() after such process will cause a
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // mismatch between increment/decrement. See crbug.com/238477
204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (collection_)
205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    collection_->DecrementDeferCounter();
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// ui::AnimationDelegate
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::AnimationProgressed(const ui::Animation* animation) {
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (animation == bounds_animation_.get()) {
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect current(animation->CurrentValueBetween(
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        animated_bounds_start_, animated_bounds_end_));
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetWidget()->SetBounds(current);
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (animation == fade_animation_.get()) {
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned char opacity =
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        static_cast<unsigned char>(fade_animation_->GetCurrentValue() * 255);
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetWidget()->SetOpacity(opacity);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::AnimationEnded(const ui::Animation* animation) {
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OnBoundsAnimationEndedOrCancelled(animation);
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::AnimationCanceled(
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ui::Animation* animation) {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OnBoundsAnimationEndedOrCancelled(animation);
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// views::WidgetDelegate
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::View* ToastContentsView::GetContentsView() {
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return this;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::WindowClosing() {
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!is_closing_ && collection_)
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    collection_->RemoveToast(this);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ToastContentsView::CanActivate() const {
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN) && defined(USE_AURA)
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ToastContentsView::OnDisplayChanged() {
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  views::Widget* widget = GetWidget();
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!widget)
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  gfx::NativeView native_view = widget->GetNativeView();
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!native_view || !collection_)
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  collection_->OnDisplayBoundsChanged(gfx::Screen::GetScreenFor(
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      native_view)->GetDisplayNearestWindow(native_view));
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ToastContentsView::OnWorkAreaChanged() {
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  views::Widget* widget = GetWidget();
263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!widget)
264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  gfx::NativeView native_view = widget->GetNativeView();
267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!native_view || !collection_)
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  collection_->OnDisplayBoundsChanged(gfx::Screen::GetScreenFor(
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      native_view)->GetDisplayNearestWindow(native_view));
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// views::View
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnMouseEntered(const ui::MouseEvent& event) {
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (collection_)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    collection_->OnMouseEntered(this);
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnMouseExited(const ui::MouseEvent& event) {
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (collection_)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    collection_->OnMouseExited(this);
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::Layout() {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (child_count() > 0) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    child_at(0)->SetBounds(
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        0, 0, preferred_size_.width(), preferred_size_.height());
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Size ToastContentsView::GetPreferredSize() {
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return child_count() ? GetToastSizeForView(child_at(0)) : gfx::Size();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ToastContentsView::GetAccessibleState(ui::AccessibleViewState* state) {
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (child_count() > 0)
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    child_at(0)->GetAccessibleState(state);
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  state->role = ui::AccessibilityTypes::ROLE_WINDOW;
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect ToastContentsView::GetClosedToastBounds(gfx::Rect bounds) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return gfx::Rect(bounds.x() + bounds.width() - kClosedToastWidth,
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bounds.y(),
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   kClosedToastWidth,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bounds.height());
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace message_center
310