1 // 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.
5 #include "remoting/host/clipboard.h"
8 #undef Status // Xlib.h #defines this, which breaks protobuf headers.
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "remoting/host/linux/x_server_clipboard.h"
14 #include "remoting/proto/event.pb.h"
15 #include "remoting/protocol/clipboard_stub.h"
19 // This code is expected to be called on the desktop thread only.
20 class ClipboardX11
: public Clipboard
,
21 public base::MessageLoopForIO::Watcher
{
24 ~ClipboardX11() override
;
26 // Clipboard interface.
27 void Start(scoped_ptr
<protocol::ClipboardStub
> client_clipboard
) override
;
28 void InjectClipboardEvent(const protocol::ClipboardEvent
& event
) override
;
30 // MessageLoopForIO::Watcher interface.
31 void OnFileCanReadWithoutBlocking(int fd
) override
;
32 void OnFileCanWriteWithoutBlocking(int fd
) override
;
35 void OnClipboardChanged(const std::string
& mime_type
,
36 const std::string
& data
);
39 scoped_ptr
<protocol::ClipboardStub
> client_clipboard_
;
41 // Underlying X11 clipboard implementation.
42 XServerClipboard x_server_clipboard_
;
44 // Connection to the X server, used by |x_server_clipboard_|. This is created
45 // and owned by this class.
48 // Watcher used to handle X11 events from |display_|.
49 base::MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_
;
51 DISALLOW_COPY_AND_ASSIGN(ClipboardX11
);
54 ClipboardX11::ClipboardX11()
58 ClipboardX11::~ClipboardX11() {
60 XCloseDisplay(display_
);
63 void ClipboardX11::Start(
64 scoped_ptr
<protocol::ClipboardStub
> client_clipboard
) {
65 // TODO(lambroslambrou): Share the X connection with InputInjector.
66 display_
= XOpenDisplay(nullptr);
68 LOG(ERROR
) << "Couldn't open X display";
71 client_clipboard_
.swap(client_clipboard
);
73 x_server_clipboard_
.Init(display_
,
74 base::Bind(&ClipboardX11::OnClipboardChanged
,
75 base::Unretained(this)));
77 base::MessageLoopForIO::current()->WatchFileDescriptor(
78 ConnectionNumber(display_
),
80 base::MessageLoopForIO::WATCH_READ
,
81 &x_connection_watcher_
,
86 void ClipboardX11::InjectClipboardEvent(
87 const protocol::ClipboardEvent
& event
) {
88 x_server_clipboard_
.SetClipboard(event
.mime_type(), event
.data());
91 void ClipboardX11::OnFileCanReadWithoutBlocking(int fd
) {
95 void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd
) {
98 void ClipboardX11::OnClipboardChanged(const std::string
& mime_type
,
99 const std::string
& data
) {
100 protocol::ClipboardEvent event
;
101 event
.set_mime_type(mime_type
);
102 event
.set_data(data
);
104 if (client_clipboard_
.get()) {
105 client_clipboard_
->InjectClipboardEvent(event
);
109 void ClipboardX11::PumpXEvents() {
112 while (XPending(display_
)) {
114 XNextEvent(display_
, &event
);
115 x_server_clipboard_
.ProcessXEvent(&event
);
119 scoped_ptr
<Clipboard
> Clipboard::Create() {
120 return make_scoped_ptr(new ClipboardX11());
123 } // namespace remoting