172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/status_icons/status_tray_win.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/wrapped_window_proc.h"
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/status_icons/status_icon_win.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/win/hwnd_util.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const UINT kStatusIconMessage = WM_APP + 1;
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochStatusTrayWin::StatusTrayWin()
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : next_icon_id_(1) {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Register our window class
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HINSTANCE hinst = GetModuleHandle(NULL);
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WNDCLASSEX wc = {0};
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  wc.cbSize = sizeof(wc);
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  wc.lpfnWndProc = base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>;
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  wc.hInstance = hinst;
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  wc.lpszClassName = chrome::kStatusTrayWindowClass;
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ATOM clazz = RegisterClassEx(&wc);
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(clazz);
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If the taskbar is re-created after we start up, we have to rebuild all of
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // our icons.
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Create an offscreen window for handling messages for the status icons. We
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // only top-level windows such as popups can receive broadcast messages like
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // "TaskbarCreated".
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_ = CreateWindow(chrome::kStatusTrayWindowClass,
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                         0, WS_POPUP, 0, 0, 0, 0, 0, 0, hinst, 0);
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ui::CheckWindowCreated(window_);
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::SetWindowUserData(window_, this);
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              UINT message,
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              WPARAM wparam,
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              LPARAM lparam) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetWindowLongPtr(hwnd, GWLP_USERDATA));
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (msg_wnd)
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return msg_wnd->WndProc(hwnd, message, wparam, lparam);
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  else
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ::DefWindowProc(hwnd, message, wparam, lparam);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        UINT message,
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        WPARAM wparam,
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        LPARAM lparam) {
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (message == taskbar_created_message_) {
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // We need to reset all of our icons because the taskbar went away.
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (StatusIconList::const_iterator iter = status_icons().begin();
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         iter != status_icons().end();
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         ++iter) {
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      win_icon->ResetIcon();
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return TRUE;
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (message == kStatusIconMessage) {
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    switch (lparam) {
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      case WM_LBUTTONDOWN:
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      case WM_RBUTTONDOWN:
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      case WM_CONTEXTMENU:
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Walk our icons, find which one was clicked on, and invoke its
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // HandleClickEvent() method.
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        for (StatusIconList::const_iterator iter = status_icons().begin();
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen             iter != status_icons().end();
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen             ++iter) {
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          if (win_icon->icon_id() == wparam) {
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            POINT p;
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            GetCursorPos(&p);
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        }
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        return TRUE;
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ::DefWindowProc(hwnd, message, wparam, lparam);
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochStatusTrayWin::~StatusTrayWin() {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (window_)
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DestroyWindow(window_);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UnregisterClass(chrome::kStatusTrayWindowClass, GetModuleHandle(NULL));
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatusIcon* StatusTrayWin::CreatePlatformStatusIcon() {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new StatusIconWin(next_icon_id_++, window_, kStatusIconMessage);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochStatusTray* StatusTray::Create() {
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new StatusTrayWin();
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
101