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

Side by Side Diff: ui/message_center/views/message_popup_collection.cc

Issue 14817004: Makes mouse-hover prevent notification toasts from moving. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: name constant Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/message_center/views/message_popup_collection.h" 5 #include "ui/message_center/views/message_popup_collection.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 15 matching lines...) Expand all
26 #include "ui/views/view.h" 26 #include "ui/views/view.h"
27 #include "ui/views/widget/widget.h" 27 #include "ui/views/widget/widget.h"
28 #include "ui/views/widget/widget_delegate.h" 28 #include "ui/views/widget/widget_delegate.h"
29 29
30 namespace message_center { 30 namespace message_center {
31 namespace { 31 namespace {
32 32
33 // Timeout between the last user-initiated close of the toast and the moment 33 // Timeout between the last user-initiated close of the toast and the moment
34 // when normal layout/update of the toast stack continues. If the last toast was 34 // when normal layout/update of the toast stack continues. If the last toast was
35 // just closed, the timeout is shorter. 35 // just closed, the timeout is shorter.
36 const int kUpdateTimeoutOnUserActionMs = 2000; 36 const int kMouseExitedDeferTimeoutMs = 200;
37 const int kUpdateTimeoutOnUserActionEmptyMs = 700;
38 37
39 const int kToastMargin = kMarginBetweenItems; 38 const int kToastMargin = kMarginBetweenItems;
40 39
41 } // namespace. 40 } // namespace.
42 41
43 MessagePopupCollection::MessagePopupCollection(gfx::NativeView parent, 42 MessagePopupCollection::MessagePopupCollection(gfx::NativeView parent,
44 MessageCenter* message_center) 43 MessageCenter* message_center)
45 : parent_(parent), 44 : parent_(parent),
46 message_center_(message_center), 45 message_center_(message_center),
47 defer_counter_(0), 46 defer_counter_(0),
47 latest_toast_entered_(NULL),
48 user_is_closing_toasts_by_clicking_(false) { 48 user_is_closing_toasts_by_clicking_(false) {
49 DCHECK(message_center_); 49 DCHECK(message_center_);
50 defer_timer_.reset(new base::OneShotTimer<MessagePopupCollection>); 50 defer_timer_.reset(new base::OneShotTimer<MessagePopupCollection>);
51 DoUpdateIfPossible(); 51 DoUpdateIfPossible();
52 message_center_->AddObserver(this); 52 message_center_->AddObserver(this);
53 } 53 }
54 54
55 MessagePopupCollection::~MessagePopupCollection() { 55 MessagePopupCollection::~MessagePopupCollection() {
56 message_center_->RemoveObserver(this); 56 message_center_->RemoveObserver(this);
57 CloseAllWidgets(); 57 CloseAllWidgets();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 toasts_.push_back(toast); 101 toasts_.push_back(toast);
102 102
103 toast->RevealWithAnimation( 103 toast->RevealWithAnimation(
104 gfx::Point(base_position.x() - kToastMargin, bottom)); 104 gfx::Point(base_position.x() - kToastMargin, bottom));
105 bottom -= view_height + kToastMargin; 105 bottom -= view_height + kToastMargin;
106 106
107 message_center_->DisplayedNotification((*iter)->id()); 107 message_center_->DisplayedNotification((*iter)->id());
108 } 108 }
109 } 109 }
110 110
111 void MessagePopupCollection::OnMouseEntered() { 111 void MessagePopupCollection::OnMouseEntered(ToastContentsView* toast_entered) {
112 // Sometimes we can get two MouseEntered/MouseExited in a row when animating
113 // toasts. So we need to keep track of which one is the currently active one.
114 latest_toast_entered_ = toast_entered;
115
112 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end(); ++iter) { 116 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end(); ++iter) {
113 (*iter)->SuspendTimer(); 117 (*iter)->SuspendTimer();
114 } 118 }
119
120 if (user_is_closing_toasts_by_clicking_)
121 defer_timer_->Stop();
115 } 122 }
116 123
117 void MessagePopupCollection::OnMouseExited() { 124 void MessagePopupCollection::OnMouseExited(ToastContentsView* toast_exited) {
118 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end(); ++iter) { 125 // If we're exiting a toast after entering a different toast, then ignore
119 (*iter)->StartTimer(); 126 // this mouse event.
127 if (toast_exited != latest_toast_entered_)
128 return;
129 latest_toast_entered_ = NULL;
130
131 if (user_is_closing_toasts_by_clicking_) {
132 defer_timer_->Start(
133 FROM_HERE,
134 base::TimeDelta::FromMilliseconds(kMouseExitedDeferTimeoutMs),
135 this,
136 &MessagePopupCollection::OnDeferTimerExpired);
137 } else {
138 for (Toasts::iterator iter = toasts_.begin();
139 iter != toasts_.end();
140 ++iter) {
141 (*iter)->StartTimer();
142 }
120 } 143 }
121 } 144 }
122 145
123 void MessagePopupCollection::CloseAllWidgets() { 146 void MessagePopupCollection::CloseAllWidgets() {
124 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end();) { 147 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end();) {
125 // the toast can be removed from toasts_ during CloseWithAnimation(). 148 // the toast can be removed from toasts_ during CloseWithAnimation().
126 Toasts::iterator curiter = iter++; 149 Toasts::iterator curiter = iter++;
127 (*curiter)->CloseWithAnimation(); 150 (*curiter)->CloseWithAnimation();
128 } 151 }
129 DCHECK(toasts_.empty()); 152 DCHECK(toasts_.empty());
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 // normal locations after tracking the mouse pointer for easy deletion. 238 // normal locations after tracking the mouse pointer for easy deletion.
216 // This provides a period of time when toasts are easy to remove because 239 // This provides a period of time when toasts are easy to remove because
217 // they re-position themselves to have Close button right under the mouse 240 // they re-position themselves to have Close button right under the mouse
218 // pointer. If the user continue to remove the toasts, the delay is reset. 241 // pointer. If the user continue to remove the toasts, the delay is reset.
219 // Once user stopped removing the toasts, the toasts re-populate/rearrange 242 // Once user stopped removing the toasts, the toasts re-populate/rearrange
220 // after the specified delay. 243 // after the specified delay.
221 if (!user_is_closing_toasts_by_clicking_) { 244 if (!user_is_closing_toasts_by_clicking_) {
222 user_is_closing_toasts_by_clicking_ = true; 245 user_is_closing_toasts_by_clicking_ = true;
223 IncrementDeferCounter(); 246 IncrementDeferCounter();
224 } 247 }
225 int update_timeout =
226 toasts_.empty() ? kUpdateTimeoutOnUserActionEmptyMs :
227 kUpdateTimeoutOnUserActionMs;
228 defer_timer_->Start(
229 FROM_HERE,
230 base::TimeDelta::FromMilliseconds(update_timeout),
231 this,
232 &MessagePopupCollection::OnDeferTimerExpired);
233 } 248 }
234 } 249 }
235 250
236 void MessagePopupCollection::OnDeferTimerExpired() { 251 void MessagePopupCollection::OnDeferTimerExpired() {
237 user_is_closing_toasts_by_clicking_ = false; 252 user_is_closing_toasts_by_clicking_ = false;
238 DecrementDeferCounter(); 253 DecrementDeferCounter();
254
255 for (Toasts::iterator iter = toasts_.begin(); iter != toasts_.end(); ++iter) {
256 (*iter)->StartTimer();
257 }
239 } 258 }
240 259
241 void MessagePopupCollection::OnNotificationUpdated( 260 void MessagePopupCollection::OnNotificationUpdated(
242 const std::string& notification_id) { 261 const std::string& notification_id) {
243 // Find a toast. 262 // Find a toast.
244 Toasts::iterator toast_iter = toasts_.begin(); 263 Toasts::iterator toast_iter = toasts_.begin();
245 for (; toast_iter != toasts_.end(); ++toast_iter) { 264 for (; toast_iter != toasts_.end(); ++toast_iter) {
246 if ((*toast_iter)->id() == notification_id) 265 if ((*toast_iter)->id() == notification_id)
247 break; 266 break;
248 } 267 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 views::Widget* widget = (*iter)->GetWidget(); 368 views::Widget* widget = (*iter)->GetWidget();
350 if (widget) 369 if (widget)
351 return widget->GetWindowBoundsInScreen(); 370 return widget->GetWindowBoundsInScreen();
352 break; 371 break;
353 } 372 }
354 } 373 }
355 return gfx::Rect(); 374 return gfx::Rect();
356 } 375 }
357 376
358 } // namespace message_center 377 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/message_popup_collection.h ('k') | ui/message_center/views/toast_contents_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698