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

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: USE_GLIB 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') | ui/events/platform/x11/x11_event_source.h » ('j') | 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..e6651f0b814dec70abddccff23f808c41171a0c0 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -12,6 +12,7 @@
#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_foreign_window_manager.h"
#include "ui/base/x/x11_util.h"
+#include "ui/events/platform/x11/x11_event_source.h"
namespace ui {
@@ -22,15 +23,10 @@ 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
-};
+const char* kAtomsToCache[] = {kAtomPair, kIncr, kMultiple, kSaveTargets,
+ kTargets, kTimestamp, NULL};
// The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <=
// than kIncrementalTransferTimeoutMs.
@@ -122,6 +118,12 @@ void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
void SelectionOwner::TakeOwnershipOfSelection(
const SelectionFormatMap& data) {
+ // Save the last server timestamp seen from X, to satisfy requests for the
+ // TIMESTAMP target later…
+ acquired_selection_timestamp_ =
+ X11EventSource::GetInstance()->last_seen_server_time();
+ // …but always pass CurrentTime to XSetSelectionOwner to increase the chances
+ // of this succeeding.
XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime);
if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) {
@@ -219,14 +221,23 @@ 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 == timestamp_atom) {
+ XChangeProperty(
+ x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1);
+ return true;
+ }
+
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);
@@ -237,68 +248,69 @@ bool SelectionOwner::ProcessTarget(XAtom target,
reinterpret_cast<unsigned char*>(&targets.front()),
targets.size());
return true;
- } else {
- // Try to find the data type in map.
- SelectionFormatMap::const_iterator it = format_map_.find(target);
- if (it != format_map_.end()) {
- if (it->second->size() > max_request_size_) {
- // We must send the data back in several chunks due to a limitation in
- // the size of X requests. Notify the selection requestor that the data
- // will be sent incrementally by returning data of type "INCR".
- long length = it->second->size();
- XChangeProperty(x_display_,
- requestor,
- property,
- atom_cache_.GetAtom(kIncr),
- 32,
- PropModeReplace,
- reinterpret_cast<unsigned char*>(&length),
- 1);
-
- // Wait for the selection requestor to indicate that it has processed
- // the selection result before sending the first chunk of data. The
- // selection requestor indicates this by deleting |property|.
- base::TimeTicks timeout =
- base::TimeTicks::Now() +
- base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs);
- int foreign_window_manager_id =
- ui::XForeignWindowManager::GetInstance()->RequestEvents(
- requestor, PropertyChangeMask);
- incremental_transfers_.push_back(
- IncrementalTransfer(requestor,
- target,
- property,
- it->second,
- 0,
- timeout,
- foreign_window_manager_id));
-
- // Start a timer to abort the data transfer in case that the selection
- // requestor does not support the INCR property or gets destroyed during
- // the data transfer.
- if (!incremental_transfer_abort_timer_.IsRunning()) {
- incremental_transfer_abort_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kTimerPeriodMs),
- this,
- &SelectionOwner::AbortStaleIncrementalTransfers);
- }
- } else {
- XChangeProperty(
- x_display_,
- requestor,
- property,
- target,
- 8,
- PropModeReplace,
- const_cast<unsigned char*>(it->second->front()),
- it->second->size());
+ }
+
+ // Try to find the data type in map.
+ SelectionFormatMap::const_iterator it = format_map_.find(target);
+ if (it != format_map_.end()) {
+ if (it->second->size() > max_request_size_) {
+ // We must send the data back in several chunks due to a limitation in
+ // the size of X requests. Notify the selection requestor that the data
+ // will be sent incrementally by returning data of type "INCR".
+ long length = it->second->size();
+ XChangeProperty(x_display_,
+ requestor,
+ property,
+ atom_cache_.GetAtom(kIncr),
+ 32,
+ PropModeReplace,
+ reinterpret_cast<unsigned char*>(&length),
+ 1);
+
+ // Wait for the selection requestor to indicate that it has processed
+ // the selection result before sending the first chunk of data. The
+ // selection requestor indicates this by deleting |property|.
+ base::TimeTicks timeout =
+ base::TimeTicks::Now() +
+ base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs);
+ int foreign_window_manager_id =
+ ui::XForeignWindowManager::GetInstance()->RequestEvents(
+ requestor, PropertyChangeMask);
+ incremental_transfers_.push_back(
+ IncrementalTransfer(requestor,
+ target,
+ property,
+ it->second,
+ 0,
+ timeout,
+ foreign_window_manager_id));
+
+ // Start a timer to abort the data transfer in case that the selection
+ // requestor does not support the INCR property or gets destroyed during
+ // the data transfer.
+ if (!incremental_transfer_abort_timer_.IsRunning()) {
+ incremental_transfer_abort_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kTimerPeriodMs),
+ this,
+ &SelectionOwner::AbortStaleIncrementalTransfers);
}
- return true;
+ } else {
+ XChangeProperty(
+ x_display_,
+ requestor,
+ property,
+ target,
+ 8,
+ PropModeReplace,
+ const_cast<unsigned char*>(it->second->front()),
+ it->second->size());
}
- // I would put error logging here, but GTK ignores TARGETS and spams us
- // looking for its own internal types.
+ return true;
}
+
+ // I would put error logging here, but GTK ignores TARGETS and spams us
+ // looking for its own internal types.
return false;
}
« no previous file with comments | « ui/base/x/selection_owner.h ('k') | ui/events/platform/x11/x11_event_source.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698