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) { |
121 // Save the last server timestamp seen from X, to satisfy requests for the | |
122 // TIMESTAMP target later… | |
123 acquired_selection_timestamp_ = | |
124 X11EventSource::GetInstance()->last_seen_server_time(); | |
125 // …but always pass CurrentTime to XSetSelectionOwner to increase the chances | |
126 // of this succeeding. | |
125 XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime); | 127 XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime); |
dcheng
2016/04/20 00:55:26
For whatever reason, using last_seen_server_time()
| |
126 | 128 |
127 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { | 129 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { |
128 // The X server agrees that we are the selection owner. Commit our data. | 130 // The X server agrees that we are the selection owner. Commit our data. |
129 format_map_ = data; | 131 format_map_ = data; |
130 } | 132 } |
131 } | 133 } |
132 | 134 |
133 void SelectionOwner::ClearSelectionOwner() { | 135 void SelectionOwner::ClearSelectionOwner() { |
134 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime); | 136 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime); |
135 format_map_ = SelectionFormatMap(); | 137 format_map_ = SelectionFormatMap(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 if (!it->data.get()) | 214 if (!it->data.get()) |
213 CompleteIncrementalTransfer(it); | 215 CompleteIncrementalTransfer(it); |
214 } | 216 } |
215 | 217 |
216 bool SelectionOwner::ProcessTarget(XAtom target, | 218 bool SelectionOwner::ProcessTarget(XAtom target, |
217 XID requestor, | 219 XID requestor, |
218 XAtom property) { | 220 XAtom property) { |
219 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); | 221 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); |
220 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); | 222 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); |
221 XAtom targets_atom = atom_cache_.GetAtom(kTargets); | 223 XAtom targets_atom = atom_cache_.GetAtom(kTargets); |
224 XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp); | |
222 | 225 |
223 if (target == multiple_atom || target == save_targets_atom) | 226 if (target == multiple_atom || target == save_targets_atom) |
224 return false; | 227 return false; |
225 | 228 |
226 if (target == targets_atom) { | 229 if (target == timestamp_atom) { |
230 XChangeProperty( | |
231 x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace, | |
232 reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1); | |
233 return true; | |
234 } else if (target == targets_atom) { | |
227 // We have been asked for TARGETS. Send an atom array back with the data | 235 // We have been asked for TARGETS. Send an atom array back with the data |
228 // types we support. | 236 // types we support. |
229 std::vector<XAtom> targets; | 237 std::vector<XAtom> targets; |
238 targets.push_back(timestamp_atom); | |
230 targets.push_back(targets_atom); | 239 targets.push_back(targets_atom); |
231 targets.push_back(save_targets_atom); | 240 targets.push_back(save_targets_atom); |
232 targets.push_back(multiple_atom); | 241 targets.push_back(multiple_atom); |
233 RetrieveTargets(&targets); | 242 RetrieveTargets(&targets); |
234 | 243 |
235 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, | 244 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, |
236 PropModeReplace, | 245 PropModeReplace, |
237 reinterpret_cast<unsigned char*>(&targets.front()), | 246 reinterpret_cast<unsigned char*>(&targets.front()), |
238 targets.size()); | 247 targets.size()); |
239 return true; | 248 return true; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 foreign_window_manager_id(foreign_window_manager_id) { | 385 foreign_window_manager_id(foreign_window_manager_id) { |
377 } | 386 } |
378 | 387 |
379 SelectionOwner::IncrementalTransfer::IncrementalTransfer( | 388 SelectionOwner::IncrementalTransfer::IncrementalTransfer( |
380 const IncrementalTransfer& other) = default; | 389 const IncrementalTransfer& other) = default; |
381 | 390 |
382 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { | 391 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { |
383 } | 392 } |
384 | 393 |
385 } // namespace ui | 394 } // namespace ui |
OLD | NEW |