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 #include "ui/base/x/selection_owner.h" | 5 #include "ui/base/x/selection_owner.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "ui/base/x/selection_utils.h" | 12 #include "ui/base/x/selection_utils.h" |
13 #include "ui/base/x/x11_foreign_window_manager.h" | 13 #include "ui/base/x/x11_foreign_window_manager.h" |
14 #include "ui/base/x/x11_util.h" | 14 #include "ui/base/x/x11_util.h" |
| 15 #include "ui/events/platform/x11/x11_event_source.h" |
15 | 16 |
16 namespace ui { | 17 namespace ui { |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 const char kAtomPair[] = "ATOM_PAIR"; | 21 const char kAtomPair[] = "ATOM_PAIR"; |
21 const char kIncr[] = "INCR"; | 22 const char kIncr[] = "INCR"; |
22 const char kMultiple[] = "MULTIPLE"; | 23 const char kMultiple[] = "MULTIPLE"; |
23 const char kSaveTargets[] = "SAVE_TARGETS"; | 24 const char kSaveTargets[] = "SAVE_TARGETS"; |
24 const char kTargets[] = "TARGETS"; | 25 const char kTargets[] = "TARGETS"; |
| 26 const char kTimestamp[] = "TIMESTAMP"; |
25 | 27 |
26 const char* kAtomsToCache[] = { | 28 const char* kAtomsToCache[] = {kAtomPair, kIncr, kMultiple, kSaveTargets, |
27 kAtomPair, | 29 kTargets, kTimestamp, NULL}; |
28 kIncr, | |
29 kMultiple, | |
30 kSaveTargets, | |
31 kTargets, | |
32 NULL | |
33 }; | |
34 | 30 |
35 // The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <= | 31 // The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <= |
36 // than kIncrementalTransferTimeoutMs. | 32 // than kIncrementalTransferTimeoutMs. |
37 const int kTimerPeriodMs = 1000; | 33 const int kTimerPeriodMs = 1000; |
38 | 34 |
39 // The amount of time to wait for the selection requestor to process the data | 35 // The amount of time to wait for the selection requestor to process the data |
40 // sent by the selection owner before aborting an incremental data transfer. | 36 // sent by the selection owner before aborting an incremental data transfer. |
41 const int kIncrementalTransferTimeoutMs = 10000; | 37 const int kIncrementalTransferTimeoutMs = 10000; |
42 | 38 |
43 static_assert(kTimerPeriodMs <= kIncrementalTransferTimeoutMs, | 39 static_assert(kTimerPeriodMs <= kIncrementalTransferTimeoutMs, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 | 111 |
116 void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) { | 112 void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) { |
117 for (SelectionFormatMap::const_iterator it = format_map_.begin(); | 113 for (SelectionFormatMap::const_iterator it = format_map_.begin(); |
118 it != format_map_.end(); ++it) { | 114 it != format_map_.end(); ++it) { |
119 targets->push_back(it->first); | 115 targets->push_back(it->first); |
120 } | 116 } |
121 } | 117 } |
122 | 118 |
123 void SelectionOwner::TakeOwnershipOfSelection( | 119 void SelectionOwner::TakeOwnershipOfSelection( |
124 const SelectionFormatMap& data) { | 120 const SelectionFormatMap& data) { |
125 XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime); | 121 // Note that we don't just use CurrentTime, since we need to return an actual |
| 122 // timestamp for the TIMESTAMP target later. |
| 123 acquired_selection_timestamp_ = |
| 124 X11EventSource::GetInstance()->last_seen_server_time(); |
| 125 XSetSelectionOwner(x_display_, selection_name_, x_window_, |
| 126 acquired_selection_timestamp_); |
126 | 127 |
127 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { | 128 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { |
128 // The X server agrees that we are the selection owner. Commit our data. | 129 // The X server agrees that we are the selection owner. Commit our data. |
129 format_map_ = data; | 130 format_map_ = data; |
130 } | 131 } |
131 } | 132 } |
132 | 133 |
133 void SelectionOwner::ClearSelectionOwner() { | 134 void SelectionOwner::ClearSelectionOwner() { |
134 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime); | 135 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime); |
135 format_map_ = SelectionFormatMap(); | 136 format_map_ = SelectionFormatMap(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 if (!it->data.get()) | 213 if (!it->data.get()) |
213 CompleteIncrementalTransfer(it); | 214 CompleteIncrementalTransfer(it); |
214 } | 215 } |
215 | 216 |
216 bool SelectionOwner::ProcessTarget(XAtom target, | 217 bool SelectionOwner::ProcessTarget(XAtom target, |
217 XID requestor, | 218 XID requestor, |
218 XAtom property) { | 219 XAtom property) { |
219 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); | 220 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); |
220 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); | 221 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); |
221 XAtom targets_atom = atom_cache_.GetAtom(kTargets); | 222 XAtom targets_atom = atom_cache_.GetAtom(kTargets); |
| 223 XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp); |
222 | 224 |
223 if (target == multiple_atom || target == save_targets_atom) | 225 if (target == multiple_atom || target == save_targets_atom) |
224 return false; | 226 return false; |
225 | 227 |
226 if (target == targets_atom) { | 228 if (target == timestamp_atom) { |
| 229 XChangeProperty( |
| 230 x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace, |
| 231 reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1); |
| 232 return true; |
| 233 } else if (target == targets_atom) { |
227 // We have been asked for TARGETS. Send an atom array back with the data | 234 // We have been asked for TARGETS. Send an atom array back with the data |
228 // types we support. | 235 // types we support. |
229 std::vector<XAtom> targets; | 236 std::vector<XAtom> targets; |
| 237 targets.push_back(timestamp_atom); |
230 targets.push_back(targets_atom); | 238 targets.push_back(targets_atom); |
231 targets.push_back(save_targets_atom); | 239 targets.push_back(save_targets_atom); |
232 targets.push_back(multiple_atom); | 240 targets.push_back(multiple_atom); |
233 RetrieveTargets(&targets); | 241 RetrieveTargets(&targets); |
234 | 242 |
235 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, | 243 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, |
236 PropModeReplace, | 244 PropModeReplace, |
237 reinterpret_cast<unsigned char*>(&targets.front()), | 245 reinterpret_cast<unsigned char*>(&targets.front()), |
238 targets.size()); | 246 targets.size()); |
239 return true; | 247 return true; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 foreign_window_manager_id(foreign_window_manager_id) { | 384 foreign_window_manager_id(foreign_window_manager_id) { |
377 } | 385 } |
378 | 386 |
379 SelectionOwner::IncrementalTransfer::IncrementalTransfer( | 387 SelectionOwner::IncrementalTransfer::IncrementalTransfer( |
380 const IncrementalTransfer& other) = default; | 388 const IncrementalTransfer& other) = default; |
381 | 389 |
382 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { | 390 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { |
383 } | 391 } |
384 | 392 |
385 } // namespace ui | 393 } // namespace ui |
OLD | NEW |