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

Side by Side 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: I hate X 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 unified diff | Download patch
« no previous file with comments | « ui/base/x/selection_owner.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 15
16 namespace ui { 16 namespace ui {
17 17
18 namespace { 18 namespace {
19 19
20 const char kAtomPair[] = "ATOM_PAIR"; 20 const char kAtomPair[] = "ATOM_PAIR";
21 const char kIncr[] = "INCR"; 21 const char kIncr[] = "INCR";
22 const char kMultiple[] = "MULTIPLE"; 22 const char kMultiple[] = "MULTIPLE";
23 const char kSaveTargets[] = "SAVE_TARGETS"; 23 const char kSaveTargets[] = "SAVE_TARGETS";
24 const char kTargets[] = "TARGETS"; 24 const char kTargets[] = "TARGETS";
25 const char kTimestamp[] = "TIMESTAMP";
25 26
26 const char* kAtomsToCache[] = { 27 // Used in conjunction with GetCurrentTimeFromX.
27 kAtomPair, 28 const char kDummyTimestampProperty[] = "CHROMIUM_TIMESTAMP_PROPERTY";
28 kIncr, 29
29 kMultiple, 30 const char* kAtomsToCache[] = {kAtomPair,
30 kSaveTargets, 31 kIncr,
31 kTargets, 32 kMultiple,
32 NULL 33 kSaveTargets,
33 }; 34 kTargets,
35 kTimestamp,
36 kDummyTimestampProperty,
37 NULL};
34 38
35 // The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <= 39 // The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <=
36 // than kIncrementalTransferTimeoutMs. 40 // than kIncrementalTransferTimeoutMs.
37 const int kTimerPeriodMs = 1000; 41 const int kTimerPeriodMs = 1000;
38 42
39 // The amount of time to wait for the selection requestor to process the data 43 // 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. 44 // sent by the selection owner before aborting an incremental data transfer.
41 const int kIncrementalTransferTimeoutMs = 10000; 45 const int kIncrementalTransferTimeoutMs = 10000;
42 46
43 static_assert(kTimerPeriodMs <= kIncrementalTransferTimeoutMs, 47 static_assert(kTimerPeriodMs <= kIncrementalTransferTimeoutMs,
44 "timer period must be <= transfer timeout"); 48 "timer period must be <= transfer timeout");
45 49
46 // Returns a conservative max size of the data we can pass into 50 // Returns a conservative max size of the data we can pass into
47 // XChangeProperty(). Copied from GTK. 51 // XChangeProperty(). Copied from GTK.
48 size_t GetMaxRequestSize(XDisplay* display) { 52 size_t GetMaxRequestSize(XDisplay* display) {
49 long extended_max_size = XExtendedMaxRequestSize(display); 53 long extended_max_size = XExtendedMaxRequestSize(display);
50 long max_size = 54 long max_size =
51 (extended_max_size ? extended_max_size : XMaxRequestSize(display)) - 100; 55 (extended_max_size ? extended_max_size : XMaxRequestSize(display)) - 100;
52 return std::min(static_cast<long>(0x40000), 56 return std::min(static_cast<long>(0x40000),
53 std::max(static_cast<long>(0), max_size)); 57 std::max(static_cast<long>(0), max_size));
54 } 58 }
55 59
60 // Get the value of CurrentTime from X. There's no easy way to do this, so like
61 // GTK, we do this by triggering a spurious property change and inspecting the
62 // resulting event.
63 Time GetCurrentTimeFromX(XDisplay* display, XID window, XAtom property) {
64 unsigned char c = 0;
65 XChangeProperty(display, window, property, property, 8, PropModeReplace, &c,
66 1);
67 struct ArgData {
68 // Target window and atom to wait for.
69 XID window;
70 XAtom atom;
71 } args = {window, property};
72 auto predicate = [](XDisplay* display, XEvent* event, XPointer arg) -> Bool {
73 ArgData* data = reinterpret_cast<ArgData*>(arg);
74 return (event->type == PropertyNotify &&
75 event->xproperty.window == data->window &&
76 event->xproperty.atom == data->atom)
77 ? True
78 : False;
79
80 };
81 XEvent event;
82 XIfEvent(display, &event, +predicate, reinterpret_cast<XPointer>(&args));
Elliot Glaysher 2016/04/15 21:45:31 "+" predicate? I assume the unary plus is some sor
dcheng 2016/04/15 21:53:47 I was forcing a decay to function pointer, but it
83 return event.xproperty.time;
84 }
85
56 // Gets the value of an atom pair array property. On success, true is returned 86 // Gets the value of an atom pair array property. On success, true is returned
57 // and the value is stored in |value|. 87 // and the value is stored in |value|.
58 bool GetAtomPairArrayProperty(XID window, 88 bool GetAtomPairArrayProperty(XID window,
59 XAtom property, 89 XAtom property,
60 std::vector<std::pair<XAtom,XAtom> >* value) { 90 std::vector<std::pair<XAtom,XAtom> >* value) {
61 XAtom type = None; 91 XAtom type = None;
62 int format = 0; // size in bits of each item in 'property' 92 int format = 0; // size in bits of each item in 'property'
63 unsigned long num_items = 0; 93 unsigned long num_items = 0;
64 unsigned char* properties = NULL; 94 unsigned char* properties = NULL;
65 unsigned long remaining_bytes = 0; 95 unsigned long remaining_bytes = 0;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 145
116 void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) { 146 void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
117 for (SelectionFormatMap::const_iterator it = format_map_.begin(); 147 for (SelectionFormatMap::const_iterator it = format_map_.begin();
118 it != format_map_.end(); ++it) { 148 it != format_map_.end(); ++it) {
119 targets->push_back(it->first); 149 targets->push_back(it->first);
120 } 150 }
121 } 151 }
122 152
123 void SelectionOwner::TakeOwnershipOfSelection( 153 void SelectionOwner::TakeOwnershipOfSelection(
124 const SelectionFormatMap& data) { 154 const SelectionFormatMap& data) {
125 XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime); 155 // Note that we don't just use CurrentTime, since we need to return an actual
156 // timestamp for the TIMESTAMP target later.
157 acquired_selection_timestamp_ = GetCurrentTimeFromX(
158 x_display_, x_window_, atom_cache_.GetAtom(kDummyTimestampProperty));
159 XSetSelectionOwner(x_display_, selection_name_, x_window_,
160 acquired_selection_timestamp_);
126 161
127 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { 162 if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) {
128 // The X server agrees that we are the selection owner. Commit our data. 163 // The X server agrees that we are the selection owner. Commit our data.
129 format_map_ = data; 164 format_map_ = data;
130 } 165 }
131 } 166 }
132 167
133 void SelectionOwner::ClearSelectionOwner() { 168 void SelectionOwner::ClearSelectionOwner() {
134 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime); 169 XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime);
135 format_map_ = SelectionFormatMap(); 170 format_map_ = SelectionFormatMap();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 if (!it->data.get()) 247 if (!it->data.get())
213 CompleteIncrementalTransfer(it); 248 CompleteIncrementalTransfer(it);
214 } 249 }
215 250
216 bool SelectionOwner::ProcessTarget(XAtom target, 251 bool SelectionOwner::ProcessTarget(XAtom target,
217 XID requestor, 252 XID requestor,
218 XAtom property) { 253 XAtom property) {
219 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); 254 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple);
220 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); 255 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets);
221 XAtom targets_atom = atom_cache_.GetAtom(kTargets); 256 XAtom targets_atom = atom_cache_.GetAtom(kTargets);
257 XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp);
222 258
223 if (target == multiple_atom || target == save_targets_atom) 259 if (target == multiple_atom || target == save_targets_atom)
224 return false; 260 return false;
225 261
226 if (target == targets_atom) { 262 if (target == timestamp_atom) {
263 XChangeProperty(
264 x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace,
265 reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1);
266 return true;
267 } else if (target == targets_atom) {
227 // We have been asked for TARGETS. Send an atom array back with the data 268 // We have been asked for TARGETS. Send an atom array back with the data
228 // types we support. 269 // types we support.
229 std::vector<XAtom> targets; 270 std::vector<XAtom> targets;
271 targets.push_back(timestamp_atom);
230 targets.push_back(targets_atom); 272 targets.push_back(targets_atom);
231 targets.push_back(save_targets_atom); 273 targets.push_back(save_targets_atom);
232 targets.push_back(multiple_atom); 274 targets.push_back(multiple_atom);
233 RetrieveTargets(&targets); 275 RetrieveTargets(&targets);
234 276
235 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, 277 XChangeProperty(x_display_, requestor, property, XA_ATOM, 32,
236 PropModeReplace, 278 PropModeReplace,
237 reinterpret_cast<unsigned char*>(&targets.front()), 279 reinterpret_cast<unsigned char*>(&targets.front()),
238 targets.size()); 280 targets.size());
239 return true; 281 return true;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 foreign_window_manager_id(foreign_window_manager_id) { 418 foreign_window_manager_id(foreign_window_manager_id) {
377 } 419 }
378 420
379 SelectionOwner::IncrementalTransfer::IncrementalTransfer( 421 SelectionOwner::IncrementalTransfer::IncrementalTransfer(
380 const IncrementalTransfer& other) = default; 422 const IncrementalTransfer& other) = default;
381 423
382 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { 424 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() {
383 } 425 }
384 426
385 } // namespace ui 427 } // namespace ui
OLDNEW
« 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