7#include <QtWaylandCompositor/QWaylandCompositor>
9#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
10#include <QtWaylandCompositor/private/qwaylandseat_p.h>
14#include "qwaylandmimehelper_p.h"
16#include <QtCore/QDebug>
17#include <QtCore/QSocketNotifier>
19#include <QtCore/private/qcore_unix_p.h>
20#include <QtCore/QFile>
27 : wl_data_device_manager(compositor->display(), 1)
28 , m_compositor(compositor)
34 if (m_current_selection_source && source
35 && m_current_selection_source->time() > source->time()) {
36 qDebug() <<
"Trying to set older selection";
40 m_compositorOwnsSelection =
false;
42 finishReadFromClient();
44 m_current_selection_source = source;
54 if (source && m_compositor->retainedSelectionEnabled()) {
55 m_retainedData.clear();
56 m_retainedReadIndex = 0;
63 if (m_current_selection_source == source) {
64 finishReadFromClient();
65 m_current_selection_source =
nullptr;
71 QList<QString> offers = m_current_selection_source->mimeTypes();
72 finishReadFromClient();
73 if (m_retainedReadIndex >= offers.size()) {
74 QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
77 QString mimeType = offers.at(m_retainedReadIndex);
78 m_retainedReadBuf.clear();
81 qWarning(
"Clipboard: Failed to create pipe");
84 fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL, 0) | O_NONBLOCK);
85 m_current_selection_source->send(mimeType, fd[1]);
86 m_retainedReadNotifier =
new QSocketNotifier(fd[0], QSocketNotifier::Read,
this);
87 connect(m_retainedReadNotifier, &QSocketNotifier::activated,
this, &DataDeviceManager::readFromClient);
93 if (m_retainedReadNotifier) {
95 int fd = m_retainedReadNotifier->socket();
96 delete m_retainedReadNotifier;
101 m_obsoleteRetainedReadNotifiers.append(m_retainedReadNotifier);
103 m_retainedReadNotifier =
nullptr;
109 static char buf[4096];
110 int obsCount = m_obsoleteRetainedReadNotifiers.size();
111 for (
int i = 0; i < obsCount; ++i) {
112 QSocketNotifier *sn = m_obsoleteRetainedReadNotifiers.at(i);
113 if (sn->socket() == fd) {
119 n = QT_READ(fd, buf,
sizeof buf);
121 if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
122 m_obsoleteRetainedReadNotifiers.removeAt(i);
129 int n = QT_READ(fd, buf,
sizeof buf);
131 if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
132 finishReadFromClient(
true);
133 QList<QString> offers = m_current_selection_source->mimeTypes();
134 QString mimeType = offers.at(m_retainedReadIndex);
135 m_retainedData.setData(mimeType, m_retainedReadBuf);
136 ++m_retainedReadIndex;
140 m_retainedReadBuf.append(buf, n);
146 return m_current_selection_source;
151 return m_compositor->display();
156 const QStringList formats = mimeData.formats();
157 if (formats.isEmpty())
160 m_retainedData.clear();
161 for (
const QString &format : formats)
162 m_retainedData.setData(format, mimeData.data(format));
164 QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
166 m_compositorOwnsSelection =
true;
168 if (m_current_selection_source) {
169 finishReadFromClient();
174 m_current_selection_source =
nullptr;
177 QWaylandSeat *dev = m_compositor->defaultSeat();
178 QWaylandSurface *focusSurface = dev->keyboardFocus();
180 offerFromCompositorToClient(
181 QWaylandSeatPrivate::get(dev)->dataDevice()->resourceMap().value(focusSurface->waylandClient())->handle);
186 if (!m_compositorOwnsSelection)
189 wl_client *client = wl_resource_get_client(clientDataDeviceResource);
192 struct wl_resource *selectionOffer =
193 wl_resource_create(client, &wl_data_offer_interface, -1, 0);
194 wl_resource_set_implementation(selectionOffer, &compositor_offer_interface,
this,
nullptr);
195 wl_data_device_send_data_offer(clientDataDeviceResource, selectionOffer);
196 const auto formats = m_retainedData.formats();
197 for (
const QString &format : formats) {
198 QByteArray ba = format.toLatin1();
199 wl_data_offer_send_offer(selectionOffer, ba.constData());
201 wl_data_device_send_selection(clientDataDeviceResource, selectionOffer);
208 if (m_retainedData.formats().isEmpty())
211 m_compositorOwnsSelection =
true;
212 offerFromCompositorToClient(clientDataDeviceResource);
217 new DataSource(resource->client(), id, m_compositor->currentTimeMsecs());
220void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id,
struct ::wl_resource *seat)
222 QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat);
223 QWaylandSeatPrivate::get(input_device)->clientRequestedDataDevice(
this, resource->client(), id);
226void DataDeviceManager::comp_accept(wl_client *, wl_resource *, uint32_t,
const char *)
230void DataDeviceManager::comp_receive(wl_client *client, wl_resource *resource,
const char *mime_type, int32_t fd)
235 QByteArray content = QWaylandMimeHelper::getByteArray(&self->m_retainedData, QString::fromLatin1(mime_type));
236 if (!content.isEmpty()) {
238 if (f.open(fd, QIODevice::WriteOnly))
248QT_WARNING_DISABLE_GCC(
"-Wmissing-field-initializers")
261#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)