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

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

Issue 10381115: [Chromoting] The Windows IT2Me host gets any new text items it finds on the clipboard. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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
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"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 68
69 void SetData(UINT uFormat, HANDLE hMem) { 69 void SetData(UINT uFormat, HANDLE hMem) {
70 if (!opened_) { 70 if (!opened_) {
71 NOTREACHED(); 71 NOTREACHED();
72 return; 72 return;
73 } 73 }
74 // The caller must not close the handle that ::SetClipboardData returns. 74 // The caller must not close the handle that ::SetClipboardData returns.
75 ::SetClipboardData(uFormat, hMem); 75 ::SetClipboardData(uFormat, hMem);
76 } 76 }
77 77
78 // The caller must not free the handle. The caller should lock the handle,
79 // copy the clipboard data, and unlock the handle. All this must be done
80 // before this ScopedClipboard is destroyed.
81 HANDLE GetData(UINT uFormat) {
dcheng 2012/05/11 20:28:31 u_format or just format.
alexeypa (please no reviews) 2012/05/11 20:42:37 |uFormat| -> |format|
simonmorris 2012/05/11 22:12:58 Done.
simonmorris 2012/05/11 22:12:58 Done.
82 if (!opened_) {
83 NOTREACHED();
84 return NULL;
85 }
86 return ::GetClipboardData(uFormat);
87 }
88
78 private: 89 private:
79 bool opened_; 90 bool opened_;
80 }; 91 };
81 92
93 // A scoper class that wraps a lock on a global memory object.
94 template <typename T>
95 class ScopedGlobalLock {
dcheng 2012/05/11 20:28:31 Can you use ScopedHGlobalfrom base/win?
simonmorris 2012/05/11 22:12:58 Done.
96 public:
97 ScopedGlobalLock(HGLOBAL hGlobalMem) : hGlobalMem_(hGlobalMem) {
alexeypa (please no reviews) 2012/05/11 20:42:37 explicit
alexeypa (please no reviews) 2012/05/11 20:42:37 hGlobalMem -> global_mem. Same thing for the data
simonmorris 2012/05/11 22:12:58 Removed code.
simonmorris 2012/05/11 22:12:58 Removed code.
98 pointer_ = ::GlobalLock(hGlobalMem_);
alexeypa (please no reviews) 2012/05/11 20:42:37 Validate that the handle is valid. The check shoul
simonmorris 2012/05/11 22:12:58 Removed code.
99 }
100
101 ~ScopedGlobalLock() {
102 if (pointer_) {
103 ::GlobalUnlock(hGlobalMem_);
104 }
105 }
106
107 T GetPointer() {
alexeypa (please no reviews) 2012/05/11 20:42:37 This is the only place where T is needed. WDYT abo
simonmorris 2012/05/11 22:12:58 Removed code.
108 return reinterpret_cast<T>(pointer_);
109 }
110
111 private:
112 HGLOBAL hGlobalMem_;
alexeypa (please no reviews) 2012/05/11 20:42:37 Make it non-copyable.
simonmorris 2012/05/11 22:12:58 Removed code.
113 LPVOID pointer_;
114 };
115
116 typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND);
117 typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND);
118
82 } // namespace 119 } // namespace
83 120
84 namespace remoting { 121 namespace remoting {
85 122
86 class ClipboardWin : public Clipboard { 123 class ClipboardWin : public Clipboard {
87 public: 124 public:
88 ClipboardWin(); 125 ClipboardWin();
89 126
90 virtual void Start() OVERRIDE; 127 virtual void Start() OVERRIDE;
91 virtual void InjectClipboardEvent( 128 virtual void InjectClipboardEvent(
92 const protocol::ClipboardEvent& event) OVERRIDE; 129 const protocol::ClipboardEvent& event) OVERRIDE;
93 virtual void Stop() OVERRIDE; 130 virtual void Stop() OVERRIDE;
94 131
95 private: 132 private:
96 static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam, 133 static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam,
97 LPARAM lParam); 134 LPARAM lParam);
98 135
99 static bool RegisterWindowClass(); 136 static bool RegisterWindowClass();
100 137
138 void OnClipboardUpdate();
alexeypa (please no reviews) 2012/05/11 20:42:37 nit: I tend to put static members last. I'm not su
simonmorris 2012/05/11 22:12:58 Done.
139
101 HWND hwnd_; 140 HWND hwnd_;
102 141
103 DISALLOW_COPY_AND_ASSIGN(ClipboardWin); 142 DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
104 }; 143 };
105 144
106 ClipboardWin::ClipboardWin() : hwnd_(NULL) { 145 ClipboardWin::ClipboardWin() : hwnd_(NULL) {
107 } 146 }
108 147
109 void ClipboardWin::Start() { 148 void ClipboardWin::Start() {
110 if (!RegisterWindowClass()) { 149 if (!RegisterWindowClass()) {
111 LOG(FATAL) << "Couldn't register clipboard window class."; 150 LOG(FATAL) << "Couldn't register clipboard window class.";
112 return; 151 return;
113 } 152 }
114 hwnd_ = ::CreateWindow(kWindowClassName, 153 hwnd_ = ::CreateWindow(kWindowClassName,
115 kWindowName, 154 kWindowName,
116 0, 0, 0, 0, 0, 155 0, 0, 0, 0, 0,
117 HWND_MESSAGE, 156 HWND_MESSAGE,
118 NULL, 157 NULL,
119 base::GetModuleFromAddress(&WndProc), 158 base::GetModuleFromAddress(&WndProc),
120 this); 159 this);
121 if (!hwnd_) { 160 if (!hwnd_) {
122 LOG(FATAL) << "Couldn't create clipboard window."; 161 LOG(FATAL) << "Couldn't create clipboard window.";
123 return; 162 return;
124 } 163 }
164
165 AddClipboardFormatListenerFn* add =
166 reinterpret_cast<AddClipboardFormatListenerFn*>(
167 ::GetProcAddress(::GetModuleHandle(L"user32.dll"),
alexeypa (please no reviews) 2012/05/11 20:42:37 GetModuleHandle will increment the library referen
simonmorris 2012/05/11 22:12:58 <http://msdn.microsoft.com/en-us/library/windows/d
alexeypa (please no reviews) 2012/05/11 23:49:17 Oops. Yes, indeed. It is actually GetModuleHandleE
168 "AddClipboardFormatListener"));
169 if (add) {
170 if (!(*add)(hwnd_)) {
171 LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError();
172 }
173 } else {
174 LOG(WARNING) << "AddClipboardFormatListener() couldn't be loaded.";
alexeypa (please no reviews) 2012/05/11 20:42:37 This will pollute logs. We should complain in the
simonmorris 2012/05/11 22:12:58 Done (assuming you meant "greater than Vista".)
alexeypa (please no reviews) 2012/05/11 23:49:17 Yes, I meant that.
simonmorris 2012/05/12 00:16:56 I don't agree. It means something went surprisingl
alexeypa (please no reviews) 2012/05/15 15:34:59 Yes, I agree with this part. I was concerned abou
175 }
125 } 176 }
126 177
127 void ClipboardWin::Stop() { 178 void ClipboardWin::Stop() {
128 if (hwnd_) { 179 if (hwnd_) {
180 RemoveClipboardFormatListenerFn* remove =
181 reinterpret_cast<RemoveClipboardFormatListenerFn*>(
182 ::GetProcAddress(::GetModuleHandle(L"user32.dll"),
183 "RemoveClipboardFormatListener"));
184 if (remove) {
185 (*remove)(hwnd_);
alexeypa (please no reviews) 2012/05/11 20:42:37 This should be called only if the Add function was
simonmorris 2012/05/11 22:12:58 Done.
186 }
129 ::DestroyWindow(hwnd_); 187 ::DestroyWindow(hwnd_);
130 hwnd_ = NULL; 188 hwnd_ = NULL;
131 } 189 }
132 } 190 }
133 191
134 void ClipboardWin::InjectClipboardEvent( 192 void ClipboardWin::InjectClipboardEvent(
135 const protocol::ClipboardEvent& event) { 193 const protocol::ClipboardEvent& event) {
136 if (!hwnd_) { 194 if (!hwnd_) {
137 return; 195 return;
138 } 196 }
(...skipping 22 matching lines...) Expand all
161 reinterpret_cast<LPWSTR>(::GlobalLock(text_global)); 219 reinterpret_cast<LPWSTR>(::GlobalLock(text_global));
162 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR)); 220 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR));
163 text_global_locked[text.size()] = (WCHAR)0; 221 text_global_locked[text.size()] = (WCHAR)0;
164 ::GlobalUnlock(text_global); 222 ::GlobalUnlock(text_global);
165 223
166 clipboard.SetData(CF_UNICODETEXT, text_global); 224 clipboard.SetData(CF_UNICODETEXT, text_global);
167 } 225 }
168 226
169 LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam, 227 LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam,
170 LPARAM lParam) { 228 LPARAM lParam) {
229 if (msg == WM_CREATE) {
230 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
dcheng 2012/05/11 20:28:31 avar or a_var instead of aVar.
simonmorris 2012/05/11 22:12:58 Done.
231 ::SetWindowLongPtr(hwnd,
232 GWLP_USERDATA,
233 reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
234 return 0;
235 }
236 ClipboardWin* clipboardWin =
alexeypa (please no reviews) 2012/05/11 20:42:37 |clipboard_win|, or, maybe, simply |clipboard|
simonmorris 2012/05/11 22:12:58 Done.
237 reinterpret_cast<ClipboardWin*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
238 switch (msg) {
239 case WM_CLIPBOARDUPDATE:
240 clipboardWin->OnClipboardUpdate();
241 return 0;
242 }
171 return ::DefWindowProc(hwnd, msg, wParam, lParam); 243 return ::DefWindowProc(hwnd, msg, wParam, lParam);
172 } 244 }
173 245
174 bool ClipboardWin::RegisterWindowClass() { 246 bool ClipboardWin::RegisterWindowClass() {
175 // This method is only called on the desktop thread, so it doesn't matter 247 // This method is only called on the desktop thread, so it doesn't matter
176 // that the following test is not thread-safe. 248 // that the following test is not thread-safe.
177 static bool registered = false; 249 static bool registered = false;
178 if (registered) { 250 if (registered) {
179 return true; 251 return true;
180 } 252 }
181 253
182 WNDCLASSEX window_class; 254 WNDCLASSEX window_class;
183 base::win::InitializeWindowClass( 255 base::win::InitializeWindowClass(
184 kWindowClassName, 256 kWindowClassName,
185 base::win::WrappedWindowProc<WndProc>, 257 base::win::WrappedWindowProc<WndProc>,
186 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 258 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
187 &window_class); 259 &window_class);
188 if (!::RegisterClassEx(&window_class)) { 260 if (!::RegisterClassEx(&window_class)) {
189 return false; 261 return false;
190 } 262 }
191 263
192 registered = true; 264 registered = true;
193 return true; 265 return true;
194 } 266 }
195 267
268 void ClipboardWin::OnClipboardUpdate() {
269 if (!hwnd_) {
alexeypa (please no reviews) 2012/05/11 20:42:37 Make it a DCHECK. I don't think there is a way to
simonmorris 2012/05/11 22:12:58 Done.
270 return;
271 }
272
273 if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
274 string16 text;
275 // Add a scope, so that we keep the clipboard open for as short a time as
276 // possible.
277 {
278 ScopedClipboard clipboard;
279 if (!clipboard.Init(hwnd_)) {
280 LOG(WARNING) << "Couldn't open the clipboard." << GetLastError();
281 return;
282 }
283
284 HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT);
285 if (!text_global) {
286 LOG(WARNING) << "Couldn't get data from the clipboard: "
287 << GetLastError();
288 return;
289 }
290
291 ScopedGlobalLock<LPWSTR> text_lock(text_global);
292 if (!text_lock.GetPointer()) {
293 LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError();
294 return;
295 }
296 string16 text_temp(text_lock.GetPointer());
dcheng 2012/05/11 20:28:31 You can just use assign instead of swapping.
simonmorris 2012/05/11 22:12:58 Done.
297 text.swap(text_temp);
alexeypa (please no reviews) 2012/05/11 20:42:37 I don't think text.swap buys anything here. text c
simonmorris 2012/05/11 22:12:58 Done.
298 }
299
300 protocol::ClipboardEvent event;
301 event.set_mime_type(kMimeTypeTextUtf8);
302 event.set_data(UTF16ToUTF8(text));
303
304 // TODO(simonmorris): Send the event to the client.
305 }
306 }
307
196 scoped_ptr<Clipboard> Clipboard::Create() { 308 scoped_ptr<Clipboard> Clipboard::Create() {
197 return scoped_ptr<Clipboard>(new ClipboardWin()); 309 return scoped_ptr<Clipboard>(new ClipboardWin());
198 } 310 }
199 311
200 } // namespace remoting 312 } // namespace remoting
OLDNEW
« remoting/host/chromoting_host_context.cc ('K') | « remoting/host/chromoting_host_context.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698