Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaylanddataoffer.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "qwaylanddisplay_p.h"
7
8#include <QtCore/private/qcore_unix_p.h>
9#include <QtGui/private/qguiapplication_p.h>
10#include <qpa/qplatformclipboard.h>
11
12#include <QtCore/QDebug>
13
14using namespace std::chrono;
15
17
18namespace QtWaylandClient {
19
21{
22 return QStringLiteral("text/plain;charset=utf-8");
23}
24
26{
27 return QStringLiteral("text/uri-list");
28}
29
31{
32 return QStringLiteral("text/x-moz-url");
33}
34
36{
37 return QStringLiteral("application/vnd.portal.filetransfer");
38}
39
40static QByteArray convertData(const QString &originalMime, const QString &newMime, const QByteArray &data)
41{
42 if (originalMime == newMime)
43 return data;
44
45 // Convert text/x-moz-url, which is an UTF-16 string of
46 // URL and page title pairs, all separated by line breaks, to text/uri-list.
47 // see also qtbase/src/plugins/platforms/xcb/qxcbmime.cpp
48 if (originalMime == uriList() && newMime == mozUrl()) {
49 if (data.size() > 1) {
50 const quint8 byte0 = data.at(0);
51 const quint8 byte1 = data.at(1);
52
53 if ((byte0 == 0xff && byte1 == 0xfe) || (byte0 == 0xfe && byte1 == 0xff)
54 || (byte0 != 0 && byte1 == 0) || (byte0 == 0 && byte1 != 0)) {
55 QByteArray converted;
57 reinterpret_cast<const char16_t *>(data.constData()), data.size() / 2);
58 if (!str.isNull()) {
59 const auto urls = QStringView{str}.split(u'\n');
60 // Only the URL is interesting, skip the page title.
61 for (int i = 0; i < urls.size(); i += 2) {
62 const QUrl url(urls.at(i).trimmed().toString());
63 if (url.isValid()) {
64 converted += url.toEncoded();
65 converted += "\r\n";
66 }
67 }
68 }
69 return converted;
70 // 8 byte encoding, remove a possible 0 at the end.
71 } else {
72 QByteArray converted = data;
73 if (converted.endsWith('\0'))
74 converted.chop(1);
75 converted += "\r\n";
76 return converted;
77 }
78 }
79 }
80
81 return data;
82}
83
85 : QtWayland::wl_data_offer(offer)
86 , m_display(display)
87 , m_mimeData(new QWaylandMimeData(this))
88{
89}
90
95
96
98{
99 if (m_mimeData->formats().isEmpty())
100 return QString();
101
102 return m_mimeData->formats().first();
103}
104
106{
107 return m_mimeData.data();
108}
109
111{
112 if (version() < 3) {
114 }
115
116 return m_supportedActions;
117}
118
120{
121 receive(mimeType, fd);
122 wl_display_flush(m_display->wl_display());
123}
124
126{
127 m_mimeData->appendFormat(mime_type);
128}
129
131{
132 Q_UNUSED(dnd_action);
133 // This is the compositor telling the drag target what action it should perform
134 // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
135}
136
138{
139 m_supportedActions = Qt::DropActions();
140 if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
141 m_supportedActions |= Qt::MoveAction;
142 if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
143 m_supportedActions |= Qt::CopyAction;
144}
145
147 : m_dataOffer(dataOffer)
148{
149}
150
154
156{
157 // "DELETE" is a potential leftover from XdndActionMode sent by e.g. Firefox, ignore it.
158 if (mimeType != QLatin1String("DELETE")) {
159 m_types << mimeType;
160 m_data.remove(mimeType); // Clear previous contents
161 }
162}
163
165{
166 if (m_types.contains(mimeType))
167 return true;
168
169 if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
170 return true;
171
172 if (mimeType == uriList() && m_types.contains(mozUrl()))
173 return true;
174
175 return false;
176}
177
179{
180 return m_types;
181}
182
184{
185 Q_UNUSED(type);
186
187 auto it = m_data.constFind(mimeType);
188 if (it != m_data.constEnd())
189 return *it;
190
192
193 if (!m_types.contains(mimeType)) {
194 if (mimeType == QStringLiteral("text/plain") && m_types.contains(utf8Text()))
195 mime = utf8Text();
196 else if (mimeType == uriList() && m_types.contains(mozUrl()))
197 mime = mozUrl();
198 else
199 return QVariant();
200 }
201
202 int pipefd[2];
203 if (qt_safe_pipe(pipefd) == -1) {
204 qWarning("QWaylandMimeData: pipe2() failed");
205 return QVariant();
206 }
207
208 m_dataOffer->startReceiving(mime, pipefd[1]);
209
210 close(pipefd[1]);
211
212 QByteArray content;
213 if (readData(pipefd[0], content) != 0) {
214 qWarning("QWaylandDataOffer: error reading data for mimeType %s", qPrintable(mimeType));
215 content = QByteArray();
216 }
217
218 close(pipefd[0]);
219
220 content = convertData(mimeType, mime, content);
221
223 m_data.insert(mimeType, content);
224
225 return content;
226}
227
228int QWaylandMimeData::readData(int fd, QByteArray &data) const
229{
230 struct pollfd readset;
231 readset.fd = fd;
232 readset.events = POLLIN;
233
234 Q_FOREVER {
235 int ready = qt_safe_poll(&readset, 1, QDeadlineTimer(1s));
236 if (ready < 0) {
237 qWarning() << "QWaylandDataOffer: qt_safe_poll() failed";
238 return -1;
239 } else if (ready == 0) {
240 qWarning("QWaylandDataOffer: timeout reading from pipe");
241 return -1;
242 } else {
243 char buf[4096];
244 int n = QT_READ(fd, buf, sizeof buf);
245
246 if (n < 0) {
247 qWarning("QWaylandDataOffer: read() failed");
248 return -1;
249 } else if (n == 0) {
250 return 0;
251 } else if (n > 0) {
252 data.append(buf, n);
253 }
254 }
255 }
256}
257
258}
259
\inmodule QtCore
Definition qbytearray.h:57
bool endsWith(char c) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:227
void chop(qsizetype n)
Removes n bytes from the end of the byte array.
\inmodule QtCore
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1299
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1219
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:8218
static QString fromUtf16(const char16_t *, qsizetype size=-1)
Definition qstring.cpp:6045
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
\inmodule QtCore
Definition qurl.h:94
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1882
QByteArray toEncoded(FormattingOptions options=FullyEncoded) const
Returns the encoded representation of the URL if it's valid; otherwise an empty QByteArray is returne...
Definition qurl.cpp:2967
\inmodule QtCore
Definition qvariant.h:65
virtual void startReceiving(const QString &mimeType, int fd)=0
QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
void data_offer_action(uint32_t dnd_action) override
void data_offer_offer(const QString &mime_type) override
void data_offer_source_actions(uint32_t source_actions) override
void startReceiving(const QString &mimeType, int fd) override
struct wl_display * wl_display() const
QVariant retrieveData_sys(const QString &mimeType, QMetaType type) const override
void appendFormat(const QString &mimeType)
QStringList formats_sys() const override
QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
bool hasFormat_sys(const QString &mimeType) const override
#define this
Definition dialogs.cpp:9
QString str
[2]
QSet< QString >::iterator it
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
static QString portalFileTransfer()
static QByteArray convertData(const QString &originalMime, const QString &newMime, const QByteArray &data)
static QString utf8Text()
static QString mozUrl()
static QString uriList()
@ CopyAction
@ MoveAction
int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline)
#define QT_READ
static int qt_safe_pipe(int pipefd[2], int flags=0)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
const char * mimeType
#define Q_FOREVER
Definition qforeach.h:70
#define qWarning
Definition qlogging.h:166
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint64 GLenum GLint fd
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define Q_UNUSED(x)
unsigned char quint8
Definition qtypes.h:46
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
QByteArray readData()