blob: 94ec094a2445c962c0e6a9c3066b6c01ef919c23 [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>
pkastingdea81dc32015-08-17 20:30:578#undef Status // Xlib.h #defines this, which breaks protobuf headers.
[email protected]070ffb72012-09-27 00:24:499
10#include "base/bind.h"
[email protected]6d17db92012-05-11 17:03:1411#include "base/logging.h"
avic5960f32015-12-22 22:49:4812#include "base/macros.h"
[email protected]f368eeb2013-07-17 23:53:3213#include "base/message_loop/message_loop.h"
[email protected]070ffb72012-09-27 00:24:4914#include "remoting/host/linux/x_server_clipboard.h"
15#include "remoting/proto/event.pb.h"
16#include "remoting/protocol/clipboard_stub.h"
[email protected]6d17db92012-05-11 17:03:1417
18namespace remoting {
19
[email protected]070ffb72012-09-27 00:24:4920// This code is expected to be called on the desktop thread only.
[email protected]c9c94bad2013-04-29 17:45:1221class ClipboardX11 : public Clipboard,
[email protected]faea9d2d2013-04-30 03:18:4422 public base::MessageLoopForIO::Watcher {
[email protected]6d17db92012-05-11 17:03:1423 public:
[email protected]c9c94bad2013-04-29 17:45:1224 ClipboardX11();
dcheng440d8e1c2014-10-28 01:23:1525 ~ClipboardX11() override;
[email protected]6d17db92012-05-11 17:03:1426
[email protected]070ffb72012-09-27 00:24:4927 // Clipboard interface.
dcheng440d8e1c2014-10-28 01:23:1528 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard) override;
29 void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
[email protected]6d17db92012-05-11 17:03:1430
[email protected]070ffb72012-09-27 00:24:4931 // MessageLoopForIO::Watcher interface.
dcheng440d8e1c2014-10-28 01:23:1532 void OnFileCanReadWithoutBlocking(int fd) override;
33 void OnFileCanWriteWithoutBlocking(int fd) override;
[email protected]070ffb72012-09-27 00:24:4934
[email protected]6d17db92012-05-11 17:03:1435 private:
[email protected]070ffb72012-09-27 00:24:4936 void OnClipboardChanged(const std::string& mime_type,
37 const std::string& data);
38 void PumpXEvents();
39
40 scoped_ptr<protocol::ClipboardStub> client_clipboard_;
41
[email protected]e2123b52012-11-17 14:19:4942 // Underlying X11 clipboard implementation.
[email protected]070ffb72012-09-27 00:24:4943 XServerClipboard x_server_clipboard_;
[email protected]e2123b52012-11-17 14:19:4944
45 // Connection to the X server, used by |x_server_clipboard_|. This is created
46 // and owned by this class.
[email protected]070ffb72012-09-27 00:24:4947 Display* display_;
48
[email protected]e2123b52012-11-17 14:19:4949 // Watcher used to handle X11 events from |display_|.
[email protected]faea9d2d2013-04-30 03:18:4450 base::MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_;
[email protected]070ffb72012-09-27 00:24:4951
[email protected]c9c94bad2013-04-29 17:45:1252 DISALLOW_COPY_AND_ASSIGN(ClipboardX11);
[email protected]6d17db92012-05-11 17:03:1453};
54
[email protected]c9c94bad2013-04-29 17:45:1255ClipboardX11::ClipboardX11()
sergeyuc5f104b2015-01-09 19:33:2456 : display_(nullptr) {
[email protected]070ffb72012-09-27 00:24:4957}
58
[email protected]c9c94bad2013-04-29 17:45:1259ClipboardX11::~ClipboardX11() {
sergeyu45f92d832015-02-19 01:24:1960 if (display_)
61 XCloseDisplay(display_);
[email protected]070ffb72012-09-27 00:24:4962}
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.
sergeyuc5f104b2015-01-09 19:33:2467 display_ = XOpenDisplay(nullptr);
[email protected]070ffb72012-09-27 00:24:4968 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::OnFileCanReadWithoutBlocking(int fd) {
[email protected]070ffb72012-09-27 00:24:4993 PumpXEvents();
94}
95
[email protected]c9c94bad2013-04-29 17:45:1296void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]070ffb72012-09-27 00:24:4997}
98
[email protected]c9c94bad2013-04-29 17:45:1299void ClipboardX11::OnClipboardChanged(const std::string& mime_type,
100 const std::string& data) {
[email protected]070ffb72012-09-27 00:24:49101 protocol::ClipboardEvent event;
102 event.set_mime_type(mime_type);
103 event.set_data(data);
104
105 if (client_clipboard_.get()) {
106 client_clipboard_->InjectClipboardEvent(event);
107 }
108}
109
[email protected]c9c94bad2013-04-29 17:45:12110void ClipboardX11::PumpXEvents() {
[email protected]070ffb72012-09-27 00:24:49111 DCHECK(display_);
112
113 while (XPending(display_)) {
114 XEvent event;
115 XNextEvent(display_, &event);
116 x_server_clipboard_.ProcessXEvent(&event);
117 }
[email protected]6d17db92012-05-11 17:03:14118}
119
120scoped_ptr<Clipboard> Clipboard::Create() {
sergeyu2d690882014-10-01 02:36:43121 return make_scoped_ptr(new ClipboardX11());
[email protected]6d17db92012-05-11 17:03:14122}
123
124} // namespace remoting