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

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: Reviews. 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
« no previous file with comments | « remoting/host/chromoting_host_context.cc ('k') | no next file » | 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/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
15 #include "base/win/scoped_hglobal.h"
16 #include "base/win/windows_version.h"
15 #include "base/win/wrapped_window_proc.h" 17 #include "base/win/wrapped_window_proc.h"
16 #include "remoting/base/constants.h" 18 #include "remoting/base/constants.h"
17 #include "remoting/proto/event.pb.h" 19 #include "remoting/proto/event.pb.h"
18 20
19 namespace { 21 namespace {
20 22
21 const WCHAR kWindowClassName[] = L"clipboardWindowClass"; 23 const WCHAR kWindowClassName[] = L"clipboardWindowClass";
22 const WCHAR kWindowName[] = L"clipboardWindow"; 24 const WCHAR kWindowName[] = L"clipboardWindow";
23 25
24 // A scoper class that opens and closes the clipboard. 26 // A scoper class that opens and closes the clipboard.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 70
69 void SetData(UINT uFormat, HANDLE hMem) { 71 void SetData(UINT uFormat, HANDLE hMem) {
70 if (!opened_) { 72 if (!opened_) {
71 NOTREACHED(); 73 NOTREACHED();
72 return; 74 return;
73 } 75 }
74 // The caller must not close the handle that ::SetClipboardData returns. 76 // The caller must not close the handle that ::SetClipboardData returns.
75 ::SetClipboardData(uFormat, hMem); 77 ::SetClipboardData(uFormat, hMem);
76 } 78 }
77 79
80 // The caller must not free the handle. The caller should lock the handle,
81 // copy the clipboard data, and unlock the handle. All this must be done
82 // before this ScopedClipboard is destroyed.
83 HANDLE GetData(UINT format) {
84 if (!opened_) {
85 NOTREACHED();
86 return NULL;
87 }
88 return ::GetClipboardData(format);
89 }
90
78 private: 91 private:
79 bool opened_; 92 bool opened_;
80 }; 93 };
81 94
95 typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND);
96 typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND);
97
82 } // namespace 98 } // namespace
83 99
84 namespace remoting { 100 namespace remoting {
85 101
86 class ClipboardWin : public Clipboard { 102 class ClipboardWin : public Clipboard {
87 public: 103 public:
88 ClipboardWin(); 104 ClipboardWin();
89 105
90 virtual void Start() OVERRIDE; 106 virtual void Start() OVERRIDE;
91 virtual void InjectClipboardEvent( 107 virtual void InjectClipboardEvent(
92 const protocol::ClipboardEvent& event) OVERRIDE; 108 const protocol::ClipboardEvent& event) OVERRIDE;
93 virtual void Stop() OVERRIDE; 109 virtual void Stop() OVERRIDE;
94 110
95 private: 111 private:
112 void OnClipboardUpdate();
113
114 static bool RegisterWindowClass();
96 static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam, 115 static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam,
97 LPARAM lParam); 116 LPARAM lParam);
98 117
99 static bool RegisterWindowClass();
100
101 HWND hwnd_; 118 HWND hwnd_;
119 AddClipboardFormatListenerFn* add_clipboard_format_listener_;
120 RemoveClipboardFormatListenerFn* remove_clipboard_format_listener_;
121 bool load_functions_tried_;
102 122
103 DISALLOW_COPY_AND_ASSIGN(ClipboardWin); 123 DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
104 }; 124 };
105 125
106 ClipboardWin::ClipboardWin() : hwnd_(NULL) { 126 ClipboardWin::ClipboardWin()
127 : hwnd_(NULL),
128 add_clipboard_format_listener_(NULL),
129 remove_clipboard_format_listener_(NULL),
130 load_functions_tried_(false) {
107 } 131 }
108 132
109 void ClipboardWin::Start() { 133 void ClipboardWin::Start() {
134 if (!load_functions_tried_) {
135 load_functions_tried_ = true;
136 HMODULE user32_module = ::GetModuleHandle(L"user32.dll");
alexeypa (please no reviews) 2012/05/11 23:49:17 nit: Presubmit check used to frown on L"" literals
alexeypa (please no reviews) 2012/05/11 23:49:17 nit: I think it make sense to check if GetModuleHa
simonmorris 2012/05/12 00:16:56 Presubmit doesn't complain, and this seems to be t
simonmorris 2012/05/12 00:16:56 Done.
137 add_clipboard_format_listener_ =
138 reinterpret_cast<AddClipboardFormatListenerFn*>(
139 ::GetProcAddress(user32_module, "AddClipboardFormatListener"));
140 remove_clipboard_format_listener_ =
141 reinterpret_cast<RemoveClipboardFormatListenerFn*>(
142 ::GetProcAddress(user32_module, "RemoveClipboardFormatListener"));
143 // We don't expect to load these functions for OS versions before Vista.
144 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
145 if (!add_clipboard_format_listener_) {
146 LOG(WARNING) << "Couldn't load AddClipboardFormatListener.";
147 }
148 if (!remove_clipboard_format_listener_) {
alexeypa (please no reviews) 2012/05/11 23:49:17 nit: It is highly unlikely, but it is better to re
simonmorris 2012/05/12 00:16:56 Done.
149 LOG(WARNING) << "Couldn't load RemoveClipboardFormatListener.";
150 }
151 }
152 }
153
110 if (!RegisterWindowClass()) { 154 if (!RegisterWindowClass()) {
111 LOG(FATAL) << "Couldn't register clipboard window class."; 155 LOG(FATAL) << "Couldn't register clipboard window class.";
112 return; 156 return;
113 } 157 }
114 hwnd_ = ::CreateWindow(kWindowClassName, 158 hwnd_ = ::CreateWindow(kWindowClassName,
115 kWindowName, 159 kWindowName,
116 0, 0, 0, 0, 0, 160 0, 0, 0, 0, 0,
117 HWND_MESSAGE, 161 HWND_MESSAGE,
118 NULL, 162 NULL,
119 base::GetModuleFromAddress(&WndProc), 163 base::GetModuleFromAddress(&WndProc),
120 this); 164 this);
121 if (!hwnd_) { 165 if (!hwnd_) {
122 LOG(FATAL) << "Couldn't create clipboard window."; 166 LOG(FATAL) << "Couldn't create clipboard window.";
123 return; 167 return;
124 } 168 }
169
170 if (add_clipboard_format_listener_) {
171 if (!(*add_clipboard_format_listener_)(hwnd_)) {
172 LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError();
173 }
174 }
125 } 175 }
126 176
127 void ClipboardWin::Stop() { 177 void ClipboardWin::Stop() {
128 if (hwnd_) { 178 if (hwnd_) {
179 if (add_clipboard_format_listener_ && remove_clipboard_format_listener_) {
alexeypa (please no reviews) 2012/05/11 23:49:17 nit: This check will be simpler if you make sure t
simonmorris 2012/05/12 00:16:56 Done.
180 (*remove_clipboard_format_listener_)(hwnd_);
181 }
129 ::DestroyWindow(hwnd_); 182 ::DestroyWindow(hwnd_);
130 hwnd_ = NULL; 183 hwnd_ = NULL;
131 } 184 }
132 } 185 }
133 186
134 void ClipboardWin::InjectClipboardEvent( 187 void ClipboardWin::InjectClipboardEvent(
135 const protocol::ClipboardEvent& event) { 188 const protocol::ClipboardEvent& event) {
136 if (!hwnd_) { 189 if (!hwnd_) {
137 return; 190 return;
138 } 191 }
(...skipping 20 matching lines...) Expand all
159 212
160 LPWSTR text_global_locked = 213 LPWSTR text_global_locked =
161 reinterpret_cast<LPWSTR>(::GlobalLock(text_global)); 214 reinterpret_cast<LPWSTR>(::GlobalLock(text_global));
162 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR)); 215 memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR));
163 text_global_locked[text.size()] = (WCHAR)0; 216 text_global_locked[text.size()] = (WCHAR)0;
164 ::GlobalUnlock(text_global); 217 ::GlobalUnlock(text_global);
165 218
166 clipboard.SetData(CF_UNICODETEXT, text_global); 219 clipboard.SetData(CF_UNICODETEXT, text_global);
167 } 220 }
168 221
169 LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam, 222 void ClipboardWin::OnClipboardUpdate() {
170 LPARAM lParam) { 223 DCHECK(hwnd_);
171 return ::DefWindowProc(hwnd, msg, wParam, lParam); 224
225 if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
226 string16 text;
227 // Add a scope, so that we keep the clipboard open for as short a time as
228 // possible.
229 {
230 ScopedClipboard clipboard;
231 if (!clipboard.Init(hwnd_)) {
232 LOG(WARNING) << "Couldn't open the clipboard." << GetLastError();
233 return;
234 }
235
236 HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT);
237 if (!text_global) {
238 LOG(WARNING) << "Couldn't get data from the clipboard: "
239 << GetLastError();
240 return;
241 }
242
243 base::win::ScopedHGlobal<WCHAR> text_lock(text_global);
244 if (!text_lock.get()) {
245 LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError();
246 return;
247 }
248 text.assign(text_lock.get());
249 }
250
251 protocol::ClipboardEvent event;
252 event.set_mime_type(kMimeTypeTextUtf8);
253 event.set_data(UTF16ToUTF8(text));
254
255 // TODO(simonmorris): Send the event to the client.
256 }
172 } 257 }
173 258
174 bool ClipboardWin::RegisterWindowClass() { 259 bool ClipboardWin::RegisterWindowClass() {
175 // This method is only called on the desktop thread, so it doesn't matter 260 // This method is only called on the desktop thread, so it doesn't matter
176 // that the following test is not thread-safe. 261 // that the following test is not thread-safe.
177 static bool registered = false; 262 static bool registered = false;
178 if (registered) { 263 if (registered) {
179 return true; 264 return true;
180 } 265 }
181 266
182 WNDCLASSEX window_class; 267 WNDCLASSEX window_class;
183 base::win::InitializeWindowClass( 268 base::win::InitializeWindowClass(
184 kWindowClassName, 269 kWindowClassName,
185 base::win::WrappedWindowProc<WndProc>, 270 base::win::WrappedWindowProc<WndProc>,
186 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 271 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
187 &window_class); 272 &window_class);
188 if (!::RegisterClassEx(&window_class)) { 273 if (!::RegisterClassEx(&window_class)) {
189 return false; 274 return false;
190 } 275 }
191 276
192 registered = true; 277 registered = true;
193 return true; 278 return true;
194 } 279 }
195 280
281 LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wparam,
282 LPARAM lparam) {
283 if (msg == WM_CREATE) {
284 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lparam);
285 ::SetWindowLongPtr(hwnd,
286 GWLP_USERDATA,
287 reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
288 return 0;
289 }
290 ClipboardWin* clipboard =
291 reinterpret_cast<ClipboardWin*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
292 switch (msg) {
293 case WM_CLIPBOARDUPDATE:
294 clipboard->OnClipboardUpdate();
295 return 0;
296 }
297 return ::DefWindowProc(hwnd, msg, wparam, lparam);
298 }
299
196 scoped_ptr<Clipboard> Clipboard::Create() { 300 scoped_ptr<Clipboard> Clipboard::Create() {
197 return scoped_ptr<Clipboard>(new ClipboardWin()); 301 return scoped_ptr<Clipboard>(new ClipboardWin());
198 } 302 }
199 303
200 } // namespace remoting 304 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/chromoting_host_context.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698