blob: 234dacf0f4b52e19419aaf90964cac1297664c11 [file] [log] [blame]
[email protected]6d17db92012-05-11 17:03:141// 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
3// found in the LICENSE file.
4
5#include "remoting/host/clipboard.h"
6
[email protected]070ffb72012-09-27 00:24:497#include <X11/Xlib.h>
8
9#include "base/bind.h"
[email protected]6d17db92012-05-11 17:03:1410#include "base/logging.h"
[email protected]070ffb72012-09-27 00:24:4911#include "base/message_loop.h"
12#include "remoting/host/linux/x_server_clipboard.h"
13#include "remoting/proto/event.pb.h"
14#include "remoting/protocol/clipboard_stub.h"
[email protected]6d17db92012-05-11 17:03:1415
16namespace remoting {
17
[email protected]070ffb72012-09-27 00:24:4918// This code is expected to be called on the desktop thread only.
[email protected]c9c94bad2013-04-29 17:45:1219class ClipboardX11 : public Clipboard,
[email protected]faea9d2d2013-04-30 03:18:4420 public base::MessageLoopForIO::Watcher {
[email protected]6d17db92012-05-11 17:03:1421 public:
[email protected]c9c94bad2013-04-29 17:45:1222 ClipboardX11();
23 virtual ~ClipboardX11();
[email protected]6d17db92012-05-11 17:03:1424
[email protected]070ffb72012-09-27 00:24:4925 // Clipboard interface.
[email protected]7f44ba42012-05-31 20:26:2926 virtual void Start(
27 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE;
[email protected]6d17db92012-05-11 17:03:1428 virtual void InjectClipboardEvent(
29 const protocol::ClipboardEvent& event) OVERRIDE;
30 virtual void Stop() OVERRIDE;
31
[email protected]070ffb72012-09-27 00:24:4932 // MessageLoopForIO::Watcher interface.
33 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
34 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
35
[email protected]6d17db92012-05-11 17:03:1436 private:
[email protected]070ffb72012-09-27 00:24:4937 void OnClipboardChanged(const std::string& mime_type,
38 const std::string& data);
39 void PumpXEvents();
40
41 scoped_ptr<protocol::ClipboardStub> client_clipboard_;
42
[email protected]e2123b52012-11-17 14:19:4943 // Underlying X11 clipboard implementation.
[email protected]070ffb72012-09-27 00:24:4944 XServerClipboard x_server_clipboard_;
[email protected]e2123b52012-11-17 14:19:4945
46 // Connection to the X server, used by |x_server_clipboard_|. This is created
47 // and owned by this class.
[email protected]070ffb72012-09-27 00:24:4948 Display* display_;
49
[email protected]e2123b52012-11-17 14:19:4950 // Watcher used to handle X11 events from |display_|.
[email protected]faea9d2d2013-04-30 03:18:4451 base::MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_;
[email protected]070ffb72012-09-27 00:24:4952
[email protected]c9c94bad2013-04-29 17:45:1253 DISALLOW_COPY_AND_ASSIGN(ClipboardX11);
[email protected]6d17db92012-05-11 17:03:1454};
55
[email protected]c9c94bad2013-04-29 17:45:1256ClipboardX11::ClipboardX11()
[email protected]070ffb72012-09-27 00:24:4957 : display_(NULL) {
58}
59
[email protected]c9c94bad2013-04-29 17:45:1260ClipboardX11::~ClipboardX11() {
[email protected]070ffb72012-09-27 00:24:4961 Stop();
62}
63
[email protected]c9c94bad2013-04-29 17:45:1264void ClipboardX11::Start(
[email protected]7f44ba42012-05-31 20:26:2965 scoped_ptr<protocol::ClipboardStub> client_clipboard) {
[email protected]b0b72f112013-03-24 03:42:4266 // TODO(lambroslambrou): Share the X connection with InputInjector.
[email protected]070ffb72012-09-27 00:24:4967 display_ = XOpenDisplay(NULL);
68 if (!display_) {
69 LOG(ERROR) << "Couldn't open X display";
70 return;
71 }
72 client_clipboard_.swap(client_clipboard);
73
74 x_server_clipboard_.Init(display_,
[email protected]c9c94bad2013-04-29 17:45:1275 base::Bind(&ClipboardX11::OnClipboardChanged,
[email protected]070ffb72012-09-27 00:24:4976 base::Unretained(this)));
77
[email protected]faea9d2d2013-04-30 03:18:4478 base::MessageLoopForIO::current()->WatchFileDescriptor(
79 ConnectionNumber(display_),
80 true,
81 base::MessageLoopForIO::WATCH_READ,
82 &x_connection_watcher_,
83 this);
[email protected]070ffb72012-09-27 00:24:4984 PumpXEvents();
[email protected]6d17db92012-05-11 17:03:1485}
86
[email protected]c9c94bad2013-04-29 17:45:1287void ClipboardX11::InjectClipboardEvent(
[email protected]6d17db92012-05-11 17:03:1488 const protocol::ClipboardEvent& event) {
[email protected]070ffb72012-09-27 00:24:4989 x_server_clipboard_.SetClipboard(event.mime_type(), event.data());
[email protected]6d17db92012-05-11 17:03:1490}
91
[email protected]c9c94bad2013-04-29 17:45:1292void ClipboardX11::Stop() {
[email protected]070ffb72012-09-27 00:24:4993 client_clipboard_.reset();
94 x_connection_watcher_.StopWatchingFileDescriptor();
95
96 if (display_) {
97 XCloseDisplay(display_);
98 display_ = NULL;
99 }
100}
101
[email protected]c9c94bad2013-04-29 17:45:12102void ClipboardX11::OnFileCanReadWithoutBlocking(int fd) {
[email protected]070ffb72012-09-27 00:24:49103 PumpXEvents();
104}
105
[email protected]c9c94bad2013-04-29 17:45:12106void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]070ffb72012-09-27 00:24:49107}
108
[email protected]c9c94bad2013-04-29 17:45:12109void ClipboardX11::OnClipboardChanged(const std::string& mime_type,
110 const std::string& data) {
[email protected]070ffb72012-09-27 00:24:49111 protocol::ClipboardEvent event;
112 event.set_mime_type(mime_type);
113 event.set_data(data);
114
115 if (client_clipboard_.get()) {
116 client_clipboard_->InjectClipboardEvent(event);
117 }
118}
119
[email protected]c9c94bad2013-04-29 17:45:12120void ClipboardX11::PumpXEvents() {
[email protected]070ffb72012-09-27 00:24:49121 DCHECK(display_);
122
123 while (XPending(display_)) {
124 XEvent event;
125 XNextEvent(display_, &event);
126 x_server_clipboard_.ProcessXEvent(&event);
127 }
[email protected]6d17db92012-05-11 17:03:14128}
129
130scoped_ptr<Clipboard> Clipboard::Create() {
[email protected]c9c94bad2013-04-29 17:45:12131 return scoped_ptr<Clipboard>(new ClipboardX11());
[email protected]6d17db92012-05-11 17:03:14132}
133
134} // namespace remoting