15#include "wayland/datasource.h"
22#include <xwayland_logging.h>
31 , m_selection(selection)
32 , m_window(selection->window())
46 for (
const auto &mime : dsi->
mimeTypes()) {
52 m_offerConnection = connect(dsi,
79 if (!checkStartTransfer(event)) {
88 QList<xcb_atom_t> targets;
89 targets.resize(m_offers.size() + 2);
94 for (
const auto &mime : std::as_const(m_offers)) {
99 xcb_change_property(kwinApp()->x11Connection(),
100 XCB_PROP_MODE_REPLACE,
104 32, cnt, targets.data());
110 const xcb_timestamp_t time =
timestamp();
111 xcb_change_property(kwinApp()->x11Connection(),
112 XCB_PROP_MODE_REPLACE,
121bool WlSource::checkStartTransfer(xcb_selection_request_event_t *event)
129 if (targets.isEmpty()) {
130 qCDebug(KWIN_XWL) <<
"Unknown selection atom. Ignoring request.";
133 const auto firstTarget = targets[0];
135 auto cmp = [firstTarget](
const QString &b) {
136 if (firstTarget ==
"text/uri-list") {
138 return firstTarget == b || b ==
"text/x-uri";
140 return firstTarget == b;
144 const auto mimeIt = std::find_if(offers.begin(), offers.end(), cmp);
145 if (mimeIt == offers.end()) {
151 if (pipe2(p, O_CLOEXEC) == -1) {
152 qCWarning(KWIN_XWL) <<
"Pipe failed. Not sending selection.";
158 Q_EMIT
transferReady(
new xcb_selection_request_event_t(*event), p[0]);
170 xcb_connection_t *xcbConn = kwinApp()->x11Connection();
172 xcb_convert_selection(xcbConn,
181using Mime = QPair<QString, xcb_atom_t>;
183void X11Source::handleTargets()
186 xcb_connection_t *xcbConn = kwinApp()->x11Connection();
187 xcb_get_property_cookie_t cookie = xcb_get_property(xcbConn,
191 XCB_GET_PROPERTY_TYPE_ANY,
194 auto *reply = xcb_get_property_reply(xcbConn, cookie,
nullptr);
196 qCDebug(KWIN_XWL) <<
"Failed to get selection property";
199 if (reply->type != XCB_ATOM_ATOM) {
200 qCDebug(KWIN_XWL) <<
"Wrong reply type";
209 xcb_atom_t *value =
static_cast<xcb_atom_t *
>(xcb_get_property_value(reply));
210 for (uint32_t i = 0; i < reply->value_len; i++) {
211 if (value[i] == XCB_ATOM_NONE) {
216 if (mimeStrings.isEmpty()) {
221 const auto mimeIt = std::find_if(m_offers.begin(), m_offers.end(),
222 [value, i](
const Mime &mime) {
223 return mime.second == value[i];
226 auto mimePair =
Mime(mimeStrings[0], value[i]);
227 if (mimeIt == m_offers.end()) {
228 added << mimePair.first;
230 m_offers.removeAll(mimePair);
235 for (
const auto &mimePair : std::as_const(m_offers)) {
236 removed << mimePair.first;
240 if (!added.isEmpty() || !removed.isEmpty()) {
254 if (event->requestor !=
window()) {
257 if (event->selection !=
selection()->atom()) {
260 if (event->property == XCB_ATOM_NONE) {
261 qCWarning(KWIN_XWL) <<
"Incoming X selection conversion failed";
273 const auto mimeIt = std::find_if(m_offers.begin(), m_offers.end(),
274 [mimeName](
const Mime &mime) {
275 return mime.first == mimeName;
277 if (mimeIt == m_offers.end()) {
278 qCDebug(KWIN_XWL) <<
"Sending X11 clipboard to Wayland failed: unsupported MIME.";
289#include "moc_selection_source.cpp"
The AbstractDataSource class abstracts the data that can be transferred to another client.
void mimeTypeOffered(const QString &)
virtual QStringList mimeTypes() const =0
virtual void requestData(const QString &mimeType, qint32 fd)=0
static void sendSelectionNotify(xcb_selection_request_event_t *event, bool success)
static QStringList atomToMimeTypes(xcb_atom_t atom)
static xcb_atom_t mimeTypeToAtom(const QString &mimeType)
xcb_timestamp_t timestamp() const
SelectionSource(Selection *selection)
void setTimestamp(xcb_timestamp_t time)
xcb_window_t window() const
Selection * selection() const
WlSource(Selection *selection)
bool handleSelectionRequest(xcb_selection_request_event_t *event)
void sendTargets(xcb_selection_request_event_t *event)
void transferReady(xcb_selection_request_event_t *event, qint32 fd)
void sendSelectionNotify(xcb_selection_request_event_t *event, bool success)
void receiveOffer(const QString &mime)
void sendTimestamp(xcb_selection_request_event_t *event)
void setDataSourceIface(AbstractDataSource *dsi)
bool handleSelectionNotify(xcb_selection_notify_event_t *event)
void offersChanged(const QStringList &added, const QStringList &removed)
X11Source(Selection *selection, xcb_xfixes_selection_notify_event_t *event)
void transferReady(xcb_atom_t target, qint32 fd)
void startTransfer(const QString &mimeName, qint32 fd)
void setOffers(const Mimes &offers)
QPair< QString, xcb_atom_t > Mime
QList< QPair< QString, xcb_atom_t > > Mimes
KWIN_EXPORT Atoms * atoms