OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef UI_BASE_X_SELECTION_REQUESTOR_H_ | 5 #ifndef UI_BASE_X_SELECTION_REQUESTOR_H_ |
6 #define UI_BASE_X_SELECTION_REQUESTOR_H_ | 6 #define UI_BASE_X_SELECTION_REQUESTOR_H_ |
7 | 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> | 8 #include <vector> |
15 | 9 |
16 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
17 #include "base/callback.h" | 11 #include "base/callback.h" |
18 #include "base/event_types.h" | 12 #include "base/event_types.h" |
19 #include "base/memory/ref_counted_memory.h" | 13 #include "base/memory/ref_counted_memory.h" |
| 14 #include "base/time/time.h" |
| 15 #include "base/timer/timer.h" |
20 #include "ui/base/ui_base_export.h" | 16 #include "ui/base/ui_base_export.h" |
21 #include "ui/gfx/x/x11_atom_cache.h" | 17 #include "ui/gfx/x/x11_atom_cache.h" |
22 #include "ui/gfx/x/x11_types.h" | 18 #include "ui/gfx/x/x11_types.h" |
23 | 19 |
24 namespace ui { | 20 namespace ui { |
25 class PlatformEventDispatcher; | 21 class PlatformEventDispatcher; |
26 class SelectionData; | 22 class SelectionData; |
27 | 23 |
28 // Requests and later receives data from the X11 server through the selection | 24 // Requests and later receives data from the X11 server through the selection |
29 // system. | 25 // system. |
30 // | 26 // |
31 // X11 uses a system called "selections" to implement clipboards and drag and | 27 // X11 uses a system called "selections" to implement clipboards and drag and |
32 // drop. This class interprets messages from the statefull selection request | 28 // drop. This class interprets messages from the stateful selection request |
33 // API. SelectionRequestor should only deal with the X11 details; it does not | 29 // API. SelectionRequestor should only deal with the X11 details; it does not |
34 // implement per-component fast-paths. | 30 // implement per-component fast-paths. |
35 class UI_BASE_EXPORT SelectionRequestor { | 31 class UI_BASE_EXPORT SelectionRequestor { |
36 public: | 32 public: |
37 SelectionRequestor(XDisplay* xdisplay, | 33 SelectionRequestor(XDisplay* xdisplay, |
38 XID xwindow, | 34 XID xwindow, |
39 XAtom selection_name, | |
40 PlatformEventDispatcher* dispatcher); | 35 PlatformEventDispatcher* dispatcher); |
41 ~SelectionRequestor(); | 36 ~SelectionRequestor(); |
42 | 37 |
43 // Does the work of requesting |target| from the selection we handle, | 38 // Does the work of requesting |target| from |selection|, spinning up the |
44 // spinning up the nested message loop, and reading the resulting data | 39 // nested message loop, and reading the resulting data back. The result is |
45 // back. The result is stored in |out_data|. | 40 // stored in |out_data|. |
46 // |out_data_items| is the length of |out_data| in |out_type| items. | 41 // |out_data_items| is the length of |out_data| in |out_type| items. |
47 bool PerformBlockingConvertSelection( | 42 bool PerformBlockingConvertSelection( |
| 43 XAtom selection, |
48 XAtom target, | 44 XAtom target, |
49 scoped_refptr<base::RefCountedMemory>* out_data, | 45 scoped_refptr<base::RefCountedMemory>* out_data, |
50 size_t* out_data_items, | 46 size_t* out_data_items, |
51 XAtom* out_type); | 47 XAtom* out_type); |
52 | 48 |
53 // Requests |target| from the selection that we handle, passing |parameter| | 49 // Requests |target| from |selection|, passing |parameter| as a parameter to |
54 // as a parameter to XConvertSelection(). | 50 // XConvertSelection(). |
55 void PerformBlockingConvertSelectionWithParameter( | 51 void PerformBlockingConvertSelectionWithParameter( |
| 52 XAtom selection, |
56 XAtom target, | 53 XAtom target, |
57 const std::vector<XAtom>& parameter); | 54 const std::vector<XAtom>& parameter); |
58 | 55 |
59 // Returns the first of |types| offered by the current selection holder, or | 56 // Returns the first of |types| offered by the current owner of |selection|. |
60 // returns NULL if none of those types are available. | 57 // Returns an empty SelectionData object if none of |types| are available. |
61 SelectionData RequestAndWaitForTypes(const std::vector<XAtom>& types); | 58 SelectionData RequestAndWaitForTypes(XAtom selection, |
| 59 const std::vector<XAtom>& types); |
62 | 60 |
63 // It is our owner's responsibility to plumb X11 SelectionNotify events on | 61 // It is our owner's responsibility to plumb X11 SelectionNotify events on |
64 // |xwindow_| to us. | 62 // |xwindow_| to us. |
65 void OnSelectionNotify(const XEvent& event); | 63 void OnSelectionNotify(const XEvent& event); |
66 | 64 |
67 private: | 65 private: |
68 // A request that has been issued and we are waiting for a response to. | 66 friend class SelectionRequestorTest; |
69 struct PendingRequest { | |
70 explicit PendingRequest(XAtom target); | |
71 ~PendingRequest(); | |
72 | 67 |
73 // Data to the current XConvertSelection request. Used for error detection; | 68 // A request that has been issued. |
74 // we verify it on the return message. | 69 struct Request { |
| 70 Request(XAtom selection, XAtom target, base::TimeTicks timeout); |
| 71 ~Request(); |
| 72 |
| 73 // The target and selection requested in the XConvertSelection() request. |
| 74 // Used for error detection. |
| 75 XAtom selection; |
75 XAtom target; | 76 XAtom target; |
76 | 77 |
| 78 // The result data for the XConvertSelection() request. |
| 79 scoped_refptr<base::RefCountedMemory> out_data; |
| 80 size_t out_data_items; |
| 81 XAtom out_type; |
| 82 |
| 83 // Whether the XConvertSelection() request was successful. |
| 84 bool success; |
| 85 |
| 86 // The time when the request should be aborted. |
| 87 base::TimeTicks timeout; |
| 88 |
77 // Called to terminate the nested message loop. | 89 // Called to terminate the nested message loop. |
78 base::Closure quit_closure; | 90 base::Closure quit_closure; |
79 | 91 |
80 // The property in the returning SelectNotify message is used to signal | 92 // True if the request is complete. |
81 // success. If None, our request failed somehow. If equal to the property | 93 bool completed; |
82 // atom that we sent in the XConvertSelection call, we can read that | 94 }; |
83 // property on |x_window_| for the requested data. | |
84 XAtom returned_property; | |
85 | 95 |
86 // Set to true when return_property is populated. | 96 // Aborts requests which have timed out. |
87 bool returned; | 97 void AbortStaleRequests(); |
88 }; | 98 |
| 99 // Mark |request| as completed. If the current request is completed, converts |
| 100 // the selection for the next request. |
| 101 void CompleteRequest(size_t index); |
| 102 |
| 103 // Converts the selection for the request at |current_request_index_|. |
| 104 void ConvertSelectionForCurrentRequest(); |
89 | 105 |
90 // Blocks till SelectionNotify is received for the target specified in | 106 // Blocks till SelectionNotify is received for the target specified in |
91 // |request|. | 107 // |request|. |
92 void BlockTillSelectionNotifyForRequest(PendingRequest* request); | 108 void BlockTillSelectionNotifyForRequest(Request* request); |
| 109 |
| 110 // Returns the request at |current_request_index_| or NULL if there isn't any. |
| 111 Request* GetCurrentRequest(); |
93 | 112 |
94 // Our X11 state. | 113 // Our X11 state. |
95 XDisplay* x_display_; | 114 XDisplay* x_display_; |
96 XID x_window_; | 115 XID x_window_; |
97 | 116 |
98 // The X11 selection that this instance communicates on. | 117 // The property on |x_window_| set by the selection owner with the value of |
99 XAtom selection_name_; | 118 // the selection. |
| 119 XAtom x_property_; |
100 | 120 |
101 // Dispatcher which handles SelectionNotify and SelectionRequest for | 121 // Dispatcher which handles SelectionNotify and SelectionRequest for |
102 // |selection_name_|. PerformBlockingConvertSelection() calls the | 122 // |selection_name_|. PerformBlockingConvertSelection() calls the |
103 // dispatcher directly if PerformBlockingConvertSelection() is called after | 123 // dispatcher directly if PerformBlockingConvertSelection() is called after |
104 // the PlatformEventSource is destroyed. | 124 // the PlatformEventSource is destroyed. |
105 // Not owned. | 125 // Not owned. |
106 PlatformEventDispatcher* dispatcher_; | 126 PlatformEventDispatcher* dispatcher_; |
107 | 127 |
108 // A list of requests for which we are waiting for responses. | 128 // In progress requests. Requests are added to the list at the start of |
109 std::list<PendingRequest*> pending_requests_; | 129 // PerformBlockingConvertSelection() and are removed and destroyed right |
| 130 // before the method terminates. |
| 131 std::vector<Request*> requests_; |
| 132 |
| 133 // The index of the currently active request in |requests_|. The active |
| 134 // request is the request for which XConvertSelection() has been |
| 135 // called and for which we are waiting for a SelectionNotify response. |
| 136 size_t current_request_index_; |
| 137 |
| 138 base::RepeatingTimer<SelectionRequestor> abort_timer_; |
110 | 139 |
111 X11AtomCache atom_cache_; | 140 X11AtomCache atom_cache_; |
112 | 141 |
113 DISALLOW_COPY_AND_ASSIGN(SelectionRequestor); | 142 DISALLOW_COPY_AND_ASSIGN(SelectionRequestor); |
114 }; | 143 }; |
115 | 144 |
116 } // namespace ui | 145 } // namespace ui |
117 | 146 |
118 #endif // UI_BASE_X_SELECTION_REQUESTOR_H_ | 147 #endif // UI_BASE_X_SELECTION_REQUESTOR_H_ |
OLD | NEW |