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"
10 #include "base/logging.h"
11 #include "base/message_loop/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"
18 // This code is expected to be called on the desktop thread only.
19 class ClipboardX11
: public Clipboard
,
20 public base::MessageLoopForIO::Watcher
{
23 virtual ~ClipboardX11();
25 // Clipboard interface.
27 scoped_ptr
<protocol::ClipboardStub
> client_clipboard
) OVERRIDE
;
28 virtual void InjectClipboardEvent(
29 const protocol::ClipboardEvent
& event
) OVERRIDE
;
30 virtual void Stop() OVERRIDE
;
32 // MessageLoopForIO::Watcher interface.
33 virtual void OnFileCanReadWithoutBlocking(int fd
) OVERRIDE
;
34 virtual void OnFileCanWriteWithoutBlocking(int fd
) OVERRIDE
;
37 void OnClipboardChanged(const std::string
& mime_type
,
38 const std::string
& data
);
41 scoped_ptr
<protocol::ClipboardStub
> client_clipboard_
;
43 // Underlying X11 clipboard implementation.
44 XServerClipboard x_server_clipboard_
;
46 // Connection to the X server, used by |x_server_clipboard_|. This is created
47 // and owned by this class.
50 // Watcher used to handle X11 events from |display_|.
51 base::MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_
;
53 DISALLOW_COPY_AND_ASSIGN(ClipboardX11
);
56 ClipboardX11::ClipboardX11()
60 ClipboardX11::~ClipboardX11() {
64 void ClipboardX11::Start(
65 scoped_ptr
<protocol::ClipboardStub
> client_clipboard
) {
66 // TODO(lambroslambrou): Share the X connection with InputInjector.
67 display_
= XOpenDisplay(NULL
);
69 LOG(ERROR
) << "Couldn't open X display";
72 client_clipboard_
.swap(client_clipboard
);
74 x_server_clipboard_
.Init(display_
,
75 base::Bind(&ClipboardX11::OnClipboardChanged
,
76 base::Unretained(this)));
78 base::MessageLoopForIO::current()->WatchFileDescriptor(
79 ConnectionNumber(display_
),
81 base::MessageLoopForIO::WATCH_READ
,
82 &x_connection_watcher_
,
87 void ClipboardX11::InjectClipboardEvent(
88 const protocol::ClipboardEvent
& event
) {
89 x_server_clipboard_
.SetClipboard(event
.mime_type(), event
.data());
92 void ClipboardX11::Stop() {
93 client_clipboard_
.reset();
94 x_connection_watcher_
.StopWatchingFileDescriptor();
97 XCloseDisplay(display_
);
102 void ClipboardX11::OnFileCanReadWithoutBlocking(int fd
) {
106 void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd
) {
109 void ClipboardX11::OnClipboardChanged(const std::string
& mime_type
,
110 const std::string
& data
) {
111 protocol::ClipboardEvent event
;
112 event
.set_mime_type(mime_type
);
113 event
.set_data(data
);
115 if (client_clipboard_
.get()) {
116 client_clipboard_
->InjectClipboardEvent(event
);
120 void ClipboardX11::PumpXEvents() {
123 while (XPending(display_
)) {
125 XNextEvent(display_
, &event
);
126 x_server_clipboard_
.ProcessXEvent(&event
);
130 scoped_ptr
<Clipboard
> Clipboard::Create() {
131 return scoped_ptr
<Clipboard
>(new ClipboardX11());
134 } // namespace remoting