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" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/display.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/screen.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/notification.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/message_popup_collection.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/message_view.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/background.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) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_WIN) 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using gfx::Screen; 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace message_center { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The width of a toast before animated reveal and after closing. 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kClosedToastWidth = 5; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// FadeIn/Out look a bit better if they are slightly longer then default slide. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kFadeInOutDuration = 200; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ToastContentsView::GetToastSizeForView(const views::View* view) { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int width = kNotificationWidth + view->GetInsets().width(); 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return gfx::Size(width, view->GetHeightForWidth(width)); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ToastContentsView::ToastContentsView( 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& notification_id, 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::WeakPtr<MessagePopupCollection> collection) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : collection_(collection), 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) id_(notification_id), 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_animating_bounds_(false), 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_closing_(false), 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closing_animation_(NULL) { 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set_notify_enter_exit_on_child(true); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Sets the transparent background. Then, when the message view is slid out, 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the whole toast seems to slide although the actual bound of the widget 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // remains. This is hacky but easier to keep the consistency. 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set_background(views::Background::CreateSolidBackground(0, 0, 0, 0)); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fade_animation_.reset(new gfx::SlideAnimation(this)); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->SetSlideDuration(kFadeInOutDuration); 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateWidget(collection->parent()); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is destroyed when the toast window closes. 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ToastContentsView::~ToastContentsView() { 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (collection_) 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) collection_->ForgetToast(this); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ToastContentsView::SetContents(MessageView* view, 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool a11y_feedback_for_updates) { 78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool already_has_contents = child_count() > 0; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RemoveAllChildViews(true); 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AddChildView(view); 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) preferred_size_ = GetToastSizeForView(view); 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Layout(); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If it has the contents already, this invocation means an update of the 85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // popup toast, and the new contents should be read through a11y feature. 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The notification type should be ALERT, otherwise the accessibility message 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // won't be read for this view which returns ROLE_WINDOW. 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (already_has_contents && a11y_feedback_for_updates) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, false); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void ToastContentsView::UpdateContents(const Notification& notification, 930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) bool a11y_feedback_for_updates) { 940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_GT(child_count(), 0); 950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) MessageView* message_view = static_cast<MessageView*>(child_at(0)); 960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view->UpdateWithNotification(notification); 970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (a11y_feedback_for_updates) 980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, false); 990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 1000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::RevealWithAnimation(gfx::Point origin) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Place/move the toast widgets. Currently it stacks the widgets from the 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // right-bottom of the work area. 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(mukai): allow to specify the placement policy from outside of this 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // class. The policy should be specified from preference on Windows, or 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the launcher alignment on ChromeOS. 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) origin_ = gfx::Point(origin.x() - preferred_size_.width(), 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) origin.y() - preferred_size_.height()); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect stable_bounds(origin_, preferred_size_); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetBoundsInstantly(GetClosedToastBounds(stable_bounds)); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StartFadeIn(); 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetBoundsWithAnimation(stable_bounds); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ToastContentsView::CloseWithAnimation() { 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_closing_) 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_closing_ = true; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StartFadeOut(); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::SetBoundsInstantly(gfx::Rect new_bounds) { 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (new_bounds == bounds()) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) origin_ = new_bounds.origin(); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!GetWidget()) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWidget()->SetBounds(new_bounds); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::SetBoundsWithAnimation(gfx::Rect new_bounds) { 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (new_bounds == bounds()) 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) origin_ = new_bounds.origin(); 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!GetWidget()) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This picks up the current bounds, so if there was a previous animation 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // half-done, the next one will pick up from the current location. 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This is the only place that should query current location of the Widget 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // on screen, the rest should refer to the bounds_. 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) animated_bounds_start_ = GetWidget()->GetWindowBoundsInScreen(); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) animated_bounds_end_ = new_bounds; 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (collection_) 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) collection_->IncrementDeferCounter(); 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (bounds_animation_.get()) 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bounds_animation_->Stop(); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bounds_animation_.reset(new gfx::SlideAnimation(this)); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bounds_animation_->Show(); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::StartFadeIn() { 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The decrement is done in OnBoundsAnimationEndedOrCancelled callback. 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (collection_) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) collection_->IncrementDeferCounter(); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Stop(); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWidget()->SetOpacity(0); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetWidget()->ShowInactive(); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Reset(0); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Show(); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ToastContentsView::StartFadeOut() { 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The decrement is done in OnBoundsAnimationEndedOrCancelled callback. 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (collection_) 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) collection_->IncrementDeferCounter(); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Stop(); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closing_animation_ = (is_closing_ ? fade_animation_.get() : NULL); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Reset(1); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fade_animation_->Hide(); 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnBoundsAnimationEndedOrCancelled( 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (is_closing_ && closing_animation_ == animation && GetWidget()) { 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) views::Widget* widget = GetWidget(); 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(dewittj): This is a workaround to prevent a nasty bug where 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // closing a transparent widget doesn't actually remove the window, 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // causing entire areas of the screen to become unresponsive to clicks. 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // See crbug.com/243469 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget->Hide(); 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_WIN) 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget->SetOpacity(0xFF); 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget->Close(); 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // This cannot be called before GetWidget()->Close(). Decrementing defer count 200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // will invoke update, which may invoke another close animation with 201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // incrementing defer counter. Close() after such process will cause a 202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // mismatch between increment/decrement. See crbug.com/238477 203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (collection_) 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) collection_->DecrementDeferCounter(); 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// gfx::AnimationDelegate 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ToastContentsView::AnimationProgressed(const gfx::Animation* animation) { 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (animation == bounds_animation_.get()) { 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect current(animation->CurrentValueBetween( 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) animated_bounds_start_, animated_bounds_end_)); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWidget()->SetBounds(current); 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (animation == fade_animation_.get()) { 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned char opacity = 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<unsigned char>(fade_animation_->GetCurrentValue() * 255); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWidget()->SetOpacity(opacity); 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ToastContentsView::AnimationEnded(const gfx::Animation* animation) { 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnBoundsAnimationEndedOrCancelled(animation); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::AnimationCanceled( 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnBoundsAnimationEndedOrCancelled(animation); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// views::WidgetDelegate 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::View* ToastContentsView::GetContentsView() { 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return this; 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::WindowClosing() { 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!is_closing_ && collection_.get()) 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) collection_->ForgetToast(this); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ToastContentsView::OnDisplayChanged() { 240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) views::Widget* widget = GetWidget(); 241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!widget) 242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) gfx::NativeView native_view = widget->GetNativeView(); 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!native_view || !collection_.get()) 246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) collection_->OnDisplayMetricsChanged( 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Screen::GetScreenFor(native_view)->GetDisplayNearestWindow(native_view)); 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ToastContentsView::OnWorkAreaChanged() { 253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) views::Widget* widget = GetWidget(); 254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!widget) 255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) gfx::NativeView native_view = widget->GetNativeView(); 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!native_view || !collection_.get()) 259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) collection_->OnDisplayMetricsChanged( 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Screen::GetScreenFor(native_view)->GetDisplayNearestWindow(native_view)); 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// views::View 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnMouseEntered(const ui::MouseEvent& event) { 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (collection_) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) collection_->OnMouseEntered(this); 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::OnMouseExited(const ui::MouseEvent& event) { 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (collection_) 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) collection_->OnMouseExited(this); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ToastContentsView::Layout() { 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (child_count() > 0) { 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) child_at(0)->SetBounds( 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, 0, preferred_size_.width(), preferred_size_.height()); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ToastContentsView::GetPreferredSize() const { 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return child_count() ? GetToastSizeForView(child_at(0)) : gfx::Size(); 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ToastContentsView::GetAccessibleState(ui::AXViewState* state) { 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (child_count() > 0) 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_at(0)->GetAccessibleState(state); 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_WINDOW; 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ToastContentsView::ClickOnNotification( 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& notification_id) { 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (collection_) 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) collection_->ClickOnNotification(notification_id); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ToastContentsView::RemoveNotification( 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& notification_id, 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool by_user) { 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (collection_) 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) collection_->RemoveNotification(notification_id, by_user); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<ui::MenuModel> ToastContentsView::CreateMenuModel( 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const NotifierId& notifier_id, 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& display_source) { 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should not reach, the context menu should be handled in 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // MessagePopupCollection. 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<ui::MenuModel>(); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ToastContentsView::HasClickedListener( 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& notification_id) { 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!collection_) 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return collection_->HasClickedListener(notification_id); 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ToastContentsView::ClickOnNotificationButton( 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& notification_id, 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int button_index) { 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (collection_) 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) collection_->ClickOnNotificationButton(notification_id, button_index); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ToastContentsView::CreateWidget(gfx::NativeView parent) { 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.keep_on_top = true; 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (parent) 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.parent = parent; 334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.delegate = this; 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) views::Widget* widget = new views::Widget(); 337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) widget->set_focus_on_creation(false); 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_WIN) 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We want to ensure that this toast always goes to the native desktop, 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // not the Ash desktop (since there is already another toast contents view 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // there. 343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!params.parent) 344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.native_widget = new views::DesktopNativeWidgetAura(widget); 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) widget->Init(params); 348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect ToastContentsView::GetClosedToastBounds(gfx::Rect bounds) { 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return gfx::Rect(bounds.x() + bounds.width() - kClosedToastWidth, 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bounds.y(), 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kClosedToastWidth, 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bounds.height()); 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace message_center 358