summaryrefslogtreecommitdiffstats
path: root/remoting/host/clipboard_x11.cc
diff options
context:
space:
mode:
Diffstat (limited to 'remoting/host/clipboard_x11.cc')
-rw-r--r--remoting/host/clipboard_x11.cc131
1 files changed, 131 insertions, 0 deletions
diff --git a/remoting/host/clipboard_x11.cc b/remoting/host/clipboard_x11.cc
new file mode 100644
index 0000000..eb952c1
--- /dev/null
+++ b/remoting/host/clipboard_x11.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/clipboard.h"
+
+#include <X11/Xlib.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "remoting/host/linux/x_server_clipboard.h"
+#include "remoting/proto/event.pb.h"
+#include "remoting/protocol/clipboard_stub.h"
+
+namespace remoting {
+
+// This code is expected to be called on the desktop thread only.
+class ClipboardX11 : public Clipboard,
+ public MessageLoopForIO::Watcher {
+ public:
+ ClipboardX11();
+ virtual ~ClipboardX11();
+
+ // Clipboard interface.
+ virtual void Start(
+ scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE;
+ virtual void InjectClipboardEvent(
+ const protocol::ClipboardEvent& event) OVERRIDE;
+ virtual void Stop() OVERRIDE;
+
+ // MessageLoopForIO::Watcher interface.
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
+
+ private:
+ void OnClipboardChanged(const std::string& mime_type,
+ const std::string& data);
+ void PumpXEvents();
+
+ scoped_ptr<protocol::ClipboardStub> client_clipboard_;
+
+ // Underlying X11 clipboard implementation.
+ XServerClipboard x_server_clipboard_;
+
+ // Connection to the X server, used by |x_server_clipboard_|. This is created
+ // and owned by this class.
+ Display* display_;
+
+ // Watcher used to handle X11 events from |display_|.
+ MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClipboardX11);
+};
+
+ClipboardX11::ClipboardX11()
+ : display_(NULL) {
+}
+
+ClipboardX11::~ClipboardX11() {
+ Stop();
+}
+
+void ClipboardX11::Start(
+ scoped_ptr<protocol::ClipboardStub> client_clipboard) {
+ // TODO(lambroslambrou): Share the X connection with InputInjector.
+ display_ = XOpenDisplay(NULL);
+ if (!display_) {
+ LOG(ERROR) << "Couldn't open X display";
+ return;
+ }
+ client_clipboard_.swap(client_clipboard);
+
+ x_server_clipboard_.Init(display_,
+ base::Bind(&ClipboardX11::OnClipboardChanged,
+ base::Unretained(this)));
+
+ MessageLoopForIO::current()->WatchFileDescriptor(
+ ConnectionNumber(display_), true, MessageLoopForIO::WATCH_READ,
+ &x_connection_watcher_, this);
+ PumpXEvents();
+}
+
+void ClipboardX11::InjectClipboardEvent(
+ const protocol::ClipboardEvent& event) {
+ x_server_clipboard_.SetClipboard(event.mime_type(), event.data());
+}
+
+void ClipboardX11::Stop() {
+ client_clipboard_.reset();
+ x_connection_watcher_.StopWatchingFileDescriptor();
+
+ if (display_) {
+ XCloseDisplay(display_);
+ display_ = NULL;
+ }
+}
+
+void ClipboardX11::OnFileCanReadWithoutBlocking(int fd) {
+ PumpXEvents();
+}
+
+void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd) {
+}
+
+void ClipboardX11::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 ClipboardX11::PumpXEvents() {
+ DCHECK(display_);
+
+ while (XPending(display_)) {
+ XEvent event;
+ XNextEvent(display_, &event);
+ x_server_clipboard_.ProcessXEvent(&event);
+ }
+}
+
+scoped_ptr<Clipboard> Clipboard::Create() {
+ return scoped_ptr<Clipboard>(new ClipboardX11());
+}
+
+} // namespace remoting