1 // Copyright (c) 2011 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/status_icons/status_icon_win.h"
6
7 #include "base/sys_string_conversions.h"
8 #include "third_party/skia/include/core/SkBitmap.h"
9 #include "ui/gfx/icon_util.h"
10 #include "ui/gfx/point.h"
11 #include "views/controls/menu/menu_2.h"
12
StatusIconWin(UINT id,HWND window,UINT message)13 StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message)
14 : icon_id_(id),
15 window_(window),
16 message_id_(message) {
17 NOTIFYICONDATA icon_data;
18 InitIconData(&icon_data);
19 icon_data.uFlags = NIF_MESSAGE;
20 icon_data.uCallbackMessage = message_id_;
21 BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
22 // This can happen if the explorer process isn't running when we try to
23 // create the icon for some reason (for example, at startup).
24 if (!result)
25 LOG(WARNING) << "Unable to create status tray icon.";
26 }
27
~StatusIconWin()28 StatusIconWin::~StatusIconWin() {
29 // Remove our icon.
30 NOTIFYICONDATA icon_data;
31 InitIconData(&icon_data);
32 Shell_NotifyIcon(NIM_DELETE, &icon_data);
33 }
34
SetImage(const SkBitmap & image)35 void StatusIconWin::SetImage(const SkBitmap& image) {
36 // Create the icon.
37 NOTIFYICONDATA icon_data;
38 InitIconData(&icon_data);
39 icon_data.uFlags = NIF_ICON;
40 icon_.Set(IconUtil::CreateHICONFromSkBitmap(image));
41 icon_data.hIcon = icon_.Get();
42 BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
43 if (!result)
44 LOG(WARNING) << "Error setting status tray icon image";
45 }
46
ResetIcon()47 void StatusIconWin::ResetIcon() {
48 NOTIFYICONDATA icon_data;
49 InitIconData(&icon_data);
50 // Delete any previously existing icon.
51 Shell_NotifyIcon(NIM_DELETE, &icon_data);
52 InitIconData(&icon_data);
53 icon_data.uFlags = NIF_MESSAGE;
54 icon_data.uCallbackMessage = message_id_;
55 icon_data.hIcon = icon_.Get();
56 // If we have an image, then set the NIF_ICON flag, which tells
57 // Shell_NotifyIcon() to set the image for the status icon it creates.
58 if (icon_data.hIcon)
59 icon_data.uFlags |= NIF_ICON;
60 // Re-add our icon.
61 BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
62 if (!result)
63 LOG(WARNING) << "Unable to re-create status tray icon.";
64 }
65
SetPressedImage(const SkBitmap & image)66 void StatusIconWin::SetPressedImage(const SkBitmap& image) {
67 // Ignore pressed images, since the standard on Windows is to not highlight
68 // pressed status icons.
69 }
70
SetToolTip(const string16 & tool_tip)71 void StatusIconWin::SetToolTip(const string16& tool_tip) {
72 // Create the icon.
73 NOTIFYICONDATA icon_data;
74 InitIconData(&icon_data);
75 icon_data.uFlags = NIF_TIP;
76 wcscpy_s(icon_data.szTip, tool_tip.c_str());
77 BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
78 if (!result)
79 LOG(WARNING) << "Unable to set tooltip for status tray icon";
80 }
81
DisplayBalloon(const string16 & title,const string16 & contents)82 void StatusIconWin::DisplayBalloon(const string16& title,
83 const string16& contents) {
84 NOTIFYICONDATA icon_data;
85 InitIconData(&icon_data);
86 icon_data.uFlags = NIF_INFO;
87 icon_data.dwInfoFlags = NIIF_INFO;
88 wcscpy_s(icon_data.szInfoTitle, title.c_str());
89 wcscpy_s(icon_data.szInfo, contents.c_str());
90 icon_data.uTimeout = 0;
91 BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
92 if (!result)
93 LOG(WARNING) << "Unable to create status tray balloon.";
94 }
95
UpdatePlatformContextMenu(ui::MenuModel * menu)96 void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) {
97 // If no items are passed, blow away our context menu.
98 if (!menu) {
99 context_menu_.reset();
100 return;
101 }
102
103 // Create context menu with the new contents.
104 context_menu_.reset(new views::Menu2(menu));
105 }
106
HandleClickEvent(int x,int y,bool left_mouse_click)107 void StatusIconWin::HandleClickEvent(int x, int y, bool left_mouse_click) {
108 // Pass to the observer if appropriate.
109 if (left_mouse_click && HasObservers()) {
110 DispatchClickEvent();
111 return;
112 }
113
114 // Event not sent to the observer, so display the context menu if one exists.
115 if (context_menu_.get()) {
116 // Set our window as the foreground window, so the context menu closes when
117 // we click away from it.
118 SetForegroundWindow(window_);
119 context_menu_->RunContextMenuAt(gfx::Point(x, y));
120 }
121 }
122
InitIconData(NOTIFYICONDATA * icon_data)123 void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) {
124 icon_data->cbSize = sizeof(NOTIFYICONDATA);
125 icon_data->hWnd = window_;
126 icon_data->uID = icon_id_;
127 }
128