Commit 6eb1c0f0 authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

[XProto] Remove Xlib usage in clipboard code

R=adunaev
CC=sky,msisov,nickdiego

Change-Id: I5fc6f0fd97e646044b7d3d0894f6bf5e2b4e2e37
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2253223
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781980}
parent 7955598d
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/xproto.h"
namespace ui {
......@@ -40,10 +41,12 @@ static_assert(KSelectionOwnerTimerPeriodMs <= kIncrementalTransferTimeoutMs,
// Returns a conservative max size of the data we can pass into
// XChangeProperty(). Copied from GTK.
size_t GetMaxRequestSize(XDisplay* display) {
long extended_max_size = XExtendedMaxRequestSize(display);
size_t GetMaxRequestSize(x11::Connection* connection) {
long extended_max_size = connection->extended_max_request_length();
long max_size =
(extended_max_size ? extended_max_size : XMaxRequestSize(display)) - 100;
(extended_max_size ? extended_max_size
: connection->setup().maximum_request_length) -
100;
return std::min(static_cast<long>(0x40000),
std::max(static_cast<long>(0), max_size));
}
......@@ -79,13 +82,12 @@ void SetSelectionOwner(x11::Window window,
} // namespace
SelectionOwner::SelectionOwner(XDisplay* x_display,
SelectionOwner::SelectionOwner(x11::Connection* connection,
x11::Window x_window,
x11::Atom selection_name)
: x_display_(x_display),
x_window_(x_window),
: x_window_(x_window),
selection_name_(selection_name),
max_request_size_(GetMaxRequestSize(x_display)) {}
max_request_size_(GetMaxRequestSize(connection)) {}
SelectionOwner::~SelectionOwner() {
// If we are the selection owner, we need to release the selection so we
......@@ -117,22 +119,20 @@ void SelectionOwner::ClearSelectionOwner() {
}
void SelectionOwner::OnSelectionRequest(const x11::Event& x11_event) {
const XEvent& event = x11_event.xlib_event();
auto requestor = static_cast<x11::Window>(event.xselectionrequest.requestor);
x11::Atom requested_target =
static_cast<x11::Atom>(event.xselectionrequest.target);
x11::Atom requested_property =
static_cast<x11::Atom>(event.xselectionrequest.property);
auto& request = *x11_event.As<x11::SelectionRequestEvent>();
auto requestor = request.requestor;
x11::Atom requested_target = request.target;
x11::Atom requested_property = request.property;
// Incrementally build our selection. By default this is a refusal, and we'll
// override the parts indicating success in the different cases.
XEvent reply;
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = static_cast<uint32_t>(requestor);
reply.xselection.selection = event.xselectionrequest.selection;
reply.xselection.target = static_cast<uint32_t>(requested_target);
reply.xselection.property = x11::None; // Indicates failure
reply.xselection.time = event.xselectionrequest.time;
x11::SelectionNotifyEvent reply{
.time = request.time,
.requestor = requestor,
.selection = request.selection,
.target = requested_target,
.property = x11::Atom::None, // Indicates failure
};
if (requested_target == gfx::GetAtom(kMultiple)) {
// The contents of |requested_property| should be a list of
......@@ -153,16 +153,15 @@ void SelectionOwner::OnSelectionRequest(const x11::Event& x11_event) {
ui::SetArrayProperty(requestor, requested_property,
gfx::GetAtom(kAtomPair), conversion_results);
reply.xselection.property = static_cast<uint32_t>(requested_property);
reply.property = requested_property;
}
} else {
if (ProcessTarget(requested_target, requestor, requested_property))
reply.xselection.property = static_cast<uint32_t>(requested_property);
reply.property = requested_property;
}
// Send off the reply.
XSendEvent(x_display_, static_cast<uint32_t>(requestor), x11::False, 0,
&reply);
ui::SendEvent(reply, requestor, x11::EventMask::NoEvent);
}
void SelectionOwner::OnSelectionClear(const x11::Event& event) {
......@@ -173,7 +172,7 @@ void SelectionOwner::OnSelectionClear(const x11::Event& event) {
}
bool SelectionOwner::CanDispatchPropertyEvent(const x11::Event& event) {
return event.xlib_event().xproperty.state == PropertyDelete &&
return event.As<x11::PropertyNotifyEvent>()->state == x11::Property::Delete &&
FindIncrementalTransferForEvent(event) != incremental_transfers_.end();
}
......@@ -296,15 +295,13 @@ void SelectionOwner::CompleteIncrementalTransfer(
}
std::vector<SelectionOwner::IncrementalTransfer>::iterator
SelectionOwner::FindIncrementalTransferForEvent(const x11::Event& x11_event) {
const XEvent& event = x11_event.xlib_event();
SelectionOwner::FindIncrementalTransferForEvent(const x11::Event& event) {
for (auto it = incremental_transfers_.begin();
it != incremental_transfers_.end(); ++it) {
if (it->window == static_cast<x11::Window>(event.xproperty.window) &&
it->property == static_cast<x11::Atom>(event.xproperty.atom)) {
const auto* prop = event.As<x11::PropertyNotifyEvent>();
if (it->window == prop->window && it->property == prop->atom)
return it;
}
}
return incremental_transfers_.end();
}
......
......@@ -34,7 +34,7 @@ COMPONENT_EXPORT(UI_BASE_X) extern const char kTargets[];
// processes.
class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner {
public:
SelectionOwner(XDisplay* xdisplay,
SelectionOwner(x11::Connection* connection,
x11::Window xwindow,
x11::Atom selection_name);
~SelectionOwner();
......@@ -126,7 +126,6 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner {
const x11::Event& event);
// Our X11 state.
XDisplay* x_display_;
x11::Window x_window_;
// The X11 selection that this instance communicates on.
......
......@@ -15,6 +15,7 @@
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gfx/x/xproto.h"
namespace ui {
......@@ -50,11 +51,9 @@ std::vector<uint8_t> CombineData(
} // namespace
SelectionRequestor::SelectionRequestor(XDisplay* x_display,
x11::Window x_window,
SelectionRequestor::SelectionRequestor(x11::Window x_window,
XEventDispatcher* dispatcher)
: x_display_(x_display),
x_window_(x_window),
: x_window_(x_window),
x_property_(x11::Atom::None),
dispatcher_(dispatcher),
current_request_index_(0u) {
......@@ -120,14 +119,13 @@ SelectionData SelectionRequestor::RequestAndWaitForTypes(
return SelectionData();
}
void SelectionRequestor::OnSelectionNotify(const x11::Event& x11_event) {
const XEvent& event = x11_event.xlib_event();
void SelectionRequestor::OnSelectionNotify(
const x11::SelectionNotifyEvent& selection) {
Request* request = GetCurrentRequest();
x11::Atom event_property = static_cast<x11::Atom>(event.xselection.property);
x11::Atom event_property = selection.property;
if (!request || request->completed ||
request->selection !=
static_cast<x11::Atom>(event.xselection.selection) ||
request->target != static_cast<x11::Atom>(event.xselection.target)) {
request->selection != selection.selection ||
request->target != selection.target) {
// ICCCM requires us to delete the property passed into SelectionNotify.
if (event_property != x11::Atom::None)
ui::DeleteProperty(x_window_, event_property);
......@@ -158,11 +156,10 @@ void SelectionRequestor::OnSelectionNotify(const x11::Event& x11_event) {
}
}
bool SelectionRequestor::CanDispatchPropertyEvent(const x11::Event& x11_event) {
const XEvent& event = x11_event.xlib_event();
return event.xproperty.window == static_cast<uint32_t>(x_window_) &&
static_cast<x11::Atom>(event.xproperty.atom) == x_property_ &&
event.xproperty.state == PropertyNewValue;
bool SelectionRequestor::CanDispatchPropertyEvent(const x11::Event& event) {
const auto* prop = event.As<x11::PropertyNotifyEvent>();
return prop->window == x_window_ && prop->atom == x_property_ &&
prop->state == x11::Property::NewValue;
}
void SelectionRequestor::OnPropertyEvent(const x11::Event& event) {
......
......@@ -33,9 +33,7 @@ class SelectionData;
// implement per-component fast-paths.
class COMPONENT_EXPORT(UI_BASE) SelectionRequestor {
public:
SelectionRequestor(XDisplay* xdisplay,
x11::Window xwindow,
XEventDispatcher* dispatcher);
SelectionRequestor(x11::Window xwindow, XEventDispatcher* dispatcher);
~SelectionRequestor();
// Does the work of requesting |target| from |selection|, spinning up the
......@@ -61,7 +59,7 @@ class COMPONENT_EXPORT(UI_BASE) SelectionRequestor {
// It is our owner's responsibility to plumb X11 SelectionNotify events on
// |xwindow_| to us.
void OnSelectionNotify(const x11::Event& event);
void OnSelectionNotify(const x11::SelectionNotifyEvent& event);
// Returns true if SelectionOwner can process the XChangeProperty event,
// |event|.
......@@ -121,7 +119,6 @@ class COMPONENT_EXPORT(UI_BASE) SelectionRequestor {
Request* GetCurrentRequest();
// Our X11 state.
XDisplay* x_display_;
x11::Window x_window_;
// The property on |x_window_| set by the selection owner with the value of
......
......@@ -55,7 +55,8 @@ class SelectionRequestorTest : public testing::Test {
event->property = static_cast<uint32_t>(requestor_->x_property_);
event->time = x11::CurrentTime;
requestor_->OnSelectionNotify(x11::Event(&ge, x11::Connection::Get()));
x11::Event xev(&ge, x11::Connection::Get());
requestor_->OnSelectionNotify(*xev.As<x11::SelectionNotifyEvent>());
}
protected:
......@@ -75,8 +76,7 @@ class SelectionRequestorTest : public testing::Test {
event_source_ = PlatformEventSource::CreateDefault();
CHECK(PlatformEventSource::GetInstance());
requestor_ =
std::make_unique<SelectionRequestor>(x_display_, x_window_, nullptr);
requestor_ = std::make_unique<SelectionRequestor>(x_window_, nullptr);
}
void TearDown() override {
......
......@@ -37,38 +37,23 @@ const char kNetscapeURL[] = "_NETSCAPE_URL";
XOSExchangeDataProvider::XOSExchangeDataProvider(
x11::Window x_window,
const SelectionFormatMap& selection)
: x_display_(gfx::GetXDisplay()),
: connection_(x11::Connection::Get()),
x_root_window_(ui::GetX11RootWindow()),
own_window_(false),
x_window_(x_window),
format_map_(selection),
selection_owner_(x_display_, x_window_, gfx::GetAtom(kDndSelection)) {}
selection_owner_(connection_, x_window_, gfx::GetAtom(kDndSelection)) {}
XOSExchangeDataProvider::XOSExchangeDataProvider()
: x_display_(gfx::GetXDisplay()),
: connection_(x11::Connection::Get()),
x_root_window_(ui::GetX11RootWindow()),
own_window_(true),
x_window_(static_cast<x11::Window>(XCreateWindow(
x_display_,
static_cast<uint32_t>(x_root_window_),
-100, // x
-100, // y
10, // width
10, // height
0, // border width
static_cast<int>(x11::WindowClass::CopyFromParent), // depth
static_cast<int>(x11::WindowClass::InputOnly),
nullptr, // visual
0,
nullptr))),
selection_owner_(x_display_, x_window_, gfx::GetAtom(kDndSelection)) {
XStoreName(x_display_, static_cast<uint32_t>(x_window_),
"Chromium Drag & Drop Window");
}
x_window_(CreateDummyWindow("Chromium Drag & Drop Window")),
selection_owner_(connection_, x_window_, gfx::GetAtom(kDndSelection)) {}
XOSExchangeDataProvider::~XOSExchangeDataProvider() {
if (own_window_)
XDestroyWindow(x_display_, static_cast<uint32_t>(x_window_));
connection_->DestroyWindow({x_window_});
}
void XOSExchangeDataProvider::TakeOwnershipOfSelection() const {
......
......@@ -125,7 +125,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider
gfx::Vector2d drag_image_offset_;
// Our X11 state.
Display* x_display_;
x11::Connection* connection_;
x11::Window x_root_window_;
// In X11, because the IPC parts of drag operations are implemented by
......
......@@ -455,6 +455,24 @@ void DefineCursor(x11::Window window, x11::Cursor cursor) {
.Sync();
}
x11::Window CreateDummyWindow(const std::string& name) {
auto* connection = x11::Connection::Get();
auto window = connection->GenerateId<x11::Window>();
connection->CreateWindow({
.wid = window,
.parent = connection->default_root(),
.x = -100,
.y = -100,
.width = 10,
.height = 10,
.c_class = x11::WindowClass::InputOnly,
.override_redirect = x11::Bool32(true),
});
if (!name.empty())
SetStringProperty(window, x11::Atom::WM_NAME, x11::Atom::STRING, name);
return window;
}
bool IsXInput2Available() {
return DeviceDataManagerX11::GetInstance()->IsXInput2Available();
}
......
......@@ -184,6 +184,18 @@ void SetProperty(x11::Window window,
SetArrayProperty(window, name, type, std::vector<T>{value});
}
template <typename T>
void SendEvent(const T& event, x11::Window target, x11::EventMask mask) {
static_assert(T::type_id > 0, "T must be an x11::*Event type");
auto event_bytes = x11::Write(event);
DCHECK_LE(event_bytes.size(), 32ul);
event_bytes.resize(32);
x11::SendEventRequest send_event{false, target, mask};
std::copy(event_bytes.begin(), event_bytes.end(), send_event.event.begin());
x11::Connection::Get()->SendEvent(send_event);
}
COMPONENT_EXPORT(UI_BASE_X)
void DeleteProperty(x11::Window window, x11::Atom name);
......@@ -211,6 +223,9 @@ void LowerWindow(x11::Window window);
COMPONENT_EXPORT(UI_BASE_X)
void DefineCursor(x11::Window window, x11::Cursor cursor);
COMPONENT_EXPORT(UI_BASE_X)
x11::Window CreateDummyWindow(const std::string& name = "");
// These functions cache their results ---------------------------------
// Returns true if the system supports XINPUT2.
......
......@@ -233,6 +233,7 @@ READ_SPECIAL = set([
WRITE_SPECIAL = set([
('xcb', 'ClientMessage'),
('xcb', 'UnmapNotify'),
('xcb', 'SelectionNotify'),
])
......
......@@ -14,6 +14,8 @@
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gfx/x/xfixes.h"
#include "ui/gfx/x/xproto.h"
#include "ui/ozone/public/platform_clipboard.h"
namespace ui {
......@@ -54,9 +56,10 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// XEventDispatcher:
bool DispatchXEvent(x11::Event* xev) override;
bool OnSelectionRequest(const XSelectionRequestEvent& event);
bool OnSelectionNotify(const XSelectionEvent& event);
bool OnSetSelectionOwnerNotify(x11::Event* xev);
bool OnSelectionRequest(const x11::SelectionRequestEvent& event);
bool OnSelectionNotify(const x11::SelectionNotifyEvent& event);
bool OnSetSelectionOwnerNotify(
const x11::XFixes::SelectionNotifyEvent& event);
// Returns an X atom for a clipboard buffer type.
x11::Atom SelectionAtomForBuffer(ClipboardBuffer buffer) const;
......@@ -89,7 +92,7 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
const x11::Atom x_property_;
// Our X11 state.
Display* const x_display_;
x11::Connection* connection_;
// Input-only window used as a selection owner.
const x11::Window x_window_;
......@@ -99,9 +102,6 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// TODO(joelhockey): Make clipboard work without xfixes.
bool using_xfixes_ = false;
// The event base returned by XFixesQueryExtension().
int xfixes_event_base_;
// Notifies whenever clipboard sequence number is changed.
PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment