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 "base/memory/ptr_util.h" | |
12 #include "ui/base/x/selection_utils.h" | 13 #include "ui/base/x/selection_utils.h" |
13 #include "ui/base/x/x11_util.h" | 14 #include "ui/base/x/x11_util.h" |
14 #include "ui/base/x/x11_window_event_manager.h" | 15 #include "ui/base/x/x11_window_event_manager.h" |
15 #include "ui/events/platform/x11/x11_event_source.h" | 16 #include "ui/events/platform/x11/x11_event_source.h" |
16 | 17 |
17 namespace ui { | 18 namespace ui { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 const char kAtomPair[] = "ATOM_PAIR"; | 22 const char kAtomPair[] = "ATOM_PAIR"; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 // TODO(erg): If we receive a SelectionClear event while we're handling data, | 195 // TODO(erg): If we receive a SelectionClear event while we're handling data, |
195 // we need to delay clearing. | 196 // we need to delay clearing. |
196 } | 197 } |
197 | 198 |
198 bool SelectionOwner::CanDispatchPropertyEvent(const XEvent& event) { | 199 bool SelectionOwner::CanDispatchPropertyEvent(const XEvent& event) { |
199 return event.xproperty.state == PropertyDelete && | 200 return event.xproperty.state == PropertyDelete && |
200 FindIncrementalTransferForEvent(event) != incremental_transfers_.end(); | 201 FindIncrementalTransferForEvent(event) != incremental_transfers_.end(); |
201 } | 202 } |
202 | 203 |
203 void SelectionOwner::OnPropertyEvent(const XEvent& event) { | 204 void SelectionOwner::OnPropertyEvent(const XEvent& event) { |
204 std::vector<IncrementalTransfer>::iterator it = | 205 IncrementalTransferIt it = FindIncrementalTransferForEvent(event); |
205 FindIncrementalTransferForEvent(event); | |
206 if (it == incremental_transfers_.end()) | 206 if (it == incremental_transfers_.end()) |
207 return; | 207 return; |
208 | 208 |
209 ProcessIncrementalTransfer(&(*it)); | 209 IncrementalTransfer* incremental_transfer = (*it).get(); |
dcheng
2017/02/17 07:42:13
Does it->get() work?
pkotwicz
2017/02/17 19:19:07
Yes it does :) Thank you!
| |
210 if (!it->data.get()) | 210 ProcessIncrementalTransfer(incremental_transfer); |
211 if (!incremental_transfer->data.get()) | |
211 CompleteIncrementalTransfer(it); | 212 CompleteIncrementalTransfer(it); |
212 } | 213 } |
213 | 214 |
214 bool SelectionOwner::ProcessTarget(XAtom target, | 215 bool SelectionOwner::ProcessTarget(XAtom target, |
215 XID requestor, | 216 XID requestor, |
216 XAtom property) { | 217 XAtom property) { |
217 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); | 218 XAtom multiple_atom = atom_cache_.GetAtom(kMultiple); |
218 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); | 219 XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets); |
219 XAtom targets_atom = atom_cache_.GetAtom(kTargets); | 220 XAtom targets_atom = atom_cache_.GetAtom(kTargets); |
220 XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp); | 221 XAtom timestamp_atom = atom_cache_.GetAtom(kTimestamp); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 PropModeReplace, | 263 PropModeReplace, |
263 reinterpret_cast<unsigned char*>(&length), | 264 reinterpret_cast<unsigned char*>(&length), |
264 1); | 265 1); |
265 | 266 |
266 // Wait for the selection requestor to indicate that it has processed | 267 // Wait for the selection requestor to indicate that it has processed |
267 // the selection result before sending the first chunk of data. The | 268 // the selection result before sending the first chunk of data. The |
268 // selection requestor indicates this by deleting |property|. | 269 // selection requestor indicates this by deleting |property|. |
269 base::TimeTicks timeout = | 270 base::TimeTicks timeout = |
270 base::TimeTicks::Now() + | 271 base::TimeTicks::Now() + |
271 base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs); | 272 base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs); |
272 requestor_events_.reset( | 273 std::unique_ptr<IncrementalTransfer> incremental_transfer( |
273 new ui::XScopedEventSelector(requestor, PropertyChangeMask)); | 274 new IncrementalTransfer(requestor, target, property, |
274 incremental_transfers_.push_back(IncrementalTransfer( | 275 base::WrapUnique(new XScopedEventSelector( |
dcheng
2017/02/17 07:42:13
Nit: base::MakeUnique
pkotwicz
2017/02/17 19:19:07
Done.
| |
275 requestor, target, property, it->second, 0, timeout)); | 276 requestor, PropertyChangeMask)), |
277 it->second, 0, timeout)); | |
278 incremental_transfers_.push_back(std::move(incremental_transfer)); | |
276 | 279 |
277 // Start a timer to abort the data transfer in case that the selection | 280 // Start a timer to abort the data transfer in case that the selection |
278 // requestor does not support the INCR property or gets destroyed during | 281 // requestor does not support the INCR property or gets destroyed during |
279 // the data transfer. | 282 // the data transfer. |
280 if (!incremental_transfer_abort_timer_.IsRunning()) { | 283 if (!incremental_transfer_abort_timer_.IsRunning()) { |
281 incremental_transfer_abort_timer_.Start( | 284 incremental_transfer_abort_timer_.Start( |
282 FROM_HERE, | 285 FROM_HERE, |
283 base::TimeDelta::FromMilliseconds(kTimerPeriodMs), | 286 base::TimeDelta::FromMilliseconds(kTimerPeriodMs), |
284 this, | 287 this, |
285 &SelectionOwner::AbortStaleIncrementalTransfers); | 288 &SelectionOwner::AbortStaleIncrementalTransfers); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
324 // transfer->data once the zero-sized chunk is sent to indicate that state | 327 // transfer->data once the zero-sized chunk is sent to indicate that state |
325 // related to this data transfer can be cleared. | 328 // related to this data transfer can be cleared. |
326 if (chunk_length == 0) | 329 if (chunk_length == 0) |
327 transfer->data = NULL; | 330 transfer->data = NULL; |
328 } | 331 } |
329 | 332 |
330 void SelectionOwner::AbortStaleIncrementalTransfers() { | 333 void SelectionOwner::AbortStaleIncrementalTransfers() { |
331 base::TimeTicks now = base::TimeTicks::Now(); | 334 base::TimeTicks now = base::TimeTicks::Now(); |
332 for (int i = static_cast<int>(incremental_transfers_.size()) - 1; | 335 for (int i = static_cast<int>(incremental_transfers_.size()) - 1; |
333 i >= 0; --i) { | 336 i >= 0; --i) { |
334 if (incremental_transfers_[i].timeout <= now) | 337 if (incremental_transfers_[i]->timeout <= now) |
335 CompleteIncrementalTransfer(incremental_transfers_.begin() + i); | 338 CompleteIncrementalTransfer(incremental_transfers_.begin() + i); |
336 } | 339 } |
337 } | 340 } |
338 | 341 |
339 void SelectionOwner::CompleteIncrementalTransfer( | 342 void SelectionOwner::CompleteIncrementalTransfer(IncrementalTransferIt it) { |
340 std::vector<IncrementalTransfer>::iterator it) { | |
341 requestor_events_.reset(); | |
dcheng
2017/02/17 07:42:13
Is it possible to just only reset this when transf
pkotwicz
2017/02/17 19:19:07
Unfortunately, there may be multiple requesting ap
| |
342 | |
343 incremental_transfers_.erase(it); | 343 incremental_transfers_.erase(it); |
344 | 344 |
345 if (incremental_transfers_.empty()) | 345 if (incremental_transfers_.empty()) |
346 incremental_transfer_abort_timer_.Stop(); | 346 incremental_transfer_abort_timer_.Stop(); |
347 } | 347 } |
348 | 348 |
349 std::vector<SelectionOwner::IncrementalTransfer>::iterator | 349 SelectionOwner::IncrementalTransferIt |
350 SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) { | 350 SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) { |
351 for (std::vector<IncrementalTransfer>::iterator it = | 351 for (IncrementalTransferIt it = incremental_transfers_.begin(); |
352 incremental_transfers_.begin(); | 352 it != incremental_transfers_.end(); ++it) { |
353 it != incremental_transfers_.end(); | 353 IncrementalTransfer* incremental_transfer = (*it).get(); |
dcheng
2017/02/17 07:42:13
Nit: Does it->get() work?
pkotwicz
2017/02/17 19:19:07
Done.
| |
354 ++it) { | 354 if (incremental_transfer->window == event.xproperty.window && |
355 if (it->window == event.xproperty.window && | 355 incremental_transfer->property == event.xproperty.atom) { |
356 it->property == event.xproperty.atom) { | |
357 return it; | 356 return it; |
358 } | 357 } |
359 } | 358 } |
360 return incremental_transfers_.end(); | 359 return incremental_transfers_.end(); |
361 } | 360 } |
362 | 361 |
363 SelectionOwner::IncrementalTransfer::IncrementalTransfer( | 362 SelectionOwner::IncrementalTransfer::IncrementalTransfer( |
364 XID window, | 363 XID window, |
365 XAtom target, | 364 XAtom target, |
366 XAtom property, | 365 XAtom property, |
366 std::unique_ptr<XScopedEventSelector> event_selector, | |
367 const scoped_refptr<base::RefCountedMemory>& data, | 367 const scoped_refptr<base::RefCountedMemory>& data, |
368 int offset, | 368 int offset, |
369 base::TimeTicks timeout) | 369 base::TimeTicks timeout) |
370 : window(window), | 370 : window(window), |
371 target(target), | 371 target(target), |
372 property(property), | 372 property(property), |
373 event_selector(std::move(event_selector)), | |
373 data(data), | 374 data(data), |
374 offset(offset), | 375 offset(offset), |
375 timeout(timeout) {} | 376 timeout(timeout) {} |
376 | 377 |
377 SelectionOwner::IncrementalTransfer::IncrementalTransfer( | |
378 const IncrementalTransfer& other) = default; | |
379 | |
380 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { | 378 SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { |
381 } | 379 } |
382 | 380 |
383 } // namespace ui | 381 } // namespace ui |
OLD | NEW |