12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/gtest_prod_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/display.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/display_observer.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/native_widget_types.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/rect.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/message_center_export.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/message_center_observer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/widget_observer.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class RunLoop;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace views {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Widget;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ash {
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class WebNotificationTrayTest;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FORWARD_DECLARE_TEST(WebNotificationTrayTest, ManyPopupNotifications);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace message_center {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MessagePopupCollectionTest;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MessageCenter;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass MessageCenterTray;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ToastContentsView;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)enum PopupAlignment {
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  POPUP_ALIGNMENT_TOP = 1 << 0,
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  POPUP_ALIGNMENT_LEFT = 1 << 1,
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  POPUP_ALIGNMENT_BOTTOM = 1 << 2,
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  POPUP_ALIGNMENT_RIGHT = 1 << 3,
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Container for popup toasts. Because each toast is a frameless window rather
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// than a view in a bubble, now the container just manages all of those toasts.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is similar to chrome/browser/notifications/balloon_collection, but the
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// contents of each toast are for the message center and layout strategy would
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// be slightly different.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MESSAGE_CENTER_EXPORT MessagePopupCollection
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public MessageCenterObserver,
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      public gfx::DisplayObserver,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public base::SupportsWeakPtr<MessagePopupCollection> {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |parent| specifies the parent widget of the toast windows. The default
63bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // parent will be used for NULL. Usually each icon is spacing against its
64bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // predecessor. If |first_item_has_no_margin| is set however the first item
65bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // does not space against the tray.
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessagePopupCollection(gfx::NativeView parent,
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         MessageCenter* message_center,
68bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         MessageCenterTray* tray,
69bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         bool first_item_has_no_margin);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MessagePopupCollection();
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by ToastContentsView when its window is closed.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RemoveToast(ToastContentsView* toast);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Since these events are really coming from individual toast widgets,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // it helps to be able to keep track of the sender.
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnMouseEntered(ToastContentsView* toast_entered);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnMouseExited(ToastContentsView* toast_exited);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invoked by toasts when they start/finish their animations.
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // While "defer counter" is greater then zero, the popup collection does
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // not perform updates. It is used to wait for various animations and user
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // actions like serial closing of the toasts, when the remaining toasts "flow
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // under the mouse".
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void IncrementDeferCounter();
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DecrementDeferCounter();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Runs the next step in update/animate sequence, if the defer counter is not
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // zero. Otherwise, simply waits when it becomes zero.
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DoUpdateIfPossible();
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Updates |work_area_| and re-calculates the alignment of notification toasts
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // rearranging them if necessary.
94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // This is separated from methods from OnDisplayBoundsChanged(), since
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // sometimes the display info has to be specified directly. One example is
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // shelf's auto-hide change. When the shelf in ChromeOS is temporarily shown
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // from auto hide status, it doesn't change the display's work area but the
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // actual work area for toasts should be resized.
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void SetDisplayInfo(const gfx::Rect& work_area,
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                      const gfx::Rect& screen_bounds);
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Overridden from gfx::DislayObserver:
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(ash::WebNotificationTrayTest,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           ManyPopupNotifications);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  friend class test::MessagePopupCollectionTest;
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  friend class ash::WebNotificationTrayTest;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef std::list<ToastContentsView*> Toasts;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CloseAllWidgets();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Returns the x-origin for the given toast bounds in the current work area.
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int GetToastOriginX(const gfx::Rect& toast_bounds);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Iterates toasts and starts closing the expired ones.
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void CloseToasts();
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Creates new widgets for new toast notifications, and updates |toasts_| and
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |widgets_| correctly.
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UpdateWidgets();
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Repositions all of the widgets based on the current work area.
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RepositionWidgets();
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Repositions widgets to the top edge of the notification toast that was
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // just removed, so that the user can click close button without mouse moves.
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // See crbug.com/224089
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RepositionWidgetsWithTarget();
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void ComputePopupAlignment(gfx::Rect work_area, gfx::Rect screen_bounds);
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The base line is an (imaginary) line that would touch the bottom of the
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // next created notification if bottom-aligned or its top if top-aligned.
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int GetBaseLine(ToastContentsView* last_toast);
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from MessageCenterObserver:
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnNotificationAdded(const std::string& notification_id) OVERRIDE;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnNotificationRemoved(const std::string& notification_id,
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     bool by_user) OVERRIDE;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnNotificationUpdated(
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const std::string& notification_id) OVERRIDE;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ToastContentsView* FindToast(const std::string& notification_id);
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // While the toasts are animated, avoid updating the collection, to reduce
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // user confusion. Instead, update the collection when all animations are
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // done. This method is run when defer counter is zero, may initiate next
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // update/animation step.
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void PerformDeferredTasks();
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnDeferTimerExpired();
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // "ForTest" methods.
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::Widget* GetWidgetForTest(const std::string& id);
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RunLoopForTest();
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect GetToastRectAt(size_t index);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::NativeView parent_;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MessageCenter* message_center_;
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MessageCenterTray* tray_;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Toasts toasts_;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect work_area_;
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 display_id_;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Specifies which corner of the screen popups should show up. This should
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // ideally be the same corner the notification area (systray) is at.
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PopupAlignment alignment_;
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int defer_counter_;
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This is only used to compare with incoming events, do not assume that
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the toast will be valid if this pointer is non-NULL.
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ToastContentsView* latest_toast_entered_;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Denotes a mode when user is clicking the Close button of toasts in a
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // sequence, w/o moving the mouse. We reposition the toasts so the next one
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // happens to be right under the mouse, and the user can just dispose of
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // multipel toasts by clicking. The mode ends when defer_timer_ expires.
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool user_is_closing_toasts_by_clicking_;
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::OneShotTimer<MessagePopupCollection> > defer_timer_;
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The top edge to align the position of the next toast during 'close by
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // clicking" mode.
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only to be used when user_is_closing_toasts_by_clicking_ is true.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int target_top_edge_;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Weak, only exists temporarily in tests.
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_for_test_;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // True if the first item should not have spacing against the tray.
193bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  bool first_item_has_no_margin_;
194bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MessagePopupCollection);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace message_center
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_
201