Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Unified Diff: ui/base/x/selection_owner.cc

Issue 1892483005: SelectionOwner: add support for TIMESTAMP target (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/x/selection_owner.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/x/selection_owner.cc
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc
index 170f32e19b2c0ea71e90bdb53e9386c5aea26fb0..8da95c1a915bfeb7b01d1ae268be84010987e9fe 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -22,15 +22,19 @@ const char kIncr[] = "INCR";
const char kMultiple[] = "MULTIPLE";
const char kSaveTargets[] = "SAVE_TARGETS";
const char kTargets[] = "TARGETS";
+const char kTimestamp[] = "TIMESTAMP";
-const char* kAtomsToCache[] = {
- kAtomPair,
- kIncr,
- kMultiple,
- kSaveTargets,
- kTargets,
- NULL
-};
+// Used in conjunction with GetCurrentTimeFromX.
+const char kDummyTimestampProperty[] = "CHROMIUM_TIMESTAMP_PROPERTY";
+
+const char* kAtomsToCache[] = {kAtomPair,
+ kIncr,
+ kMultiple,
+ kSaveTargets,
+ kTargets,
+ kTimestamp,
+ kDummyTimestampProperty,
+ NULL};
// The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <=
// than kIncrementalTransferTimeoutMs.
@@ -53,6 +57,32 @@ size_t GetMaxRequestSize(XDisplay* display) {
std::max(static_cast<long>(0), max_size));
}
+// Get the value of CurrentTime from X. There's no easy way to do this, so like
+// GTK, we do this by triggering a spurious property change and inspecting the
+// resulting event.
+Time GetCurrentTimeFromX(XDisplay* display, XID window, XAtom property) {
+ unsigned char c = 0;
+ XChangeProperty(display, window, property, property, 8, PropModeReplace, &c,
+ 1);
+ struct ArgData {
+ // Target window and atom to wait for.
+ XID window;
+ XAtom atom;
+ } args = {window, property};
+ auto predicate = [](XDisplay* display, XEvent* event, XPointer arg) -> Bool {
+ ArgData* data = reinterpret_cast<ArgData*>(arg);
+ return (event->type == PropertyNotify &&
+ event->xproperty.window == data->window &&
+ event->xproperty.atom == data->atom)
+ ? True
+ : False;
+
+ };
+ XEvent event;
+ XIfEvent(display, &event, predicate, reinterpret_cast<XPointer>(&args));
+ return event.xproperty.time;
sadrul 2016/04/19 16:11:52 How does things break when we use CurrentTime? We
dcheng 2016/04/19 17:24:15 Just using CurrentTime is unlikely to actually res
Elliot Glaysher 2016/04/19 17:30:36 Sadly, I wouldn't rely on that. We currently have
dcheng 2016/04/19 17:44:11 Is the concern here that some other app will XChan
+}
+
// Gets the value of an atom pair array property. On success, true is returned
// and the value is stored in |value|.
bool GetAtomPairArrayProperty(XID window,
@@ -122,7 +152,12 @@ void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
void SelectionOwner::TakeOwnershipOfSelection(
const SelectionFormatMap& data) {
- XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime);
+ // Note that we don't just use CurrentTime, since we need to return an actual
+ // timestamp for the TIMESTAMP target later.
+ acquired_selection_timestamp_ = GetCurrentTimeFromX(
+ x_display_, x_window_, atom_cache_.GetAtom(kDummyTimestampProperty));
+ XSetSelectionOwner(x_display_, selection_name_, x_window_,
+ acquired_selection_timestamp_);
if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) {
// The X server agrees that we are the selection owner. Commit our data.
@@ -219,14 +254,21 @@ bool SelectionOwner::ProcessTarget(XAtom target,
XAtom multiple_atom = atom_cache_.GetAtom(kMultiple);
XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets);
XAtom targets_atom = atom_cache_.GetAtom(kTargets);
+ XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp);
if (target == multiple_atom || target == save_targets_atom)
return false;
- if (target == targets_atom) {
+ if (target == timestamp_atom) {
+ XChangeProperty(
+ x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1);
+ return true;
+ } else if (target == targets_atom) {
// We have been asked for TARGETS. Send an atom array back with the data
// types we support.
std::vector<XAtom> targets;
+ targets.push_back(timestamp_atom);
targets.push_back(targets_atom);
targets.push_back(save_targets_atom);
targets.push_back(multiple_atom);
« no previous file with comments | « ui/base/x/selection_owner.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698