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)// Don't include this file from any .h files because it pulls in some X headers. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xatom.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class to allow manipulation of the X clipboard, using only X API calls. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is not thread-safe, so all its methods must be called on the 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// application's main event-processing thread. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XServerClipboard { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called when new clipboard data has been received from the owner of the X 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // selection (primary or clipboard). 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |mime_type| is the MIME type associated with the data. This will be one of 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the types listed in remoting/base/constants.h. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |data| is the clipboard data from the associated X event, encoded with the 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // specified MIME-type. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef base::Callback<void(const std::string& mime_type, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data)> 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClipboardChangedCallback; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XServerClipboard(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XServerClipboard(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start monitoring |display|'s selections, and invoke |callback| whenever 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their content changes. The caller must ensure |display| is still valid 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whenever any other methods are called on this object. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Init(Display* display, const ClipboardChangedCallback& callback); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy data to the X Clipboard. This acquires ownership of the 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PRIMARY and CLIPBOARD selections. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetClipboard(const std::string& mime_type, const std::string& data); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process |event| if it is an X selection notification. The caller should 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invoke this for every event it receives from |display|. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ProcessXEvent(XEvent* event); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Handlers called by ProcessXEvent() for each event type. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSetSelectionOwnerNotify(Atom selection, Time timestamp); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnPropertyNotify(XEvent* event); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSelectionNotify(XEvent* event); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSelectionRequest(XEvent* event); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSelectionClear(XEvent* event); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used by OnSelectionRequest() to respond to requests for details of our 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // clipboard content. This is done by changing the property |property| of the 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |requestor| window (these values come from the XSelectionRequestEvent). 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |target| must be a string type (STRING or UTF8_STRING). 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SendTargetsResponse(Window requestor, Atom property); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SendTimestampResponse(Window requestor, Atom property); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SendStringResponse(Window requestor, Atom property, Atom target); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called by OnSelectionNotify() when the selection owner has replied to a 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // request for information about a selection. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |event| is the raw X event from the notification. 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |type|, |format| etc are the results from XGetWindowProperty(), or 0 if 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // there is no associated data. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleSelectionNotify(XSelectionEvent* event, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int item_count, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* data); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These methods return true if selection processing is complete, false 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // otherwise. They are called from HandleSelectionNotify(), and take the same 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // arguments. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HandleSelectionTargetsEvent(XSelectionEvent* event, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int item_count, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* data); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HandleSelectionStringEvent(XSelectionEvent* event, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int item_count, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* data); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the registered callback of new clipboard text. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyClipboardText(const std::string& text); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These methods trigger the X server or selection owner to send back an 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // event containing the requested information. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RequestSelectionTargets(Atom selection); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RequestSelectionString(Atom selection, Atom target); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assert ownership of the specified |selection|. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AssertSelectionOwnership(Atom selection); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsSelectionOwner(Atom selection); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stores the Display* supplied to Init(). 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display_; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Window through which clipboard events are received, or BadValue if the 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // window could not be created. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window clipboard_window_; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The event base returned by XFixesQueryExtension(). If XFixes is 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // unavailable, the clipboard window will not be created, and no 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // event-processing will take place. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int xfixes_event_base_; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cached atoms for various strings, initialized during Init(). 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom clipboard_atom_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom large_selection_atom_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom selection_string_atom_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom targets_atom_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom timestamp_atom_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom utf8_string_atom_; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The set of X selections owned by |clipboard_window_| (can be Primary or 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clipboard or both). 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<Atom> selections_owned_; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clipboard content to return to other applications when |clipboard_window_| 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // owns a selection. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data_; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stores the property to use for large transfers, or None if a large 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // transfer is not currently in-progress. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom large_selection_property_; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remembers the start time of selection processing, and is set to null when 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // processing is complete. This is used to decide whether to begin processing 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a new selection or continue with the current selection. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks get_selections_time_; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |callback| argument supplied to Init(). 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClipboardChangedCallback callback_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XServerClipboard); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_ 150