Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(582)

Side by Side Diff: remoting/host/clipboard_win.cc

Issue 13142002: Moved code implementing message-only windows to a dedicated class (Windows only). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | remoting/host/local_input_monitor_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "remoting/host/clipboard.h" 5 #include "remoting/host/clipboard.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/process_util.h" 12 #include "base/process_util.h"
13 #include "base/string16.h" 13 #include "base/string16.h"
14 #include "base/threading/platform_thread.h" 14 #include "base/threading/platform_thread.h"
15 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
16 #include "base/win/scoped_hglobal.h" 16 #include "base/win/scoped_hglobal.h"
17 #include "base/win/windows_version.h" 17 #include "base/win/windows_version.h"
18 #include "base/win/wrapped_window_proc.h" 18 #include "base/win/wrapped_window_proc.h"
19 #include "remoting/base/constants.h" 19 #include "remoting/base/constants.h"
20 #include "remoting/base/util.h" 20 #include "remoting/base/util.h"
21 #include "remoting/host/win/message_window.h"
21 #include "remoting/proto/event.pb.h" 22 #include "remoting/proto/event.pb.h"
22 #include "remoting/protocol/clipboard_stub.h" 23 #include "remoting/protocol/clipboard_stub.h"
23 24
24 namespace { 25 namespace {
25 26
26 const WCHAR kWindowClassName[] = L"clipboardWindowClass";
27 const WCHAR kWindowName[] = L"clipboardWindow";
28
29 // A scoper class that opens and closes the clipboard. 27 // A scoper class that opens and closes the clipboard.
30 // This class was adapted from the ScopedClipboard class in 28 // This class was adapted from the ScopedClipboard class in
31 // ui/base/clipboard/clipboard_win.cc. 29 // ui/base/clipboard/clipboard_win.cc.
32 class ScopedClipboard { 30 class ScopedClipboard {
33 public: 31 public:
34 ScopedClipboard() : opened_(false) { 32 ScopedClipboard() : opened_(false) {
35 } 33 }
36 34
37 ~ScopedClipboard() { 35 ~ScopedClipboard() {
38 if (opened_) { 36 if (opened_) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 bool opened_; 93 bool opened_;
96 }; 94 };
97 95
98 typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND); 96 typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND);
99 typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND); 97 typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND);
100 98
101 } // namespace 99 } // namespace
102 100
103 namespace remoting { 101 namespace remoting {
104 102
105 class ClipboardWin : public Clipboard { 103 class ClipboardWin : public Clipboard,
104 public win::MessageWindow::Delegate {
106 public: 105 public:
107 ClipboardWin(); 106 ClipboardWin();
108 107
109 virtual void Start( 108 virtual void Start(
110 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; 109 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE;
111 virtual void InjectClipboardEvent( 110 virtual void InjectClipboardEvent(
112 const protocol::ClipboardEvent& event) OVERRIDE; 111 const protocol::ClipboardEvent& event) OVERRIDE;
113 virtual void Stop() OVERRIDE; 112 virtual void Stop() OVERRIDE;
114 113
115 private: 114 private:
116 void OnClipboardUpdate(); 115 void OnClipboardUpdate();
117 bool HaveClipboardListenerApi();
118 116
119 static bool RegisterWindowClass(); 117 // win::MessageWindow::Delegate interface.
120 static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam, 118 virtual bool HandleMessage(HWND hwnd,
121 LPARAM lParam); 119 UINT message,
120 WPARAM wparam,
121 LPARAM lparam,
122 LRESULT* result) OVERRIDE;
122 123
123 scoped_ptr<protocol::ClipboardStub> client_clipboard_; 124 scoped_ptr<protocol::ClipboardStub> client_clipboard_;
124 HWND hwnd_;
125 AddClipboardFormatListenerFn* add_clipboard_format_listener_; 125 AddClipboardFormatListenerFn* add_clipboard_format_listener_;
126 RemoveClipboardFormatListenerFn* remove_clipboard_format_listener_; 126 RemoveClipboardFormatListenerFn* remove_clipboard_format_listener_;
127 bool load_functions_tried_; 127
128 // Used to subscribe to WM_CLIPBOARDUPDATE messages.
129 scoped_ptr<win::MessageWindow> window_;
128 130
129 DISALLOW_COPY_AND_ASSIGN(ClipboardWin); 131 DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
130 }; 132 };
131 133
132 ClipboardWin::ClipboardWin() 134 ClipboardWin::ClipboardWin()
133 : hwnd_(NULL), 135 : add_clipboard_format_listener_(NULL),
134 add_clipboard_format_listener_(NULL), 136 remove_clipboard_format_listener_(NULL) {
135 remove_clipboard_format_listener_(NULL),
136 load_functions_tried_(false) {
137 } 137 }
138 138
139 void ClipboardWin::Start( 139 void ClipboardWin::Start(
140 scoped_ptr<protocol::ClipboardStub> client_clipboard) { 140 scoped_ptr<protocol::ClipboardStub> client_clipboard) {
141 DCHECK(!add_clipboard_format_listener_);
142 DCHECK(!remove_clipboard_format_listener_);
143 DCHECK(!window_);
144
141 client_clipboard_.swap(client_clipboard); 145 client_clipboard_.swap(client_clipboard);
142 146
143 if (!load_functions_tried_) { 147 // user32.dll is statically linked.
144 load_functions_tried_ = true; 148 HMODULE user32 = GetModuleHandle(L"user32.dll");
145 HMODULE user32_module = ::GetModuleHandle(L"user32.dll"); 149 CHECK(user32);
146 if (!user32_module) { 150
147 LOG(WARNING) << "Couldn't find user32.dll."; 151 add_clipboard_format_listener_ =
148 } else { 152 reinterpret_cast<AddClipboardFormatListenerFn*>(
149 add_clipboard_format_listener_ = 153 GetProcAddress(user32, "AddClipboardFormatListener"));
150 reinterpret_cast<AddClipboardFormatListenerFn*>( 154 if (add_clipboard_format_listener_) {
151 ::GetProcAddress(user32_module, "AddClipboardFormatListener")); 155 remove_clipboard_format_listener_ =
152 remove_clipboard_format_listener_ = 156 reinterpret_cast<RemoveClipboardFormatListenerFn*>(
153 reinterpret_cast<RemoveClipboardFormatListenerFn*>( 157 GetProcAddress(user32, "RemoveClipboardFormatListener"));
154 ::GetProcAddress(user32_module, "RemoveClipboardFormatListener")); 158 // If AddClipboardFormatListener() present, RemoveClipboardFormatListener()
155 if (!HaveClipboardListenerApi()) { 159 // should be available too.
156 LOG(WARNING) << "Couldn't load AddClipboardFormatListener or " 160 CHECK(remove_clipboard_format_listener_);
157 << "RemoveClipboardFormatListener."; 161 } else {
158 } 162 LOG(WARNING) << "AddClipboardFormatListener() is not available.";
159 }
160 } 163 }
161 164
162 if (!RegisterWindowClass()) { 165 window_.reset(new win::MessageWindow());
163 LOG(ERROR) << "Couldn't register clipboard window class."; 166 if (!window_->Create(this)) {
164 return;
165 }
166 hwnd_ = ::CreateWindow(kWindowClassName,
167 kWindowName,
168 0, 0, 0, 0, 0,
169 HWND_MESSAGE,
170 NULL,
171 base::GetModuleFromAddress(&WndProc),
172 this);
173 if (!hwnd_) {
174 LOG(ERROR) << "Couldn't create clipboard window."; 167 LOG(ERROR) << "Couldn't create clipboard window.";
168 window_.reset();
175 return; 169 return;
176 } 170 }
177 171
178 if (HaveClipboardListenerApi()) { 172 if (add_clipboard_format_listener_) {
179 if (!(*add_clipboard_format_listener_)(hwnd_)) { 173 if (!(*add_clipboard_format_listener_)(window_->hwnd())) {
180 LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError(); 174 LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError();
181 } 175 }
182 } 176 }
183 } 177 }
184 178
185 void ClipboardWin::Stop() { 179 void ClipboardWin::Stop() {
186 client_clipboard_.reset(); 180 client_clipboard_.reset();
187 181
188 if (hwnd_) { 182 if (window_ && remove_clipboard_format_listener_)
189 if (HaveClipboardListenerApi()) { 183 (*remove_clipboard_format_listener_)(window_->hwnd());
190 (*remove_clipboard_format_listener_)(hwnd_); 184
191 } 185 window_.reset();
192 ::DestroyWindow(hwnd_);
193 hwnd_ = NULL;
194 }
195 } 186 }
196 187
197 void ClipboardWin::InjectClipboardEvent( 188 void ClipboardWin::InjectClipboardEvent(
198 const protocol::ClipboardEvent& event) { 189 const protocol::ClipboardEvent& event) {
199 if (!hwnd_) 190 if (!window_)
200 return; 191 return;
201 192
202 // Currently we only handle UTF-8 text. 193 // Currently we only handle UTF-8 text.
203 if (event.mime_type().compare(kMimeTypeTextUtf8) != 0) 194 if (event.mime_type().compare(kMimeTypeTextUtf8) != 0)
204 return; 195 return;
205 if (!StringIsUtf8(event.data().c_str(), event.data().length())) { 196 if (!StringIsUtf8(event.data().c_str(), event.data().length())) {
206 LOG(ERROR) << "ClipboardEvent: data is not UTF-8 encoded."; 197 LOG(ERROR) << "ClipboardEvent: data is not UTF-8 encoded.";
207 return; 198 return;
208 } 199 }
209 200
210 string16 text = UTF8ToUTF16(ReplaceLfByCrLf(event.data())); 201 string16 text = UTF8ToUTF16(ReplaceLfByCrLf(event.data()));
211 202
212 ScopedClipboard clipboard; 203 ScopedClipboard clipboard;
213 if (!clipboard.Init(hwnd_)) { 204 if (!clipboard.Init(window_->hwnd())) {
214 LOG(WARNING) << "Couldn't open the clipboard."; 205 LOG(WARNING) << "Couldn't open the clipboard.";
215 return; 206 return;
216 } 207 }
217 208
218 clipboard.Empty(); 209 clipboard.Empty();
219 210
220 HGLOBAL text_global = 211 HGLOBAL text_global =
221 ::GlobalAlloc(GMEM_MOVEABLE, (text.size() + 1) * sizeof(WCHAR)); 212 ::GlobalAlloc(GMEM_MOVEABLE, (text.size() + 1) * sizeof(WCHAR));
222 if (!text_global) { 213 if (!text_global) {
223 LOG(WARNING) << "Couldn't allocate global memory."; 214 LOG(WARNING) << "Couldn't allocate global memory.";
224 return; 215 return;
225 } 216 }
226 217
227 LPWSTR text_global_locked = 218 LPWSTR text_global_locked =
228 reinterpret_cast<LPWSTR>(::GlobalLock(text_global)); 219 reinterpret_cast<LPWSTR>(::GlobalLock(text_global));
229 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR)); 220 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR));
230 text_global_locked[text.size()] = (WCHAR)0; 221 text_global_locked[text.size()] = (WCHAR)0;
231 ::GlobalUnlock(text_global); 222 ::GlobalUnlock(text_global);
232 223
233 clipboard.SetData(CF_UNICODETEXT, text_global); 224 clipboard.SetData(CF_UNICODETEXT, text_global);
234 } 225 }
235 226
236 void ClipboardWin::OnClipboardUpdate() { 227 void ClipboardWin::OnClipboardUpdate() {
237 DCHECK(hwnd_); 228 DCHECK(window_);
238 229
239 if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) { 230 if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
240 string16 text; 231 string16 text;
241 // Add a scope, so that we keep the clipboard open for as short a time as 232 // Add a scope, so that we keep the clipboard open for as short a time as
242 // possible. 233 // possible.
243 { 234 {
244 ScopedClipboard clipboard; 235 ScopedClipboard clipboard;
245 if (!clipboard.Init(hwnd_)) { 236 if (!clipboard.Init(window_->hwnd())) {
246 LOG(WARNING) << "Couldn't open the clipboard." << GetLastError(); 237 LOG(WARNING) << "Couldn't open the clipboard." << GetLastError();
247 return; 238 return;
248 } 239 }
249 240
250 HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT); 241 HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT);
251 if (!text_global) { 242 if (!text_global) {
252 LOG(WARNING) << "Couldn't get data from the clipboard: " 243 LOG(WARNING) << "Couldn't get data from the clipboard: "
253 << GetLastError(); 244 << GetLastError();
254 return; 245 return;
255 } 246 }
256 247
257 base::win::ScopedHGlobal<WCHAR> text_lock(text_global); 248 base::win::ScopedHGlobal<WCHAR> text_lock(text_global);
258 if (!text_lock.get()) { 249 if (!text_lock.get()) {
259 LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError(); 250 LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError();
260 return; 251 return;
261 } 252 }
262 text.assign(text_lock.get()); 253 text.assign(text_lock.get());
263 } 254 }
264 255
265 protocol::ClipboardEvent event; 256 protocol::ClipboardEvent event;
266 event.set_mime_type(kMimeTypeTextUtf8); 257 event.set_mime_type(kMimeTypeTextUtf8);
267 event.set_data(ReplaceCrLfByLf(UTF16ToUTF8(text))); 258 event.set_data(ReplaceCrLfByLf(UTF16ToUTF8(text)));
268 259
269 if (client_clipboard_.get()) { 260 if (client_clipboard_.get()) {
270 client_clipboard_->InjectClipboardEvent(event); 261 client_clipboard_->InjectClipboardEvent(event);
271 } 262 }
272 } 263 }
273 } 264 }
274 265
275 bool ClipboardWin::HaveClipboardListenerApi() { 266 bool ClipboardWin::HandleMessage(
276 return add_clipboard_format_listener_ && remove_clipboard_format_listener_; 267 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
277 } 268 if (message == WM_CLIPBOARDUPDATE) {
278 269 OnClipboardUpdate();
279 bool ClipboardWin::RegisterWindowClass() { 270 *result = 0;
280 // This method is only called on the UI thread, so it doesn't matter
281 // that the following test is not thread-safe.
282 static bool registered = false;
283 if (registered) {
284 return true; 271 return true;
285 } 272 }
286 273
287 WNDCLASSEX window_class; 274 return false;
288 base::win::InitializeWindowClass(
289 kWindowClassName,
290 base::win::WrappedWindowProc<WndProc>,
291 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
292 &window_class);
293 if (!::RegisterClassEx(&window_class)) {
294 return false;
295 }
296
297 registered = true;
298 return true;
299 }
300
301 LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wparam,
302 LPARAM lparam) {
303 if (msg == WM_CREATE) {
304 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lparam);
305 ::SetWindowLongPtr(hwnd,
306 GWLP_USERDATA,
307 reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
308 return 0;
309 }
310 ClipboardWin* clipboard =
311 reinterpret_cast<ClipboardWin*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
312 switch (msg) {
313 case WM_CLIPBOARDUPDATE:
314 clipboard->OnClipboardUpdate();
315 return 0;
316 }
317 return ::DefWindowProc(hwnd, msg, wparam, lparam);
318 } 275 }
319 276
320 scoped_ptr<Clipboard> Clipboard::Create() { 277 scoped_ptr<Clipboard> Clipboard::Create() {
321 return scoped_ptr<Clipboard>(new ClipboardWin()); 278 return scoped_ptr<Clipboard>(new ClipboardWin());
322 } 279 }
323 280
324 } // namespace remoting 281 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | remoting/host/local_input_monitor_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698