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

Unified 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: Sync. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/clipboard.h ('k') | remoting/host/desktop_environment.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/clipboard_win.cc
diff --git a/remoting/host/clipboard_win.cc b/remoting/host/clipboard_win.cc
index d812d2f86ba71531f61e339cf41a2de64abf771c..b3fc0c10effe4a647f671110859bcb7c3b2ef430 100644
--- a/remoting/host/clipboard_win.cc
+++ b/remoting/host/clipboard_win.cc
@@ -12,6 +12,8 @@
#include "base/process_util.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
+#include "base/win/scoped_hglobal.h"
+#include "base/win/windows_version.h"
#include "base/win/wrapped_window_proc.h"
#include "remoting/base/constants.h"
#include "remoting/proto/event.pb.h"
@@ -45,7 +47,7 @@ class ScopedClipboard {
return true;
}
- // This code runs on the desktop thread, so blocking briefly is acceptable.
+ // This code runs on the UI thread, so we can block only very briefly.
for (int attempt = 0; attempt < kMaxAttemptsToOpenClipboard; ++attempt) {
if (attempt > 0) {
base::PlatformThread::Sleep(kSleepTimeBetweenAttempts);
@@ -75,10 +77,24 @@ 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 format) {
+ if (!opened_) {
+ NOTREACHED();
+ return NULL;
+ }
+ return ::GetClipboardData(format);
+ }
+
private:
bool opened_;
};
+typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND);
+typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND);
+
} // namespace
namespace remoting {
@@ -93,20 +109,48 @@ class ClipboardWin : public Clipboard {
virtual void Stop() OVERRIDE;
private:
- static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam,
- LPARAM lParam);
+ void OnClipboardUpdate();
+ bool HaveClipboardListenerApi();
static bool RegisterWindowClass();
+ static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam,
+ LPARAM lParam);
HWND hwnd_;
+ AddClipboardFormatListenerFn* add_clipboard_format_listener_;
+ RemoveClipboardFormatListenerFn* remove_clipboard_format_listener_;
+ bool load_functions_tried_;
DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
};
-ClipboardWin::ClipboardWin() : hwnd_(NULL) {
+ClipboardWin::ClipboardWin()
+ : hwnd_(NULL),
+ add_clipboard_format_listener_(NULL),
+ remove_clipboard_format_listener_(NULL),
+ load_functions_tried_(false) {
}
void ClipboardWin::Start() {
+ if (!load_functions_tried_) {
+ load_functions_tried_ = true;
+ HMODULE user32_module = ::GetModuleHandle(L"user32.dll");
+ if (!user32_module) {
+ LOG(WARNING) << "Couldn't find user32.dll.";
+ } else {
+ add_clipboard_format_listener_ =
+ reinterpret_cast<AddClipboardFormatListenerFn*>(
+ ::GetProcAddress(user32_module, "AddClipboardFormatListener"));
+ remove_clipboard_format_listener_ =
+ reinterpret_cast<RemoveClipboardFormatListenerFn*>(
+ ::GetProcAddress(user32_module, "RemoveClipboardFormatListener"));
+ if (!HaveClipboardListenerApi()) {
+ LOG(WARNING) << "Couldn't load AddClipboardFormatListener or "
+ << "RemoveClipboardFormatListener.";
+ }
+ }
+ }
+
if (!RegisterWindowClass()) {
LOG(FATAL) << "Couldn't register clipboard window class.";
return;
@@ -122,10 +166,19 @@ void ClipboardWin::Start() {
LOG(FATAL) << "Couldn't create clipboard window.";
return;
}
+
+ if (HaveClipboardListenerApi()) {
+ if (!(*add_clipboard_format_listener_)(hwnd_)) {
+ LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError();
+ }
+ }
}
void ClipboardWin::Stop() {
if (hwnd_) {
+ if (HaveClipboardListenerApi()) {
+ (*remove_clipboard_format_listener_)(hwnd_);
+ }
::DestroyWindow(hwnd_);
hwnd_ = NULL;
}
@@ -166,13 +219,49 @@ void ClipboardWin::InjectClipboardEvent(
clipboard.SetData(CF_UNICODETEXT, text_global);
}
-LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam) {
- return ::DefWindowProc(hwnd, msg, wParam, lParam);
+void ClipboardWin::OnClipboardUpdate() {
+ DCHECK(hwnd_);
+
+ 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;
+ }
+
+ base::win::ScopedHGlobal<WCHAR> text_lock(text_global);
+ if (!text_lock.get()) {
+ LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError();
+ return;
+ }
+ text.assign(text_lock.get());
+ }
+
+ protocol::ClipboardEvent event;
+ event.set_mime_type(kMimeTypeTextUtf8);
+ event.set_data(UTF16ToUTF8(text));
+
+ // TODO(simonmorris): Send the event to the client.
+ }
+}
+
+bool ClipboardWin::HaveClipboardListenerApi() {
+ return add_clipboard_format_listener_ && remove_clipboard_format_listener_;
}
bool ClipboardWin::RegisterWindowClass() {
- // This method is only called on the desktop thread, so it doesn't matter
+ // This method is only called on the UI thread, so it doesn't matter
// that the following test is not thread-safe.
static bool registered = false;
if (registered) {
@@ -193,6 +282,25 @@ bool ClipboardWin::RegisterWindowClass() {
return true;
}
+LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam) {
+ if (msg == WM_CREATE) {
+ CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lparam);
+ ::SetWindowLongPtr(hwnd,
+ GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
+ return 0;
+ }
+ ClipboardWin* clipboard =
+ reinterpret_cast<ClipboardWin*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
+ switch (msg) {
+ case WM_CLIPBOARDUPDATE:
+ clipboard->OnClipboardUpdate();
+ return 0;
+ }
+ return ::DefWindowProc(hwnd, msg, wparam, lparam);
+}
+
scoped_ptr<Clipboard> Clipboard::Create() {
return scoped_ptr<Clipboard>(new ClipboardWin());
}
« no previous file with comments | « remoting/host/clipboard.h ('k') | remoting/host/desktop_environment.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698