Chromium Code Reviews| 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 { | |
|
sky
2014/04/04 21:13:25
Description?
dewittj
2014/04/04 22:35:57
Done.
| |
| 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) { | |
|
sky
2014/04/04 21:13:25
OVERRIDE
dewittj
2014/04/04 22:35:57
Done.
| |
| 40 if (pending_requests_ == 0) { | |
|
sky
2014/04/04 21:13:25
nit: no {}
dewittj
2014/04/04 22:35:57
Done.
| |
| 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 | |
| 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) { | |
|
sky
2014/04/04 21:13:25
nit: no {}
dewittj
2014/04/04 22:35:57
Done.
| |
| 73 worker_thread_.Stop(); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 private: | |
| 78 int pending_requests_; | |
| 79 | |
| 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()) { | |
|
sky
2014/04/04 21:13:25
nit: no {}
dewittj
2014/04/04 22:35:57
Done.
| |
| 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 |