Chromium Code Reviews| Index: remoting/host/clipboard_win.cc |
| diff --git a/remoting/host/clipboard_win.cc b/remoting/host/clipboard_win.cc |
| index d812d2f86ba71531f61e339cf41a2de64abf771c..0a4c8d24b4733a9ad08155cb69139992913f5db6 100644 |
| --- a/remoting/host/clipboard_win.cc |
| +++ b/remoting/host/clipboard_win.cc |
| @@ -75,10 +75,47 @@ class ScopedClipboard { |
| ::SetClipboardData(uFormat, hMem); |
| } |
| + // The caller must not free the handle. The caller should lock the handle, |
| + // copy the clipboard data, and unlock the handle. All this must be done |
| + // before this ScopedClipboard is destroyed. |
| + 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.
|
| + if (!opened_) { |
| + NOTREACHED(); |
| + return NULL; |
| + } |
| + return ::GetClipboardData(uFormat); |
| + } |
| + |
| private: |
| bool opened_; |
| }; |
| +// A scoper class that wraps a lock on a global memory object. |
| +template <typename T> |
| +class ScopedGlobalLock { |
|
dcheng
2012/05/11 20:28:31
Can you use ScopedHGlobalfrom base/win?
simonmorris
2012/05/11 22:12:58
Done.
|
| + public: |
| + 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.
|
| + 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.
|
| + } |
| + |
| + ~ScopedGlobalLock() { |
| + if (pointer_) { |
| + ::GlobalUnlock(hGlobalMem_); |
| + } |
| + } |
| + |
| + 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.
|
| + return reinterpret_cast<T>(pointer_); |
| + } |
| + |
| + private: |
| + 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.
|
| + LPVOID pointer_; |
| +}; |
| + |
| +typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND); |
| +typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND); |
| + |
| } // namespace |
| namespace remoting { |
| @@ -98,6 +135,8 @@ class ClipboardWin : public Clipboard { |
| static bool RegisterWindowClass(); |
| + 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.
|
| + |
| HWND hwnd_; |
| DISALLOW_COPY_AND_ASSIGN(ClipboardWin); |
| @@ -122,10 +161,29 @@ void ClipboardWin::Start() { |
| LOG(FATAL) << "Couldn't create clipboard window."; |
| return; |
| } |
| + |
| + AddClipboardFormatListenerFn* add = |
| + reinterpret_cast<AddClipboardFormatListenerFn*>( |
| + ::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
|
| + "AddClipboardFormatListener")); |
| + if (add) { |
| + if (!(*add)(hwnd_)) { |
| + LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError(); |
| + } |
| + } else { |
| + 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
|
| + } |
| } |
| void ClipboardWin::Stop() { |
| if (hwnd_) { |
| + RemoveClipboardFormatListenerFn* remove = |
| + reinterpret_cast<RemoveClipboardFormatListenerFn*>( |
| + ::GetProcAddress(::GetModuleHandle(L"user32.dll"), |
| + "RemoveClipboardFormatListener")); |
| + if (remove) { |
| + (*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.
|
| + } |
| ::DestroyWindow(hwnd_); |
| hwnd_ = NULL; |
| } |
| @@ -168,6 +226,20 @@ void ClipboardWin::InjectClipboardEvent( |
| LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam, |
| LPARAM lParam) { |
| + if (msg == WM_CREATE) { |
| + 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.
|
| + ::SetWindowLongPtr(hwnd, |
| + GWLP_USERDATA, |
| + reinterpret_cast<LONG_PTR>(cs->lpCreateParams)); |
| + return 0; |
| + } |
| + 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.
|
| + reinterpret_cast<ClipboardWin*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA)); |
| + switch (msg) { |
| + case WM_CLIPBOARDUPDATE: |
| + clipboardWin->OnClipboardUpdate(); |
| + return 0; |
| + } |
| return ::DefWindowProc(hwnd, msg, wParam, lParam); |
| } |
| @@ -193,6 +265,46 @@ bool ClipboardWin::RegisterWindowClass() { |
| return true; |
| } |
| +void ClipboardWin::OnClipboardUpdate() { |
| + 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.
|
| + return; |
| + } |
| + |
| + if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) { |
| + string16 text; |
| + // Add a scope, so that we keep the clipboard open for as short a time as |
| + // possible. |
| + { |
| + ScopedClipboard clipboard; |
| + if (!clipboard.Init(hwnd_)) { |
| + LOG(WARNING) << "Couldn't open the clipboard." << GetLastError(); |
| + return; |
| + } |
| + |
| + HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT); |
| + if (!text_global) { |
| + LOG(WARNING) << "Couldn't get data from the clipboard: " |
| + << GetLastError(); |
| + return; |
| + } |
| + |
| + ScopedGlobalLock<LPWSTR> text_lock(text_global); |
| + if (!text_lock.GetPointer()) { |
| + LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError(); |
| + return; |
| + } |
| + 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.
|
| + 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.
|
| + } |
| + |
| + protocol::ClipboardEvent event; |
| + event.set_mime_type(kMimeTypeTextUtf8); |
| + event.set_data(UTF16ToUTF8(text)); |
| + |
| + // TODO(simonmorris): Send the event to the client. |
| + } |
| +} |
| + |
| scoped_ptr<Clipboard> Clipboard::Create() { |
| return scoped_ptr<Clipboard>(new ClipboardWin()); |
| } |