summaryrefslogtreecommitdiff
path: root/chromium/ui/base/clipboard/clipboard_x11.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/base/clipboard/clipboard_x11.cc')
-rw-r--r--chromium/ui/base/clipboard/clipboard_x11.cc337
1 files changed, 154 insertions, 183 deletions
diff --git a/chromium/ui/base/clipboard/clipboard_x11.cc b/chromium/ui/base/clipboard/clipboard_x11.cc
index 95e2caff21a..c2f3620584b 100644
--- a/chromium/ui/base/clipboard/clipboard_x11.cc
+++ b/chromium/ui/base/clipboard/clipboard_x11.cc
@@ -22,8 +22,10 @@
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_constants.h"
+#include "ui/base/clipboard/clipboard_metrics.h"
#include "ui/base/clipboard/clipboard_monitor.h"
#include "ui/base/clipboard/custom_data_helper.h"
+#include "ui/base/nine_image_painter_factory.h"
#include "ui/base/x/selection_owner.h"
#include "ui/base/x/selection_requestor.h"
#include "ui/base/x/selection_utils.h"
@@ -32,8 +34,12 @@
#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/event.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/xfixes.h"
+#include "ui/gfx/x/xproto.h"
namespace ui {
@@ -61,63 +67,57 @@ class SelectionChangeObserver : public XEventObserver {
~SelectionChangeObserver() override;
// XEventObserver:
- void WillProcessXEvent(XEvent* xev) override;
- void DidProcessXEvent(XEvent* xev) override {}
+ void WillProcessXEvent(x11::Event* xev) override;
+ void DidProcessXEvent(x11::Event* xev) override {}
- int event_base_;
- Atom clipboard_atom_;
- uint64_t clipboard_sequence_number_;
- uint64_t primary_sequence_number_;
+ x11::Atom clipboard_atom_{};
+ uint64_t clipboard_sequence_number_{};
+ uint64_t primary_sequence_number_{};
DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver);
};
-SelectionChangeObserver::SelectionChangeObserver()
- : event_base_(-1),
- clipboard_atom_(x11::None),
- clipboard_sequence_number_(0),
- primary_sequence_number_(0) {
- int ignored;
- if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) {
- clipboard_atom_ = gfx::GetAtom(kClipboard);
- XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(),
- clipboard_atom_,
- XFixesSetSelectionOwnerNotifyMask |
- XFixesSelectionWindowDestroyNotifyMask |
- XFixesSelectionClientCloseNotifyMask);
- // This seems to be semi-optional. For some reason, registering for any
- // selection notify events seems to subscribe us to events for both the
- // primary and the clipboard buffers. Register anyway just to be safe.
- XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(),
- XA_PRIMARY,
- XFixesSetSelectionOwnerNotifyMask |
- XFixesSelectionWindowDestroyNotifyMask |
- XFixesSelectionClientCloseNotifyMask);
-
- X11EventSource::GetInstance()->AddXEventObserver(this);
- }
-}
+SelectionChangeObserver::SelectionChangeObserver() {
+ auto& xfixes = x11::Connection::Get()->xfixes();
+ // Let the server know the client version. No need to sync since we don't
+ // care what version is running on the server.
+ xfixes.QueryVersion({x11::XFixes::major_version, x11::XFixes::minor_version});
+ if (!xfixes.present())
+ return;
+
+ clipboard_atom_ = gfx::GetAtom(kClipboard);
+ auto mask = x11::XFixes::SelectionEventMask::SetSelectionOwner |
+ x11::XFixes::SelectionEventMask::SelectionWindowDestroy |
+ x11::XFixes::SelectionEventMask::SelectionClientClose;
+ xfixes.SelectSelectionInput({GetX11RootWindow(), clipboard_atom_, mask});
+ // This seems to be semi-optional. For some reason, registering for any
+ // selection notify events seems to subscribe us to events for both the
+ // primary and the clipboard buffers. Register anyway just to be safe.
+ xfixes.SelectSelectionInput({GetX11RootWindow(), x11::Atom::PRIMARY, mask});
-SelectionChangeObserver::~SelectionChangeObserver() {
- // We are a singleton; we will outlive the event source.
+ X11EventSource::GetInstance()->AddXEventObserver(this);
}
+// We are a singleton; we will outlive the event source.
+SelectionChangeObserver::~SelectionChangeObserver() = default;
+
SelectionChangeObserver* SelectionChangeObserver::GetInstance() {
return base::Singleton<SelectionChangeObserver>::get();
}
-void SelectionChangeObserver::WillProcessXEvent(XEvent* xev) {
- if (xev->type == event_base_ + XFixesSelectionNotify) {
- XFixesSelectionNotifyEvent* ev =
- reinterpret_cast<XFixesSelectionNotifyEvent*>(xev);
- if (ev->selection == clipboard_atom_) {
- clipboard_sequence_number_++;
- ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
- } else if (ev->selection == XA_PRIMARY) {
- primary_sequence_number_++;
- } else {
- DLOG(ERROR) << "Unexpected selection atom: " << ev->selection;
- }
+void SelectionChangeObserver::WillProcessXEvent(x11::Event* xev) {
+ auto* ev = xev->As<x11::XFixes::SelectionNotifyEvent>();
+ if (!ev)
+ return;
+
+ if (static_cast<x11::Atom>(ev->selection) == clipboard_atom_) {
+ clipboard_sequence_number_++;
+ ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
+ } else if (ev->selection == x11::Atom::PRIMARY) {
+ primary_sequence_number_++;
+ } else {
+ DLOG(ERROR) << "Unexpected selection atom: "
+ << static_cast<uint32_t>(ev->selection);
}
}
@@ -126,7 +126,7 @@ void SelectionChangeObserver::WillProcessXEvent(XEvent* xev) {
// Represents a list of possible return types. Copy constructable.
class TargetList {
public:
- using AtomVector = std::vector<::Atom>;
+ using AtomVector = std::vector<x11::Atom>;
explicit TargetList(const AtomVector& target_list);
@@ -134,7 +134,7 @@ class TargetList {
bool ContainsText() const;
bool ContainsFormat(const ClipboardFormatType& format_type) const;
- bool ContainsAtom(::Atom atom) const;
+ bool ContainsAtom(x11::Atom atom) const;
private:
AtomVector target_list_;
@@ -144,7 +144,7 @@ TargetList::TargetList(const AtomVector& target_list)
: target_list_(target_list) {}
bool TargetList::ContainsText() const {
- std::vector<::Atom> atoms = GetTextAtomsFrom();
+ std::vector<x11::Atom> atoms = GetTextAtomsFrom();
for (const auto& atom : atoms) {
if (ContainsAtom(atom))
return true;
@@ -154,14 +154,19 @@ bool TargetList::ContainsText() const {
}
bool TargetList::ContainsFormat(const ClipboardFormatType& format_type) const {
- ::Atom atom = gfx::GetAtom(format_type.GetName().c_str());
+ x11::Atom atom = gfx::GetAtom(format_type.GetName().c_str());
return ContainsAtom(atom);
}
-bool TargetList::ContainsAtom(::Atom atom) const {
+bool TargetList::ContainsAtom(x11::Atom atom) const {
return base::Contains(target_list_, atom);
}
+x11::Window GetSelectionOwner(x11::Atom selection) {
+ auto response = x11::Connection::Get()->GetSelectionOwner({selection}).Sync();
+ return response ? response->owner : x11::Window::None;
+}
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
@@ -176,14 +181,14 @@ class ClipboardX11::X11Details : public XEventDispatcher {
// Returns the X11 selection atom that we pass to various XSelection functions
// for the given buffer.
- ::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const;
+ x11::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const;
// Returns the X11 selection atom that we pass to various XSelection functions
// for ClipboardBuffer::kCopyPaste.
- ::Atom GetCopyPasteSelection() const;
+ x11::Atom GetCopyPasteSelection() const;
// Finds the SelectionFormatMap for the incoming selection atom.
- const SelectionFormatMap& LookupStorageForAtom(::Atom atom);
+ const SelectionFormatMap& LookupStorageForAtom(x11::Atom atom);
// As we need to collect all the data types before we tell X11 that we own a
// particular selection, we create a temporary clipboard mapping that
@@ -208,7 +213,7 @@ class ClipboardX11::X11Details : public XEventDispatcher {
// and do the asynchronous dance with whatever application is holding the
// selection.
SelectionData RequestAndWaitForTypes(ClipboardBuffer buffer,
- const std::vector<::Atom>& types);
+ const std::vector<x11::Atom>& types);
// Retrieves the list of possible data types the current clipboard owner has.
//
@@ -217,10 +222,10 @@ class ClipboardX11::X11Details : public XEventDispatcher {
TargetList WaitAndGetTargetsList(ClipboardBuffer buffer);
// Returns a list of all text atoms that we handle.
- std::vector<::Atom> GetTextAtoms() const;
+ std::vector<x11::Atom> GetTextAtoms() const;
// Returns a vector with a |format| converted to an X11 atom.
- std::vector<::Atom> GetAtomsForFormat(const ClipboardFormatType& format);
+ std::vector<x11::Atom> GetAtomsForFormat(const ClipboardFormatType& format);
// Clears a certain clipboard buffer, whether we own it or not.
void Clear(ClipboardBuffer buffer);
@@ -231,16 +236,14 @@ class ClipboardX11::X11Details : public XEventDispatcher {
private:
// XEventDispatcher:
- bool DispatchXEvent(XEvent* xev) override;
-
- bool CanDispatchXEvent(XEvent* xev);
+ bool DispatchXEvent(x11::Event* xev) override;
// Our X11 state.
- Display* x_display_;
- ::Window x_root_window_;
+ x11::Connection* connection_;
+ x11::Window x_root_window_;
// Input-only window used as a selection owner.
- ::Window x_window_;
+ x11::Window x_window_;
// Events selected on |x_window_|.
std::unique_ptr<XScopedEventSelector> x_window_events_;
@@ -259,26 +262,16 @@ class ClipboardX11::X11Details : public XEventDispatcher {
};
ClipboardX11::X11Details::X11Details()
- : x_display_(gfx::GetXDisplay()),
- x_root_window_(DefaultRootWindow(x_display_)),
- x_window_(XCreateWindow(x_display_,
- x_root_window_,
- -100,
- -100,
- 10,
- 10, // x, y, width, height
- 0, // border width
- CopyFromParent, // depth
- InputOnly,
- CopyFromParent, // visual
- 0,
- nullptr)),
- selection_requestor_(x_display_, x_window_, this),
- clipboard_owner_(x_display_, x_window_, gfx::GetAtom(kClipboard)),
- primary_owner_(x_display_, x_window_, XA_PRIMARY) {
- XStoreName(x_display_, x_window_, "Chromium clipboard");
- x_window_events_.reset(
- new XScopedEventSelector(x_window_, PropertyChangeMask));
+ : connection_(x11::Connection::Get()),
+ x_root_window_(ui::GetX11RootWindow()),
+ x_window_(CreateDummyWindow("Chromium Clipboard Window")),
+ selection_requestor_(x_window_, this),
+ clipboard_owner_(connection_, x_window_, gfx::GetAtom(kClipboard)),
+ primary_owner_(connection_, x_window_, x11::Atom::PRIMARY) {
+ SetStringProperty(x_window_, x11::Atom::WM_NAME, x11::Atom::STRING,
+ "Chromium clipboard");
+ x_window_events_ =
+ std::make_unique<XScopedEventSelector>(x_window_, PropertyChangeMask);
if (X11EventSource::GetInstance())
X11EventSource::GetInstance()->AddXEventDispatcher(this);
@@ -288,24 +281,24 @@ ClipboardX11::X11Details::~X11Details() {
if (X11EventSource::GetInstance())
X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
- XDestroyWindow(x_display_, x_window_);
+ connection_->DestroyWindow({x_window_});
}
-::Atom ClipboardX11::X11Details::LookupSelectionForClipboardBuffer(
+x11::Atom ClipboardX11::X11Details::LookupSelectionForClipboardBuffer(
ClipboardBuffer buffer) const {
if (buffer == ClipboardBuffer::kCopyPaste)
return GetCopyPasteSelection();
- return XA_PRIMARY;
+ return x11::Atom::PRIMARY;
}
-::Atom ClipboardX11::X11Details::GetCopyPasteSelection() const {
+x11::Atom ClipboardX11::X11Details::GetCopyPasteSelection() const {
return gfx::GetAtom(kClipboard);
}
const SelectionFormatMap& ClipboardX11::X11Details::LookupStorageForAtom(
- ::Atom atom) {
- if (atom == XA_PRIMARY)
+ x11::Atom atom) {
+ if (atom == x11::Atom::PRIMARY)
return primary_owner_.selection_format_map();
DCHECK_EQ(GetCopyPasteSelection(), atom);
@@ -319,7 +312,7 @@ void ClipboardX11::X11Details::CreateNewClipboardData() {
void ClipboardX11::X11Details::InsertMapping(
const std::string& key,
const scoped_refptr<base::RefCountedMemory>& memory) {
- ::Atom atom_key = gfx::GetAtom(key.c_str());
+ x11::Atom atom_key = gfx::GetAtom(key.c_str());
clipboard_data_.Insert(atom_key, memory);
}
@@ -333,9 +326,9 @@ void ClipboardX11::X11Details::TakeOwnershipOfSelection(
SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes(
ClipboardBuffer buffer,
- const std::vector<::Atom>& types) {
- ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
- if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
+ const std::vector<x11::Atom>& types) {
+ x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
+ if (GetSelectionOwner(selection_name) == x_window_) {
// We can local fastpath instead of playing the nested run loop game
// with the X server.
const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
@@ -348,8 +341,8 @@ SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes(
} else {
TargetList targets = WaitAndGetTargetsList(buffer);
- ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
- std::vector<::Atom> intersection;
+ x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
+ std::vector<x11::Atom> intersection;
GetAtomIntersection(types, targets.target_list(), &intersection);
return selection_requestor_.RequestAndWaitForTypes(selection_name,
intersection);
@@ -360,27 +353,25 @@ SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes(
TargetList ClipboardX11::X11Details::WaitAndGetTargetsList(
ClipboardBuffer buffer) {
- ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
- std::vector<::Atom> out;
- if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
+ x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer);
+ std::vector<x11::Atom> out;
+ if (GetSelectionOwner(selection_name) == x_window_) {
// We can local fastpath and return the list of local targets.
const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
for (const auto& format : format_map)
out.push_back(format.first);
} else {
- scoped_refptr<base::RefCountedMemory> data;
- size_t out_data_items = 0;
- ::Atom out_type = x11::None;
+ std::vector<uint8_t> data;
+ x11::Atom out_type = x11::Atom::None;
if (selection_requestor_.PerformBlockingConvertSelection(
- selection_name, gfx::GetAtom(kTargets), &data, &out_data_items,
- &out_type)) {
+ selection_name, gfx::GetAtom(kTargets), &data, &out_type)) {
// Some apps return an |out_type| of "TARGETS". (crbug.com/377893)
- if (out_type == XA_ATOM || out_type == gfx::GetAtom(kTargets)) {
- const ::Atom* atom_array =
- reinterpret_cast<const ::Atom*>(data->front());
- for (size_t i = 0; i < out_data_items; ++i)
+ if (out_type == x11::Atom::ATOM || out_type == gfx::GetAtom(kTargets)) {
+ const x11::Atom* atom_array =
+ reinterpret_cast<const x11::Atom*>(data.data());
+ for (size_t i = 0; i < data.size() / sizeof(x11::Atom); ++i)
out.push_back(atom_array[i]);
}
} else {
@@ -390,11 +381,11 @@ TargetList ClipboardX11::X11Details::WaitAndGetTargetsList(
// text. This is pretty unfortunate since it means we have to actually
// copy the data to see if it is available, but at least this path
// shouldn't be hit for conforming programs.
- std::vector<::Atom> types = GetTextAtoms();
+ std::vector<x11::Atom> types = GetTextAtoms();
for (const auto& text_atom : types) {
- ::Atom type = x11::None;
+ x11::Atom type = x11::Atom::None;
if (selection_requestor_.PerformBlockingConvertSelection(
- selection_name, text_atom, nullptr, nullptr, &type) &&
+ selection_name, text_atom, nullptr, &type) &&
type == text_atom) {
out.push_back(text_atom);
}
@@ -405,11 +396,11 @@ TargetList ClipboardX11::X11Details::WaitAndGetTargetsList(
return TargetList(out);
}
-std::vector<::Atom> ClipboardX11::X11Details::GetTextAtoms() const {
+std::vector<x11::Atom> ClipboardX11::X11Details::GetTextAtoms() const {
return GetTextAtomsFrom();
}
-std::vector<::Atom> ClipboardX11::X11Details::GetAtomsForFormat(
+std::vector<x11::Atom> ClipboardX11::X11Details::GetAtomsForFormat(
const ClipboardFormatType& format) {
return {gfx::GetAtom(format.GetName().c_str())};
}
@@ -422,18 +413,18 @@ void ClipboardX11::X11Details::Clear(ClipboardBuffer buffer) {
}
void ClipboardX11::X11Details::StoreCopyPasteDataAndWait() {
- ::Atom selection = GetCopyPasteSelection();
- if (XGetSelectionOwner(x_display_, selection) != x_window_)
+ x11::Atom selection = GetCopyPasteSelection();
+ if (GetSelectionOwner(selection) != x_window_)
return;
- ::Atom clipboard_manager_atom = gfx::GetAtom(kClipboardManager);
- if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == x11::None)
+ x11::Atom clipboard_manager_atom = gfx::GetAtom(kClipboardManager);
+ if (GetSelectionOwner(clipboard_manager_atom) == x11::Window::None)
return;
const SelectionFormatMap& format_map = LookupStorageForAtom(selection);
if (format_map.size() == 0)
return;
- std::vector<Atom> targets = format_map.GetTypes();
+ std::vector<x11::Atom> targets = format_map.GetTypes();
base::TimeTicks start = base::TimeTicks::Now();
selection_requestor_.PerformBlockingConvertSelectionWithParameter(
@@ -442,71 +433,45 @@ void ClipboardX11::X11Details::StoreCopyPasteDataAndWait() {
base::TimeTicks::Now() - start);
}
-bool ClipboardX11::X11Details::CanDispatchXEvent(XEvent* xev) {
- if (xev->xany.window == x_window_)
- return true;
-
- if (xev->type == PropertyNotify) {
- return primary_owner_.CanDispatchPropertyEvent(*xev) ||
- clipboard_owner_.CanDispatchPropertyEvent(*xev) ||
- selection_requestor_.CanDispatchPropertyEvent(*xev);
- }
- return false;
-}
-
-bool ClipboardX11::X11Details::DispatchXEvent(XEvent* xev) {
- if (!CanDispatchXEvent(xev))
- return false;
-
- switch (xev->type) {
- case SelectionRequest: {
- if (xev->xselectionrequest.selection == XA_PRIMARY) {
- primary_owner_.OnSelectionRequest(*xev);
- } else {
- // We should not get requests for the CLIPBOARD_MANAGER selection
- // because we never take ownership of it.
- DCHECK_EQ(GetCopyPasteSelection(), xev->xselectionrequest.selection);
- clipboard_owner_.OnSelectionRequest(*xev);
- }
- break;
- }
- case SelectionNotify: {
- selection_requestor_.OnSelectionNotify(*xev);
- break;
- }
- case SelectionClear: {
- if (xev->xselectionclear.selection == XA_PRIMARY) {
- primary_owner_.OnSelectionClear(*xev);
- } else {
- // We should not get requests for the CLIPBOARD_MANAGER selection
- // because we never take ownership of it.
- DCHECK_EQ(GetCopyPasteSelection(), xev->xselection.selection);
- clipboard_owner_.OnSelectionClear(*xev);
- }
- break;
+bool ClipboardX11::X11Details::DispatchXEvent(x11::Event* xev) {
+ if (auto* request = xev->As<x11::SelectionRequestEvent>()) {
+ if (request->owner != x_window_)
+ return false;
+ if (request->selection == x11::Atom::PRIMARY) {
+ primary_owner_.OnSelectionRequest(*xev);
+ } else {
+ // We should not get requests for the CLIPBOARD_MANAGER selection
+ // because we never take ownership of it.
+ DCHECK_EQ(GetCopyPasteSelection(), request->selection);
+ clipboard_owner_.OnSelectionRequest(*xev);
}
- case PropertyNotify: {
- if (primary_owner_.CanDispatchPropertyEvent(*xev))
- primary_owner_.OnPropertyEvent(*xev);
- if (clipboard_owner_.CanDispatchPropertyEvent(*xev))
- clipboard_owner_.OnPropertyEvent(*xev);
- if (selection_requestor_.CanDispatchPropertyEvent(*xev))
- selection_requestor_.OnPropertyEvent(*xev);
- break;
+ } else if (auto* notify = xev->As<x11::SelectionNotifyEvent>()) {
+ if (notify->requestor != x_window_)
+ return false;
+ selection_requestor_.OnSelectionNotify(*notify);
+ } else if (auto* clear = xev->As<x11::SelectionClearEvent>()) {
+ if (clear->owner != x_window_)
+ return false;
+ if (clear->selection == x11::Atom::PRIMARY) {
+ primary_owner_.OnSelectionClear(*xev);
+ } else {
+ // We should not get requests for the CLIPBOARD_MANAGER selection
+ // because we never take ownership of it.
+ DCHECK_EQ(GetCopyPasteSelection(), clear->selection);
+ clipboard_owner_.OnSelectionClear(*xev);
}
- default:
- break;
+ } else if (auto* prop = xev->As<x11::PropertyNotifyEvent>()) {
+ if (primary_owner_.CanDispatchPropertyEvent(*xev))
+ primary_owner_.OnPropertyEvent(*xev);
+ if (clipboard_owner_.CanDispatchPropertyEvent(*xev))
+ clipboard_owner_.OnPropertyEvent(*xev);
+ if (selection_requestor_.CanDispatchPropertyEvent(*xev))
+ selection_requestor_.OnPropertyEvent(*xev);
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
-// Clipboard factory method.
-Clipboard* Clipboard::Create() {
- return new ClipboardX11;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// ClipboardX11
ClipboardX11::ClipboardX11() : x11_details_(new X11Details) {
@@ -586,17 +551,16 @@ ClipboardX11::ReadAvailablePlatformSpecificFormatNames(
if (target_list.empty())
return {};
- std::vector<char*> types_buffer(target_list.size());
- // Call XGetAtomNames to minimize trips to the X11 server.
- int status = XGetAtomNames(gfx::GetXDisplay(), target_list.data(),
- target_list.size(), types_buffer.data());
- DCHECK(status) << "XGetAtomNames failed! An invalid Atom was passed in.";
-
+ std::vector<x11::Future<x11::GetAtomNameReply>> futures;
+ for (x11::Atom target : target_list)
+ futures.push_back(x11::Connection::Get()->GetAtomName({target}));
std::vector<base::string16> types;
types.reserve(target_list.size());
- for (char* type : types_buffer) {
- types.push_back(base::UTF8ToUTF16(type));
- XFree(type);
+ for (auto& future : futures) {
+ if (auto response = future.Sync())
+ types.push_back(base::UTF8ToUTF16(response->name));
+ else
+ types.emplace_back();
}
return types;
@@ -605,6 +569,7 @@ ClipboardX11::ReadAvailablePlatformSpecificFormatNames(
void ClipboardX11::ReadText(ClipboardBuffer buffer,
base::string16* result) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kText);
SelectionData data(x11_details_->RequestAndWaitForTypes(
buffer, x11_details_->GetTextAtoms()));
@@ -617,6 +582,7 @@ void ClipboardX11::ReadText(ClipboardBuffer buffer,
void ClipboardX11::ReadAsciiText(ClipboardBuffer buffer,
std::string* result) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kText);
SelectionData data(x11_details_->RequestAndWaitForTypes(
buffer, x11_details_->GetTextAtoms()));
@@ -632,6 +598,7 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer,
uint32_t* fragment_start,
uint32_t* fragment_end) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kHtml);
markup->clear();
if (src_url)
src_url->clear();
@@ -652,6 +619,7 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer,
void ClipboardX11::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kRtf);
SelectionData data(x11_details_->RequestAndWaitForTypes(
buffer,
@@ -663,6 +631,7 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
void ClipboardX11::ReadImage(ClipboardBuffer buffer,
ReadImageCallback callback) const {
DCHECK(IsSupportedClipboardBuffer(buffer));
+ RecordRead(ClipboardFormatMetric::kImage);
std::move(callback).Run(ReadImageInternal(buffer));
}
@@ -670,6 +639,7 @@ void ClipboardX11::ReadCustomData(ClipboardBuffer buffer,
const base::string16& type,
base::string16* result) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kCustomData);
SelectionData data(x11_details_->RequestAndWaitForTypes(
buffer, x11_details_->GetAtomsForFormat(
@@ -687,6 +657,7 @@ void ClipboardX11::ReadBookmark(base::string16* title, std::string* url) const {
void ClipboardX11::ReadData(const ClipboardFormatType& format,
std::string* result) const {
DCHECK(CalledOnValidThread());
+ RecordRead(ClipboardFormatMetric::kData);
SelectionData data(x11_details_->RequestAndWaitForTypes(
ClipboardBuffer::kCopyPaste, x11_details_->GetAtomsForFormat(format)));