clipboard_x11.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/clipboard.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/linux/x_server_clipboard.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/clipboard_stub.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This code is expected to be called on the desktop thread only. 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ClipboardX11 : public Clipboard, 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public base::MessageLoopForIO::Watcher { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ClipboardX11(); 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~ClipboardX11(); 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clipboard interface. 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Start( 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void InjectClipboardEvent( 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const protocol::ClipboardEvent& event) OVERRIDE; 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Stop() OVERRIDE; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MessageLoopForIO::Watcher interface. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnClipboardChanged(const std::string& mime_type, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PumpXEvents(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<protocol::ClipboardStub> client_clipboard_; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Underlying X11 clipboard implementation. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XServerClipboard x_server_clipboard_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connection to the X server, used by |x_server_clipboard_|. This is created 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and owned by this class. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display_; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Watcher used to handle X11 events from |display_|. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoopForIO::FileDescriptorWatcher x_connection_watcher_; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ClipboardX11); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClipboardX11::ClipboardX11() 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : display_(NULL) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClipboardX11::~ClipboardX11() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardX11::Start( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<protocol::ClipboardStub> client_clipboard) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(lambroslambrou): Share the X connection with InputInjector. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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_, 75 base::Bind(&ClipboardX11::OnClipboardChanged, 76 base::Unretained(this))); 77 78 base::MessageLoopForIO::current()->WatchFileDescriptor( 79 ConnectionNumber(display_), 80 true, 81 base::MessageLoopForIO::WATCH_READ, 82 &x_connection_watcher_, 83 this); 84 PumpXEvents(); 85} 86 87void ClipboardX11::InjectClipboardEvent( 88 const protocol::ClipboardEvent& event) { 89 x_server_clipboard_.SetClipboard(event.mime_type(), event.data()); 90} 91 92void ClipboardX11::Stop() { 93 client_clipboard_.reset(); 94 x_connection_watcher_.StopWatchingFileDescriptor(); 95 96 if (display_) { 97 XCloseDisplay(display_); 98 display_ = NULL; 99 } 100} 101 102void ClipboardX11::OnFileCanReadWithoutBlocking(int fd) { 103 PumpXEvents(); 104} 105 106void ClipboardX11::OnFileCanWriteWithoutBlocking(int fd) { 107} 108 109void 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); 114 115 if (client_clipboard_.get()) { 116 client_clipboard_->InjectClipboardEvent(event); 117 } 118} 119 120void ClipboardX11::PumpXEvents() { 121 DCHECK(display_); 122 123 while (XPending(display_)) { 124 XEvent event; 125 XNextEvent(display_, &event); 126 x_server_clipboard_.ProcessXEvent(&event); 127 } 128} 129 130scoped_ptr<Clipboard> Clipboard::Create() { 131 return scoped_ptr<Clipboard>(new ClipboardX11()); 132} 133 134} // namespace remoting 135