Index: chrome/browser/ui/views/message_center/message_center_tray_host_win.cc |
diff --git a/chrome/browser/ui/views/message_center/message_center_tray_host_win.cc b/chrome/browser/ui/views/message_center/message_center_tray_host_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e59f437fc72015fa01cef9dbd0872c3d4aba6e96 |
--- /dev/null |
+++ b/chrome/browser/ui/views/message_center/message_center_tray_host_win.cc |
@@ -0,0 +1,190 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/ui/views/message_center/message_center_tray_host_win.h" |
+ |
+#include "base/memory/singleton.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/status_icons/status_icon.h" |
+#include "chrome/browser/status_icons/status_tray.h" |
+#include "chrome/browser/ui/message_center/message_center_util.h" |
+#include "grit/theme_resources.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/base/win/hwnd_util.h" |
+#include "ui/gfx/image/image_skia_operations.h" |
+#include "ui/gfx/screen.h" |
+#include "ui/message_center/message_center_tray.h" |
+ |
+namespace { |
+ |
+// Tray constants |
+const int kPaddingFromLeftEdgeOfSystemTrayBottomAlignment = 8; |
+ |
+gfx::Rect GetCornerAnchorRect() { |
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen(); |
+ gfx::Point cursor = screen->GetCursorScreenPoint(); |
+ gfx::Rect rect = screen->GetPrimaryDisplay().work_area(); |
+ rect.Inset(kPaddingFromLeftEdgeOfSystemTrayBottomAlignment, 0); |
+ return gfx::Rect(rect.bottom_right(), gfx::Size()); |
+} |
+ |
+// GetMouseAnchorRect returns a rectangle that is near the cursor point, but |
+// whose behavior depends on where the Windows taskbar is. If it is on the |
+// top or bottom of the screen, we want the arrow to touch the edge of the |
+// taskbar directly above or below the mouse pointer and within the work area. |
+// Otherwise, position the anchor on the mouse cursor directly. |
+gfx::Rect GetMouseAnchorRect() { |
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen(); |
+ gfx::Point cursor = screen->GetCursorScreenPoint(); |
+ gfx::Rect rect = screen->GetPrimaryDisplay().bounds(); |
+ gfx::Rect work_area = screen->GetPrimaryDisplay().work_area(); |
+ |
+ // Inset the rectangle by the taskbar width if it is on top or bottom. |
+ rect.set_y(work_area.y()); |
+ rect.set_height(work_area.height()); |
+ |
+ rect.Inset(kPaddingFromLeftEdgeOfSystemTrayBottomAlignment, 0); |
+ |
+ // Want to find a mouse point that is on the mouse cursor, unless the mouse is |
+ // over the start menu and the start menu is on the top or bottom. |
+ gfx::Rect mouse_anchor_rect(gfx::BoundingRect(cursor, rect.bottom_right())); |
+ mouse_anchor_rect.set_height(0); |
+ if (!rect.Contains(cursor)) |
+ mouse_anchor_rect.AdjustToFit(rect); |
+ mouse_anchor_rect.set_width(0); |
+ return mouse_anchor_rect; |
+} |
+ |
+} // namespace |
+ |
+#if defined(ENABLE_MESSAGE_CENTER) |
+ |
+namespace chrome { |
+ |
+// static |
+ui::MessageCenterTrayHost* GetMessageCenterTray() { |
+ return ui::MessageCenterTrayHostWin::GetInstance(); |
+} |
+ |
+} // namespace chrome |
+ |
+#endif |
+ |
+ |
+namespace ui { |
+ |
+// TODO(dewittj): Un-singleton. |
+MessageCenterTrayHostWin* MessageCenterTrayHostWin::GetInstance() { |
+ return Singleton<MessageCenterTrayHostWin>::get(); |
+} |
+ |
+MessageCenterTrayHostWin::MessageCenterTrayHostWin() |
+ : status_icon_(NULL), |
+ message_center_visible_(false) { |
+ message_center_tray_ = new MessageCenterTray(this); |
+} |
+ |
+MessageCenterTrayHostWin::~MessageCenterTrayHostWin() { |
+ if (status_icon_ != NULL) { |
+ status_icon_->RemoveObserver(this); |
+ StatusTray * status_tray = g_browser_process->status_tray(); |
+ status_tray->RemoveStatusIcon(status_icon_); |
+ status_icon_ = NULL; |
+ } |
+} |
+ |
+message_center::MessageCenter* MessageCenterTrayHostWin::message_center() { |
+ return message_center_tray_->message_center(); |
+} |
+ |
+void MessageCenterTrayHostWin::OnMessageCenterTrayChanged() { |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ bool has_notifications = message_center()->NotificationCount() > 0; |
+ StatusTray* status_tray = g_browser_process->status_tray(); |
+ if (has_notifications) { |
+ if (status_icon_ == NULL) { |
+ status_icon_ = status_tray->CreateStatusIcon(); |
+ status_icon_->AddObserver(this); |
+ } |
+ // TODO(dewittj): Get some icons. |
+ gfx::ImageSkia* icon = |
+ rb.GetImageSkiaNamed(IDR_ALLOWED_NOTIFICATION); |
+ if (message_center()->UnreadNotificationCount() > 0) { |
+ status_icon_->SetImage(*icon); |
+ } else { |
+ status_icon_->SetImage( |
+ gfx::ImageSkiaOperations::CreateTransparentImage(*icon, .5)); |
+ } |
+ } else if (status_icon_ != NULL) { |
+ status_tray->RemoveStatusIcon(status_icon_); |
+ status_icon_ = NULL; |
+ } |
+} |
+ |
+string16 MessageCenterTrayHostWin::GetAccessibleNameForBubble() { |
+ // TODO(dewittj): Get a proper string resource. |
+ return ASCIIToUTF16("Windows Notification Center"); |
+} |
+ |
+void MessageCenterTrayHostWin::OnShowMessageCenterBubble() { |
+ message_center_visible_ = true; |
+} |
+ |
+void MessageCenterTrayHostWin::OnHideMessageCenterBubble() { |
+ message_center_visible_ = false; |
+} |
+ |
+gfx::Rect MessageCenterTrayHostWin::GetAnchorRect( |
+ views::Widget* anchor_widget, |
+ views::TrayBubbleView::AnchorType anchor_type, |
+ views::TrayBubbleView::AnchorAlignment anchor_alignment) { |
+ // |message_center_visible_| is set before the bubble is actually rendered, |
+ // so the flag can be used to determine which anchor to use. |
+ if (message_center_visible_) |
+ return message_center_anchor_rect_; |
+ return GetCornerAnchorRect(); |
+} |
+ |
+bool MessageCenterTrayHostWin::CanShowPopups() { |
+ // TODO(dewittj): This will eventually depend on whether quiet mode is active. |
+ return true; |
+} |
+ |
+void MessageCenterTrayHostWin::OnStatusIconClicked() { |
+ UpdateAnchorRect(); |
+ message_center_tray_->ToggleMessageCenterBubble(); |
+} |
+ |
+void MessageCenterTrayHostWin::UpdateAnchorRect() { |
+ message_center_anchor_rect_ = GetMouseAnchorRect(); |
+} |
+ |
+views::TrayBubbleView::AnchorAlignment |
+MessageCenterTrayHostWin::GetAnchorAlignment() { |
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen(); |
+ // TODO(dewittj): It's possible GetPrimaryDisplay is wrong. |
+ gfx::Rect screen_bounds = screen->GetPrimaryDisplay().bounds(); |
+ gfx::Rect work_area = screen->GetPrimaryDisplay().work_area(); |
+ |
+ if (work_area.height() < screen_bounds.height()) |
+ return views::TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM; |
+ if (work_area.x() > screen_bounds.x()) |
+ return views::TrayBubbleView::ANCHOR_ALIGNMENT_LEFT; |
+ return views::TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT; |
+} |
+ |
+void MessageCenterTrayHostWin::UpdateInitParams( |
+ views::TrayBubbleView::InitParams* init_params) { |
+ init_params->anchor_type = views::TrayBubbleView::ANCHOR_TYPE_TRAY; |
+ init_params->arrow_alignment = views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR; |
+ // TODO(dewittj): Show big shadow without blocking clicks. |
+ init_params->shadow = views::BubbleBorder::NO_SHADOW; |
+} |
+ |
+gfx::NativeView MessageCenterTrayHostWin::GetBubbleWindowContainer() { |
+ return NULL; |
+} |
+ |
+} // namespace ui |