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

Side by Side Diff: chrome/browser/ui/views/message_center/web_notification_tray_win.cc

Issue 11819048: Implement message center on Windows (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Now with more tests, and corrected copyright notices. Created 7 years, 11 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/message_center/web_notification_tray_win.h"
6
7 #include "base/memory/singleton.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/status_icons/status_icon.h"
10 #include "chrome/browser/status_icons/status_tray.h"
11 #include "chrome/browser/ui/message_center/message_center_util.h"
12 #include "chrome/browser/ui/views/message_center/notification_bubble_wrapper_win .h"
13 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
14 #include "grit/theme_resources.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/base/win/hwnd_util.h"
17 #include "ui/gfx/image/image_skia_operations.h"
18 #include "ui/gfx/screen.h"
19 #include "ui/message_center/message_bubble_base.h"
20 #include "ui/message_center/message_center_bubble.h"
21 #include "ui/message_center/message_center_tray.h"
22 #include "ui/message_center/message_popup_bubble.h"
23 #include "ui/views/widget/widget.h"
24
25 namespace {
26
27 // Tray constants
28 const int kPaddingFromLeftEdgeOfSystemTrayBottomAlignment = 8;
29
30 gfx::Rect GetCornerAnchorRect(gfx::Size preferred_size) {
31 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
32 gfx::Point cursor = screen->GetCursorScreenPoint();
33 gfx::Rect rect = screen->GetPrimaryDisplay().work_area();
34 rect.Inset(10, 5);
35 gfx::Point bottom_right(
36 rect.bottom_right().x() - preferred_size.width() / 2,
37 rect.bottom_right().y());
38 return gfx::Rect(bottom_right, gfx::Size());
39 }
40
41 // GetMouseAnchorRect returns a rectangle that is near the cursor point, but
42 // whose behavior depends on where the Windows taskbar is. If it is on the
43 // top or bottom of the screen, we want the arrow to touch the edge of the
44 // taskbar directly above or below the mouse pointer and within the work area.
45 // Otherwise, position the anchor on the mouse cursor directly.
46 gfx::Rect GetMouseAnchorRect() {
47 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
48 gfx::Point cursor = screen->GetCursorScreenPoint();
49 gfx::Rect rect = screen->GetPrimaryDisplay().bounds();
50 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
51
52 // Inset the rectangle by the taskbar width if it is on top or bottom.
53 rect.set_y(work_area.y());
54 rect.set_height(work_area.height());
55
56 rect.Inset(kPaddingFromLeftEdgeOfSystemTrayBottomAlignment, 0);
57
58 // Want to find a mouse point that is on the mouse cursor, unless the mouse is
59 // over the start menu and the start menu is on the top or bottom.
60 gfx::Rect mouse_anchor_rect(gfx::BoundingRect(cursor, rect.bottom_right()));
61 mouse_anchor_rect.set_height(0);
62 if (!rect.Contains(cursor))
63 mouse_anchor_rect.AdjustToFit(rect);
64 mouse_anchor_rect.set_width(0);
65 return mouse_anchor_rect;
66 }
67
68 gfx::ImageSkia GetIcon(bool has_unread_notifications) {
69 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
70 gfx::ImageSkia* icon =
71 rb.GetImageSkiaNamed(IDR_ALLOWED_NOTIFICATION);
72 if (has_unread_notifications)
73 return *icon;
74 return gfx::ImageSkiaOperations::CreateTransparentImage(*icon, .5);
75 }
76
77 } // namespace
78
79 #if defined(ENABLE_MESSAGE_CENTER)
80
81 namespace chrome {
82
83 // static
84 ui::MessageCenterTrayDelegate* GetMessageCenterTray() {
85 return ui::WebNotificationTrayWin::GetInstance();
86 }
87
88 } // namespace chrome
89
90 #endif
91
92
93 namespace ui {
94
95 // TODO(dewittj): Determine a better ownership relationship for this.
96 WebNotificationTrayWin* WebNotificationTrayWin::GetInstance() {
97 return Singleton<WebNotificationTrayWin>::get();
98 }
99
100 WebNotificationTrayWin::WebNotificationTrayWin()
101 : status_icon_(NULL),
102 message_center_visible_(false) {
103 message_center_tray_ = new MessageCenterTray(this);
104 message_center_tray_->AddObserver(this);
105 StatusTray* status_tray = g_browser_process->status_tray();
106 status_icon_ = status_tray->CreateStatusIcon();
107 status_icon_->AddObserver(this);
108 status_icon_->SetImage(
109 GetIcon(message_center()->UnreadNotificationCount() > 0));
110 }
111
112 WebNotificationTrayWin::~WebNotificationTrayWin() {
113 message_center_tray_->RemoveObserver(this);
114 if (g_browser_process) { // We are destroyed after g_browser_process.
115 status_icon_->RemoveObserver(this);
116 StatusTray * status_tray = g_browser_process->status_tray();
117 status_tray->RemoveStatusIcon(status_icon_);
118 }
119 status_icon_ = NULL;
120 }
121
122 message_center::MessageCenter* WebNotificationTrayWin::message_center() {
123 return message_center_tray_->message_center();
124 }
125
126 bool WebNotificationTrayWin::ShowPopups(
127 message_center::MessageBubbleBase* bubble) {
128 if (!CanShowPopups())
129 return false;
130 popup_bubble_.reset(new internal::NotificationBubbleWrapperWin(
131 this,
132 bubble,
133 views::TrayBubbleView::ANCHOR_TYPE_BUBBLE));
134 return true;
135 }
136 void WebNotificationTrayWin::HidePopups() {
137 popup_bubble_.reset();
138 }
139 bool WebNotificationTrayWin::ShowMessageCenter(
140 message_center::MessageBubbleBase* bubble) {
141 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
142 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
143 gfx::Point work_area_center = work_area.CenterPoint();
144 gfx::Point anchor_center = message_center_anchor_rect_.CenterPoint();
145 int max_height = 0;
146 if (work_area_center < anchor_center)
147 max_height = anchor_center.y() - work_area.origin().y();
148 else
149 max_height = work_area.bottom() - message_center_anchor_rect_.bottom();
150 bubble->SetMaxHeight(max_height);
151
152 message_center_bubble_.reset(new internal::NotificationBubbleWrapperWin(
153 this,
154 bubble,
155 views::TrayBubbleView::ANCHOR_TYPE_TRAY));
156 return true;
157 }
158
159 void WebNotificationTrayWin::HideMessageCenter() {
160 message_center_bubble_.reset();
161 }
162
163 void WebNotificationTrayWin::UpdateMessageCenter() {
164 if (message_center_bubble_.get())
165 message_center_bubble_->bubble()->ScheduleUpdate();
166 }
167
168 void WebNotificationTrayWin::UpdatePopups() {
169 if (popup_bubble_.get())
170 popup_bubble_->bubble()->ScheduleUpdate();
171 };
172
173
174
175 void WebNotificationTrayWin::OnMessageCenterTrayChanged() {
176 bool has_unread_notifications =
177 message_center()->UnreadNotificationCount() > 0;
178 status_icon_->SetImage(GetIcon(has_unread_notifications));
179 }
180
181 gfx::Rect WebNotificationTrayWin::GetAnchorRect(
182 gfx::Size preferred_size,
183 views::TrayBubbleView::AnchorType anchor_type,
184 views::TrayBubbleView::AnchorAlignment anchor_alignment) {
185 // |message_center_visible_| is set before the bubble is actually rendered,
186 // so the flag can be used to determine which anchor to use.
187 if (anchor_type == views::TrayBubbleView::ANCHOR_TYPE_TRAY) {
188 return message_center_anchor_rect_;
189 }
190 return GetCornerAnchorRect(preferred_size);
191 }
192
193 bool WebNotificationTrayWin::CanShowPopups() {
194 // TODO(dewittj): This will eventually depend on whether quiet mode is active.
195 return true;
196 }
197
198 views::TrayBubbleView::AnchorAlignment
199 WebNotificationTrayWin::GetAnchorAlignment() {
200 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
201 // TODO(dewittj): It's possible GetPrimaryDisplay is wrong.
202 gfx::Rect screen_bounds = screen->GetPrimaryDisplay().bounds();
203 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
204
205 if (work_area.height() < screen_bounds.height())
206 return views::TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM;
207 if (work_area.x() > screen_bounds.x())
208 return views::TrayBubbleView::ANCHOR_ALIGNMENT_LEFT;
209 return views::TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT;
210 }
211
212 gfx::NativeView WebNotificationTrayWin::GetBubbleWindowContainer() {
213 return NULL;
214 }
215
216
217 void WebNotificationTrayWin::OnStatusIconClicked() {
218 UpdateAnchorRect();
219 message_center_tray_->ToggleMessageCenterBubble();
220 }
221
222 void WebNotificationTrayWin::HideBubbleWithView(
223 const views::TrayBubbleView* bubble_view) {
224 if (message_center_bubble_.get() &&
225 bubble_view == message_center_bubble_->bubble_view()) {
226 message_center_tray_->HideMessageCenterBubble();
227 } else if (popup_bubble_.get() &&
228 bubble_view == popup_bubble_->bubble_view()) {
229 message_center_tray_->HidePopupBubble();
230 }
231 }
232
233 void WebNotificationTrayWin::UpdateAnchorRect() {
234 message_center_anchor_rect_ = GetMouseAnchorRect();
235 }
236
237 message_center::MessageCenterBubble*
238 WebNotificationTrayWin::GetMessageCenterBubbleForTest() {
239 if (!message_center_bubble_.get())
240 return NULL;
241 return static_cast<message_center::MessageCenterBubble*>(
242 message_center_bubble_->bubble());
243 }
244
245 message_center::MessagePopupBubble*
246 WebNotificationTrayWin::GetPopupBubbleForTest() {
247 if (!popup_bubble_.get())
248 return NULL;
249 return static_cast<message_center::MessagePopupBubble*>(
250 popup_bubble_->bubble());
251 }
252
253 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698