Commit 36ce377f authored by atwilson@chromium.org's avatar atwilson@chromium.org

Hook TaskbarCreated message to recreate status tray icons.

This allows Chrome to recreate its status tray icons on Windows in the case
that explorer.exe is restarted, or isn't running yet at the time that chrome
starts up.

BUG=69972
TEST=Run chrome without explorer.exe running, then start explorer.exe

Review URL: http://codereview.chromium.org/6289010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71974 0039d316-1c4b-4281-b951-d872f2087c98
parent 87b762f2
......@@ -19,7 +19,10 @@ StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message)
icon_data.uFlags = NIF_MESSAGE;
icon_data.uCallbackMessage = message_id_;
BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
DCHECK(result);
// This can happen if the explorer process isn't running when we try to
// create the icon for some reason (for example, at startup).
if (!result)
LOG(WARNING) << "Unable to create status tray icon.";
}
StatusIconWin::~StatusIconWin() {
......@@ -37,7 +40,27 @@ void StatusIconWin::SetImage(const SkBitmap& image) {
icon_.Set(IconUtil::CreateHICONFromSkBitmap(image));
icon_data.hIcon = icon_.Get();
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
DCHECK(result);
if (!result)
LOG(WARNING) << "Error setting status tray icon image";
}
void StatusIconWin::ResetIcon() {
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
// Delete any previously existing icon.
Shell_NotifyIcon(NIM_DELETE, &icon_data);
InitIconData(&icon_data);
icon_data.uFlags = NIF_MESSAGE;
icon_data.uCallbackMessage = message_id_;
icon_data.hIcon = icon_.Get();
// If we have an image, then set the NIF_ICON flag, which tells
// Shell_NotifyIcon() to set the image for the status icon it creates.
if (icon_data.hIcon)
icon_data.uFlags |= NIF_ICON;
// Re-add our icon.
BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
if (!result)
LOG(WARNING) << "Unable to re-create status tray icon.";
}
void StatusIconWin::SetPressedImage(const SkBitmap& image) {
......@@ -52,7 +75,8 @@ void StatusIconWin::SetToolTip(const string16& tool_tip) {
icon_data.uFlags = NIF_TIP;
wcscpy_s(icon_data.szTip, tool_tip.c_str());
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
DCHECK(result);
if (!result)
LOG(WARNING) << "Unable to set tooltip for status tray icon";
}
void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) {
......
......@@ -37,6 +37,9 @@ class StatusIconWin : public StatusIcon {
// otherwise displays the context menu if there is one.
void HandleClickEvent(int x, int y, bool left_button_click);
// Re-creates the status tray icon now after the taskbar has been created.
void ResetIcon();
protected:
// Overridden from StatusIcon.
virtual void UpdatePlatformContextMenu(ui::MenuModel* menu);
......
......@@ -22,9 +22,16 @@ StatusTrayWin::StatusTrayWin()
ATOM clazz = RegisterClassEx(&wc);
DCHECK(clazz);
// Create an offscreen window for handling messages for the status icons.
// If the taskbar is re-created after we start up, we have to rebuild all of
// our icons.
taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
// Create an offscreen window for handling messages for the status icons. We
// create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because
// only top-level windows such as popups can receive broadcast messages like
// "TaskbarCreated".
window_ = CreateWindow(chrome::kStatusTrayWindowClass,
0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0);
0, WS_POPUP, 0, 0, 0, 0, 0, 0, hinst, 0);
ui::SetWindowUserData(window_, this);
}
......@@ -34,34 +41,44 @@ LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
LPARAM lparam) {
StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
GetWindowLongPtr(hwnd, GWLP_USERDATA));
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
if (msg_wnd)
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
else
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
switch (message) {
case kStatusIconMessage:
switch (lparam) {
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
// Walk our icons, find which one was clicked on, and invoke its
// HandleClickEvent() method.
for (StatusIconList::const_iterator iter = status_icons().begin();
iter != status_icons().end();
++iter) {
StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
if (win_icon->icon_id() == wparam) {
POINT p;
GetCursorPos(&p);
win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
}
if (message == taskbar_created_message_) {
// We need to reset all of our icons because the taskbar went away.
for (StatusIconList::const_iterator iter = status_icons().begin();
iter != status_icons().end();
++iter) {
StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
win_icon->ResetIcon();
}
return TRUE;
} else if (message == kStatusIconMessage) {
switch (lparam) {
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
// Walk our icons, find which one was clicked on, and invoke its
// HandleClickEvent() method.
for (StatusIconList::const_iterator iter = status_icons().begin();
iter != status_icons().end();
++iter) {
StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
if (win_icon->icon_id() == wparam) {
POINT p;
GetCursorPos(&p);
win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
}
return TRUE;
}
break;
}
return TRUE;
}
}
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
......
......@@ -33,9 +33,14 @@ class StatusTrayWin : public StatusTray {
// The unique icon ID we will assign to the next icon.
UINT next_icon_id_;
// The window used for processing events.
HWND window_;
// The message ID of the "TaskbarCreated" message, sent to us when we need to
// reset our status icons.
UINT taskbar_created_message_;
DISALLOW_COPY_AND_ASSIGN(StatusTrayWin);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment