- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / status_icons / status_tray_win.cc
1 // Copyright (c) 2012 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_tray_win.h"
6
7 #include <commctrl.h>
8
9 #include "base/win/wrapped_window_proc.h"
10 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
11 #include "chrome/common/chrome_constants.h"
12 #include "ui/gfx/screen.h"
13 #include "ui/gfx/win/hwnd_util.h"
14 #include "win8/util/win8_util.h"
15
16 static const UINT kStatusIconMessage = WM_APP + 1;
17
18 namespace {
19 // |kBaseIconId| is 2 to avoid conflicts with plugins that hard-code id 1.
20 const UINT kBaseIconId = 2;
21
22 UINT ReservedIconId(StatusTray::StatusIconType type) {
23   return kBaseIconId + static_cast<UINT>(type);
24 }
25 }  // namespace
26
27 StatusTrayWin::StatusTrayWin()
28     : next_icon_id_(1),
29       atom_(0),
30       instance_(NULL),
31       window_(NULL) {
32   // Register our window class
33   WNDCLASSEX window_class;
34   base::win::InitializeWindowClass(
35       chrome::kStatusTrayWindowClass,
36       &base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>,
37       0, 0, 0, NULL, NULL, NULL, NULL, NULL,
38       &window_class);
39   instance_ = window_class.hInstance;
40   atom_ = RegisterClassEx(&window_class);
41   CHECK(atom_);
42
43   // If the taskbar is re-created after we start up, we have to rebuild all of
44   // our icons.
45   taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
46
47   // Create an offscreen window for handling messages for the status icons. We
48   // create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because
49   // only top-level windows such as popups can receive broadcast messages like
50   // "TaskbarCreated".
51   window_ = CreateWindow(MAKEINTATOM(atom_),
52                          0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0);
53   gfx::CheckWindowCreated(window_);
54   gfx::SetWindowUserData(window_, this);
55 }
56
57 LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
58                                               UINT message,
59                                               WPARAM wparam,
60                                               LPARAM lparam) {
61   StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
62       GetWindowLongPtr(hwnd, GWLP_USERDATA));
63   if (msg_wnd)
64     return msg_wnd->WndProc(hwnd, message, wparam, lparam);
65   else
66     return ::DefWindowProc(hwnd, message, wparam, lparam);
67 }
68
69 LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
70                                         UINT message,
71                                         WPARAM wparam,
72                                         LPARAM lparam) {
73   if (message == taskbar_created_message_) {
74     // We need to reset all of our icons because the taskbar went away.
75     for (StatusIcons::const_iterator i(status_icons().begin());
76          i != status_icons().end(); ++i) {
77       StatusIconWin* win_icon = static_cast<StatusIconWin*>(*i);
78       win_icon->ResetIcon();
79     }
80     return TRUE;
81   } else if (message == kStatusIconMessage) {
82     StatusIconWin* win_icon = NULL;
83
84     // Find the selected status icon.
85     for (StatusIcons::const_iterator i(status_icons().begin());
86          i != status_icons().end();
87          ++i) {
88       StatusIconWin* current_win_icon = static_cast<StatusIconWin*>(*i);
89       if (current_win_icon->icon_id() == wparam) {
90         win_icon = current_win_icon;
91         break;
92       }
93     }
94
95     // It is possible for this procedure to be called with an obsolete icon
96     // id.  In that case we should just return early before handling any
97     // actions.
98     if (!win_icon)
99       return TRUE;
100
101     switch (lparam) {
102       case TB_INDETERMINATE:
103         win_icon->HandleBalloonClickEvent();
104         return TRUE;
105
106       case WM_LBUTTONDOWN:
107       case WM_RBUTTONDOWN:
108       case WM_CONTEXTMENU:
109         // Walk our icons, find which one was clicked on, and invoke its
110         // HandleClickEvent() method.
111         gfx::Point cursor_pos(
112             gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
113         win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN);
114         return TRUE;
115     }
116   }
117   return ::DefWindowProc(hwnd, message, wparam, lparam);
118 }
119
120 StatusTrayWin::~StatusTrayWin() {
121   if (window_)
122     DestroyWindow(window_);
123
124   if (atom_)
125     UnregisterClass(MAKEINTATOM(atom_), instance_);
126 }
127
128 StatusIcon* StatusTrayWin::CreatePlatformStatusIcon(
129     StatusTray::StatusIconType type,
130     const gfx::ImageSkia& image,
131     const string16& tool_tip) {
132   UINT next_icon_id;
133   if (type == StatusTray::OTHER_ICON)
134     next_icon_id = NextIconId();
135   else
136     next_icon_id = ReservedIconId(type);
137
138   StatusIcon* icon = NULL;
139   if (win8::IsSingleWindowMetroMode())
140     icon = new StatusIconMetro(next_icon_id);
141   else
142     icon = new StatusIconWin(next_icon_id, window_, kStatusIconMessage);
143
144   icon->SetImage(image);
145   icon->SetToolTip(tool_tip);
146   return icon;
147 }
148
149 UINT StatusTrayWin::NextIconId() {
150   UINT icon_id = next_icon_id_++;
151   return kBaseIconId + static_cast<UINT>(NAMED_STATUS_ICON_COUNT) + icon_id;
152 }
153
154 StatusTray* StatusTray::Create() {
155   return new StatusTrayWin();
156 }