1 // Copyright (c) 2013 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 #ifndef UI_BASE_X_SELECTION_REQUESTOR_H_ 6 #define UI_BASE_X_SELECTION_REQUESTOR_H_ 7 8 #include <X11/Xlib.h> 9 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. 11 #undef RootWindow 12 13 #include <list> 14 #include <vector> 15 16 #include "base/basictypes.h" 17 #include "base/callback.h" 18 #include "base/memory/ref_counted_memory.h" 19 #include "ui/base/ui_base_export.h" 20 #include "ui/gfx/x/x11_atom_cache.h" 21 22 namespace ui { 23 class PlatformEventDispatcher; 24 class SelectionData; 25 26 // Requests and later receives data from the X11 server through the selection 27 // system. 28 // 29 // X11 uses a system called "selections" to implement clipboards and drag and 30 // drop. This class interprets messages from the statefull selection request 31 // API. SelectionRequestor should only deal with the X11 details; it does not 32 // implement per-component fast-paths. 33 class UI_BASE_EXPORT SelectionRequestor { 34 public: 35 SelectionRequestor(Display* xdisplay, 36 ::Window xwindow, 37 ::Atom selection_name, 38 PlatformEventDispatcher* dispatcher); 39 ~SelectionRequestor(); 40 41 // Does the work of requesting |target| from the selection we handle, 42 // spinning up the nested message loop, and reading the resulting data 43 // back. |out_data| is allocated with the X allocator and must be freed with 44 // XFree(). |out_data_bytes| is the length in machine chars, while 45 // |out_data_items| is the length in |out_type| items. 46 bool PerformBlockingConvertSelection( 47 ::Atom target, 48 scoped_refptr<base::RefCountedMemory>* out_data, 49 size_t* out_data_bytes, 50 size_t* out_data_items, 51 ::Atom* out_type); 52 53 // Requests |target| from the selection that we handle, passing |parameter| 54 // as a parameter to XConvertSelection(). 55 void PerformBlockingConvertSelectionWithParameter( 56 ::Atom target, 57 const std::vector< ::Atom>& parameter); 58 59 // Returns the first of |types| offered by the current selection holder, or 60 // returns NULL if none of those types are available. 61 SelectionData RequestAndWaitForTypes(const std::vector< ::Atom>& types); 62 63 // It is our owner's responsibility to plumb X11 SelectionNotify events on 64 // |xwindow_| to us. 65 void OnSelectionNotify(const XSelectionEvent& event); 66 67 private: 68 // A request that has been issued and we are waiting for a response to. 69 struct PendingRequest { 70 explicit PendingRequest(Atom target); 71 ~PendingRequest(); 72 73 // Data to the current XConvertSelection request. Used for error detection; 74 // we verify it on the return message. 75 ::Atom target; 76 77 // Called to terminate the nested message loop. 78 base::Closure quit_closure; 79 80 // The property in the returning SelectNotify message is used to signal 81 // success. If None, our request failed somehow. If equal to the property 82 // atom that we sent in the XConvertSelection call, we can read that 83 // property on |x_window_| for the requested data. 84 ::Atom returned_property; 85 86 // Set to true when return_property is populated. 87 bool returned; 88 }; 89 90 // Blocks till SelectionNotify is received for the target specified in 91 // |request|. 92 void BlockTillSelectionNotifyForRequest(PendingRequest* request); 93 94 // Our X11 state. 95 Display* x_display_; 96 ::Window x_window_; 97 98 // The X11 selection that this instance communicates on. 99 ::Atom selection_name_; 100 101 // Dispatcher which handles SelectionNotify and SelectionRequest for 102 // |selection_name_|. PerformBlockingConvertSelection() calls the 103 // dispatcher directly if PerformBlockingConvertSelection() is called after 104 // the PlatformEventSource is destroyed. 105 // Not owned. 106 PlatformEventDispatcher* dispatcher_; 107 108 // A list of requests for which we are waiting for responses. 109 std::list<PendingRequest*> pending_requests_; 110 111 X11AtomCache atom_cache_; 112 113 DISALLOW_COPY_AND_ASSIGN(SelectionRequestor); 114 }; 115 116 } // namespace ui 117 118 #endif // UI_BASE_X_SELECTION_REQUESTOR_H_ 119