Chromium Code Reviews| 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 |