OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/status_icons/status_tray_win.h" | 5 #include "chrome/browser/ui/views/status_icons/status_tray_win.h" |
6 | 6 |
7 #include <commctrl.h> | 7 #include <commctrl.h> |
8 | 8 |
9 #include "base/bind.h" | |
10 #include "base/threading/thread.h" | |
9 #include "base/win/wrapped_window_proc.h" | 11 #include "base/win/wrapped_window_proc.h" |
10 #include "chrome/browser/ui/views/status_icons/status_icon_win.h" | 12 #include "chrome/browser/ui/views/status_icons/status_icon_win.h" |
13 #include "chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h" | |
11 #include "chrome/common/chrome_constants.h" | 14 #include "chrome/common/chrome_constants.h" |
12 #include "ui/gfx/screen.h" | 15 #include "ui/gfx/screen.h" |
13 #include "ui/gfx/win/hwnd_util.h" | 16 #include "ui/gfx/win/hwnd_util.h" |
14 #include "win8/util/win8_util.h" | 17 #include "win8/util/win8_util.h" |
15 | 18 |
16 static const UINT kStatusIconMessage = WM_APP + 1; | 19 static const UINT kStatusIconMessage = WM_APP + 1; |
17 | 20 |
18 namespace { | 21 namespace { |
19 // |kBaseIconId| is 2 to avoid conflicts with plugins that hard-code id 1. | 22 // |kBaseIconId| is 2 to avoid conflicts with plugins that hard-code id 1. |
20 const UINT kBaseIconId = 2; | 23 const UINT kBaseIconId = 2; |
21 | 24 |
22 UINT ReservedIconId(StatusTray::StatusIconType type) { | 25 UINT ReservedIconId(StatusTray::StatusIconType type) { |
23 return kBaseIconId + static_cast<UINT>(type); | 26 return kBaseIconId + static_cast<UINT>(type); |
24 } | 27 } |
25 } // namespace | 28 } // namespace |
26 | 29 |
30 class StatusTrayStateChangerProxyImpl : public StatusTrayStateChangerProxy { | |
31 public: | |
32 StatusTrayStateChangerProxyImpl() | |
33 : pending_requests_(0), | |
34 worker_thread_("StatusIconCOMWorkerThread"), | |
35 weak_factory_(this) { | |
36 worker_thread_.init_com_with_mta(false); | |
37 } | |
38 | |
39 virtual void EnqueueChange(UINT icon_id, HWND window) { | |
40 if (pending_requests_ == 0) { | |
41 worker_thread_.Start(); | |
42 } | |
43 | |
44 ++pending_requests_; | |
45 worker_thread_.message_loop_proxy()->PostTaskAndReply( | |
46 FROM_HERE, | |
47 base::Bind( | |
48 &StatusTrayStateChangerProxyImpl::EnqueueChangeOnWorkerThread, | |
49 icon_id, | |
50 window), | |
51 base::Bind(&StatusTrayStateChangerProxyImpl::ChangeDone, | |
52 weak_factory_.GetWeakPtr())); | |
53 } | |
54 | |
55 private: | |
56 // Must be called only on |worker_thread_|, to ensure the correct COM | |
57 // apartment. | |
58 static void EnqueueChangeOnWorkerThread(UINT icon_id, HWND window) { | |
59 // It appears that IUnknowns are coincidentally compatible with | |
cpu_(ooo_6.6-7.5)
2014/04/04 18:04:16
please add a CHECK() to make sure you are in the c
dewittj
2014/04/04 21:05:51
How can you do that in a static method? I can't f
| |
60 // scoped_refptr. Normally I wouldn't depend on that but it seems that | |
61 // base::win::IUnknownImpl itself depends on that coincidence so it's | |
62 // already being assumed elsewhere. | |
63 scoped_refptr<StatusTrayStateChangerWin> status_tray_state_changer( | |
64 new StatusTrayStateChangerWin(icon_id, window)); | |
65 status_tray_state_changer->EnsureTrayIconVisible(); | |
66 } | |
67 | |
68 // Called on UI thread. | |
69 void ChangeDone() { | |
70 DCHECK_GT(pending_requests_, 0); | |
71 | |
72 if (--pending_requests_ == 0) { | |
73 worker_thread_.Stop(); | |
cpu_(ooo_6.6-7.5)
2014/04/04 18:04:16
remind me, does Stop() kill the actual native thre
dewittj
2014/04/04 21:05:51
Stop() calls QuitWhenIdle on the worker thread, an
| |
74 } | |
75 } | |
76 | |
77 private: | |
78 int pending_requests_; | |
79 | |
cpu_(ooo_6.6-7.5)
2014/04/04 18:04:16
remove the spaces 79, 81 unless this is a common s
dewittj
2014/04/04 21:05:51
Done.
| |
80 base::Thread worker_thread_; | |
81 | |
82 base::WeakPtrFactory<StatusTrayStateChangerProxyImpl> weak_factory_; | |
83 | |
84 DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerProxyImpl); | |
85 }; | |
86 | |
27 StatusTrayWin::StatusTrayWin() | 87 StatusTrayWin::StatusTrayWin() |
28 : next_icon_id_(1), | 88 : next_icon_id_(1), |
29 atom_(0), | 89 atom_(0), |
30 instance_(NULL), | 90 instance_(NULL), |
31 window_(NULL) { | 91 window_(NULL) { |
32 // Register our window class | 92 // Register our window class |
33 WNDCLASSEX window_class; | 93 WNDCLASSEX window_class; |
34 base::win::InitializeWindowClass( | 94 base::win::InitializeWindowClass( |
35 chrome::kStatusTrayWindowClass, | 95 chrome::kStatusTrayWindowClass, |
36 &base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>, | 96 &base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>, |
(...skipping 10 matching lines...) Expand all Loading... | |
47 // Create an offscreen window for handling messages for the status icons. We | 107 // 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 | 108 // 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 | 109 // only top-level windows such as popups can receive broadcast messages like |
50 // "TaskbarCreated". | 110 // "TaskbarCreated". |
51 window_ = CreateWindow(MAKEINTATOM(atom_), | 111 window_ = CreateWindow(MAKEINTATOM(atom_), |
52 0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0); | 112 0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0); |
53 gfx::CheckWindowCreated(window_); | 113 gfx::CheckWindowCreated(window_); |
54 gfx::SetWindowUserData(window_, this); | 114 gfx::SetWindowUserData(window_, this); |
55 } | 115 } |
56 | 116 |
117 StatusTrayWin::~StatusTrayWin() { | |
118 if (window_) | |
119 DestroyWindow(window_); | |
120 | |
121 if (atom_) | |
122 UnregisterClass(MAKEINTATOM(atom_), instance_); | |
123 } | |
124 | |
125 void StatusTrayWin::UpdateIconVisibilityInBackground( | |
126 StatusIconWin* status_icon) { | |
127 if (!state_changer_proxy_.get()) { | |
128 state_changer_proxy_.reset(new StatusTrayStateChangerProxyImpl); | |
129 } | |
130 | |
131 state_changer_proxy_->EnqueueChange(status_icon->icon_id(), | |
132 status_icon->window()); | |
133 } | |
134 | |
57 LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd, | 135 LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd, |
58 UINT message, | 136 UINT message, |
59 WPARAM wparam, | 137 WPARAM wparam, |
60 LPARAM lparam) { | 138 LPARAM lparam) { |
61 StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>( | 139 StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>( |
62 GetWindowLongPtr(hwnd, GWLP_USERDATA)); | 140 GetWindowLongPtr(hwnd, GWLP_USERDATA)); |
63 if (msg_wnd) | 141 if (msg_wnd) |
64 return msg_wnd->WndProc(hwnd, message, wparam, lparam); | 142 return msg_wnd->WndProc(hwnd, message, wparam, lparam); |
65 else | 143 else |
66 return ::DefWindowProc(hwnd, message, wparam, lparam); | 144 return ::DefWindowProc(hwnd, message, wparam, lparam); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 // HandleClickEvent() method. | 188 // HandleClickEvent() method. |
111 gfx::Point cursor_pos( | 189 gfx::Point cursor_pos( |
112 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); | 190 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); |
113 win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN); | 191 win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN); |
114 return TRUE; | 192 return TRUE; |
115 } | 193 } |
116 } | 194 } |
117 return ::DefWindowProc(hwnd, message, wparam, lparam); | 195 return ::DefWindowProc(hwnd, message, wparam, lparam); |
118 } | 196 } |
119 | 197 |
120 StatusTrayWin::~StatusTrayWin() { | |
121 if (window_) | |
122 DestroyWindow(window_); | |
123 | |
124 if (atom_) | |
125 UnregisterClass(MAKEINTATOM(atom_), instance_); | |
126 } | |
127 | |
128 StatusIcon* StatusTrayWin::CreatePlatformStatusIcon( | 198 StatusIcon* StatusTrayWin::CreatePlatformStatusIcon( |
129 StatusTray::StatusIconType type, | 199 StatusTray::StatusIconType type, |
130 const gfx::ImageSkia& image, | 200 const gfx::ImageSkia& image, |
131 const base::string16& tool_tip) { | 201 const base::string16& tool_tip) { |
132 UINT next_icon_id; | 202 UINT next_icon_id; |
133 if (type == StatusTray::OTHER_ICON) | 203 if (type == StatusTray::OTHER_ICON) |
134 next_icon_id = NextIconId(); | 204 next_icon_id = NextIconId(); |
135 else | 205 else |
136 next_icon_id = ReservedIconId(type); | 206 next_icon_id = ReservedIconId(type); |
137 | 207 |
138 StatusIcon* icon = NULL; | 208 StatusIcon* icon = NULL; |
139 if (win8::IsSingleWindowMetroMode()) | 209 if (win8::IsSingleWindowMetroMode()) |
140 icon = new StatusIconMetro(next_icon_id); | 210 icon = new StatusIconMetro(next_icon_id); |
141 else | 211 else |
142 icon = new StatusIconWin(next_icon_id, window_, kStatusIconMessage); | 212 icon = new StatusIconWin(this, next_icon_id, window_, kStatusIconMessage); |
143 | 213 |
144 icon->SetImage(image); | 214 icon->SetImage(image); |
145 icon->SetToolTip(tool_tip); | 215 icon->SetToolTip(tool_tip); |
146 return icon; | 216 return icon; |
147 } | 217 } |
148 | 218 |
149 UINT StatusTrayWin::NextIconId() { | 219 UINT StatusTrayWin::NextIconId() { |
150 UINT icon_id = next_icon_id_++; | 220 UINT icon_id = next_icon_id_++; |
151 return kBaseIconId + static_cast<UINT>(NAMED_STATUS_ICON_COUNT) + icon_id; | 221 return kBaseIconId + static_cast<UINT>(NAMED_STATUS_ICON_COUNT) + icon_id; |
152 } | 222 } |
153 | 223 |
224 void StatusTrayWin::SetStatusTrayStateChangerProxyForTest( | |
225 scoped_ptr<StatusTrayStateChangerProxy> proxy) { | |
226 state_changer_proxy_ = proxy.Pass(); | |
227 } | |
228 | |
154 StatusTray* StatusTray::Create() { | 229 StatusTray* StatusTray::Create() { |
155 return new StatusTrayWin(); | 230 return new StatusTrayWin(); |
156 } | 231 } |
OLD | NEW |