| Index: remoting/host/clipboard_linux.cc
|
| diff --git a/remoting/host/clipboard_linux.cc b/remoting/host/clipboard_linux.cc
|
| index 6a1729167fccf9aeea4617c719d28d037e3290a2..b4ed2d694d12bbb29e896429b4a4ebc2bd7c313d 100644
|
| --- a/remoting/host/clipboard_linux.cc
|
| +++ b/remoting/host/clipboard_linux.cc
|
| @@ -4,13 +4,23 @@
|
|
|
| #include "remoting/host/clipboard.h"
|
|
|
| +#include <X11/Xlib.h>
|
| +
|
| +#include "base/bind.h"
|
| #include "base/logging.h"
|
| +#include "base/threading/thread.h"
|
| +#include "base/time.h"
|
| +#include "base/timer.h"
|
| +#include "remoting/host/x_server_clipboard.h"
|
| +#include "remoting/proto/event.pb.h"
|
| +#include "remoting/protocol/clipboard_stub.h"
|
|
|
| namespace remoting {
|
|
|
| class ClipboardLinux : public Clipboard {
|
| public:
|
| ClipboardLinux();
|
| + ~ClipboardLinux();
|
|
|
| // Must be called on the UI thread.
|
| virtual void Start(
|
| @@ -20,21 +30,112 @@ class ClipboardLinux : public Clipboard {
|
| virtual void Stop() OVERRIDE;
|
|
|
| private:
|
| + void OnClipboardChanged(const std::string& mime_type,
|
| + const std::string& data);
|
| + void PumpEvents();
|
| +
|
| + scoped_ptr<protocol::ClipboardStub> client_clipboard_;
|
| +
|
| + XServerClipboard x_server_clipboard_;
|
| + Display* display_;
|
| + base::Thread x11_thread_;
|
| + base::RepeatingTimer<ClipboardLinux> event_timer_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(ClipboardLinux);
|
| };
|
|
|
| +ClipboardLinux::ClipboardLinux() : x11_thread_("Clipboard X11 thread") {
|
| + x11_thread_.Start();
|
| +}
|
| +
|
| +ClipboardLinux::~ClipboardLinux() {
|
| + Stop();
|
| + x11_thread_.Stop();
|
| +}
|
| +
|
| void ClipboardLinux::Start(
|
| scoped_ptr<protocol::ClipboardStub> client_clipboard) {
|
| - NOTIMPLEMENTED();
|
| + if (!x11_thread_.message_loop_proxy()->BelongsToCurrentThread()) {
|
| + // base::Unretained is safe, since the clipboard thread is owned by this
|
| + // object.
|
| + x11_thread_.message_loop_proxy()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ClipboardLinux::Start, base::Unretained(this),
|
| + base::Passed(client_clipboard.Pass())));
|
| + return;
|
| + }
|
| +
|
| + LOG(ERROR) << "*** Start";
|
| +
|
| + display_ = XOpenDisplay(NULL);
|
| + if (!display_) {
|
| + LOG(ERROR) << "Couldn't open X display";
|
| + return;
|
| + }
|
| + client_clipboard_.swap(client_clipboard);
|
| +
|
| + // base::Unretained is safe, since the clipboard thread is owned by this
|
| + // object, and this dtor resets |callback_|, so that no more clipboard
|
| + // changes are processed while stopping the thread.
|
| + x_server_clipboard_.Init(display_,
|
| + base::Bind(&ClipboardLinux::OnClipboardChanged,
|
| + base::Unretained(this)));
|
| +
|
| + event_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this,
|
| + &ClipboardLinux::PumpEvents);
|
| }
|
|
|
| void ClipboardLinux::InjectClipboardEvent(
|
| const protocol::ClipboardEvent& event) {
|
| - NOTIMPLEMENTED();
|
| + if (!x11_thread_.message_loop_proxy()->BelongsToCurrentThread()) {
|
| + x11_thread_.message_loop_proxy()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ClipboardLinux::InjectClipboardEvent,
|
| + base::Unretained(this),
|
| + event));
|
| + return;
|
| + }
|
| +
|
| + LOG(ERROR) << "*** InjectClipboardEvent('" << event.mime_type()
|
| + << "', '" << event.data() << "')";
|
| + x_server_clipboard_.SetClipboard(event.mime_type(), event.data());
|
| }
|
|
|
| void ClipboardLinux::Stop() {
|
| - NOTIMPLEMENTED();
|
| + if (!x11_thread_.message_loop_proxy()->BelongsToCurrentThread()) {
|
| + x11_thread_.message_loop_proxy()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ClipboardLinux::Stop, base::Unretained(this)));
|
| + return;
|
| + }
|
| +
|
| + client_clipboard_.reset();
|
| + event_timer_.Stop();
|
| + if (display_) {
|
| + XCloseDisplay(display_);
|
| + display_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void ClipboardLinux::OnClipboardChanged(const std::string& mime_type,
|
| + const std::string& data) {
|
| + protocol::ClipboardEvent event;
|
| + event.set_mime_type(mime_type);
|
| + event.set_data(data);
|
| +
|
| + if (client_clipboard_.get()) {
|
| + client_clipboard_->InjectClipboardEvent(event);
|
| + }
|
| +}
|
| +
|
| +void ClipboardLinux::PumpEvents() {
|
| + DCHECK(display_);
|
| +
|
| + while (XPending(display_)) {
|
| + XEvent event;
|
| + XNextEvent(display_, &event);
|
| + x_server_clipboard_.ProcessXEvent(&event);
|
| + }
|
| }
|
|
|
| scoped_ptr<Clipboard> Clipboard::Create() {
|
|
|