6#include <QtWaylandCompositor/QWaylandCompositor>
8#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
9#include <QtWaylandCompositor/private/qwaylandseat_p.h>
13#include "qwaylandmimehelper_p.h"
15#include <QtCore/QDebug>
16#include <QtCore/QSocketNotifier>
18#include <QtCore/private/qcore_unix_p.h>
19#include <QtCore/QFile>
26 : wl_data_device_manager(compositor->display(), 1)
27 , m_compositor(compositor)
33 if (m_current_selection_source && source
34 && m_current_selection_source->time() > source->time()) {
35 qDebug() <<
"Trying to set older selection";
39 m_compositorOwnsSelection =
false;
41 finishReadFromClient();
43 m_current_selection_source = source;
53 if (source && m_compositor->retainedSelectionEnabled()) {
54 m_retainedData.clear();
55 m_retainedReadIndex = 0;
62 if (m_current_selection_source == source) {
63 finishReadFromClient();
64 m_current_selection_source =
nullptr;
70 QList<QString> offers = m_current_selection_source->mimeTypes();
71 finishReadFromClient();
72 if (m_retainedReadIndex >= offers.size()) {
73 QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
76 QString mimeType = offers.at(m_retainedReadIndex);
77 m_retainedReadBuf.clear();
80 qWarning(
"Clipboard: Failed to create pipe");
83 fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL, 0) | O_NONBLOCK);
84 m_current_selection_source->send(mimeType, fd[1]);
85 m_retainedReadNotifier =
new QSocketNotifier(fd[0], QSocketNotifier::Read,
this);
86 connect(m_retainedReadNotifier, &QSocketNotifier::activated,
this, &DataDeviceManager::readFromClient);
92 if (m_retainedReadNotifier) {
94 int fd = m_retainedReadNotifier->socket();
95 delete m_retainedReadNotifier;
100 m_obsoleteRetainedReadNotifiers.append(m_retainedReadNotifier);
102 m_retainedReadNotifier =
nullptr;
108 static char buf[4096];
109 int obsCount = m_obsoleteRetainedReadNotifiers.size();
110 for (
int i = 0; i < obsCount; ++i) {
111 QSocketNotifier *sn = m_obsoleteRetainedReadNotifiers.at(i);
112 if (sn->socket() == fd) {
118 n = QT_READ(fd, buf,
sizeof buf);
120 if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
121 m_obsoleteRetainedReadNotifiers.removeAt(i);
128 int n = QT_READ(fd, buf,
sizeof buf);
130 if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
131 finishReadFromClient(
true);
132 QList<QString> offers = m_current_selection_source->mimeTypes();
133 QString mimeType = offers.at(m_retainedReadIndex);
134 m_retainedData.setData(mimeType, m_retainedReadBuf);
135 ++m_retainedReadIndex;
139 m_retainedReadBuf.append(buf, n);
145 return m_current_selection_source;
150 return m_compositor->display();
155 const QStringList formats = mimeData.formats();
156 if (formats.isEmpty())
159 m_retainedData.clear();
160 for (
const QString &format : formats)
161 m_retainedData.setData(format, mimeData.data(format));
163 QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
165 m_compositorOwnsSelection =
true;
167 if (m_current_selection_source) {
168 finishReadFromClient();
173 m_current_selection_source =
nullptr;
176 QWaylandSeat *dev = m_compositor->defaultSeat();
177 QWaylandSurface *focusSurface = dev->keyboardFocus();
179 offerFromCompositorToClient(
180 QWaylandSeatPrivate::get(dev)->dataDevice()->resourceMap().value(focusSurface->waylandClient())->handle);
185 if (!m_compositorOwnsSelection)
188 wl_client *client = wl_resource_get_client(clientDataDeviceResource);
191 struct wl_resource *selectionOffer =
192 wl_resource_create(client, &wl_data_offer_interface, -1, 0);
193 wl_resource_set_implementation(selectionOffer, &compositor_offer_interface,
this,
nullptr);
194 wl_data_device_send_data_offer(clientDataDeviceResource, selectionOffer);
195 const auto formats = m_retainedData.formats();
196 for (
const QString &format : formats) {
197 QByteArray ba = format.toLatin1();
198 wl_data_offer_send_offer(selectionOffer, ba.constData());
200 wl_data_device_send_selection(clientDataDeviceResource, selectionOffer);
207 if (m_retainedData.formats().isEmpty())
210 m_compositorOwnsSelection =
true;
211 offerFromCompositorToClient(clientDataDeviceResource);
216 new DataSource(resource->client(), id, m_compositor->currentTimeMsecs());
219void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id,
struct ::wl_resource *seat)
221 QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat);
222 QWaylandSeatPrivate::get(input_device)->clientRequestedDataDevice(
this, resource->client(), id);
225void DataDeviceManager::comp_accept(wl_client *, wl_resource *, uint32_t,
const char *)
229void DataDeviceManager::comp_receive(wl_client *client, wl_resource *resource,
const char *mime_type, int32_t fd)
234 QByteArray content = QWaylandMimeHelper::getByteArray(&self->m_retainedData, QString::fromLatin1(mime_type));
235 if (!content.isEmpty()) {
237 if (f.open(fd, QIODevice::WriteOnly))
247QT_WARNING_DISABLE_GCC(
"-Wmissing-field-initializers")
260#include "moc_qwldatadevicemanager_p.cpp"
struct wl_display * display() const
void overrideSelection(const QMimeData &mimeData)
void sourceDestroyed(DataSource *source)
DataSource * currentSelectionSource()
void setCurrentSelectionSource(DataSource *source)
void data_device_manager_create_data_source(Resource *resource, uint32_t id) override
void setManager(DataDeviceManager *mgr)