Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:significant reason:default
4
5
#
include
"qwaylanddataoffer_p.h"
6
#
include
"qwaylanddatadevicemanager_p.h"
7
#
include
"qwaylanddisplay_p.h"
8
#
if
QT_CONFIG
(
xdg_desktop_portal_file_transfer
)
9
#
include
<
QtGui
/
private
/
qxdgdesktopportalfiletransfer_p
.
h
>
10
#
endif
11
12
#
include
<
QtCore
/
private
/
qcore_unix_p
.
h
>
13
#
include
<
QtGui
/
private
/
qguiapplication_p
.
h
>
14
#
include
<
qpa
/
qplatformclipboard
.
h
>
15
16
#
include
<
QtCore
/
QDebug
>
17
18
using
namespace
std::chrono;
19
using
namespace
Qt::StringLiterals;
20
QT_BEGIN_NAMESPACE
21
22
namespace
QtWaylandClient
{
23
24
static
QString
plainText
()
25
{
26
return
QStringLiteral(
"text/plain"
);
27
}
28
29
static
QString
utf8Text
()
30
{
31
return
QStringLiteral(
"text/plain;charset=utf-8"
);
32
}
33
34
static
QString
uriList
()
35
{
36
return
QStringLiteral(
"text/uri-list"
);
37
}
38
39
static
QString
mozUrl
()
40
{
41
return
QStringLiteral(
"text/x-moz-url"
);
42
}
43
44
static
QString
portalFileTransfer
()
45
{
46
return
QStringLiteral(
"application/vnd.portal.filetransfer"
);
47
}
48
49
static
QByteArray
convertData
(
const
QString &originalMime,
const
QString &newMime,
const
QByteArray &data)
50
{
51
if
(originalMime == newMime)
52
return
data;
53
54
// Convert text/x-moz-url, which is an UTF-16 string of
55
// URL and page title pairs, all separated by line breaks, to text/uri-list.
56
// see also qtbase/src/plugins/platforms/xcb/qxcbmime.cpp
57
if
(originalMime == uriList() && newMime == mozUrl()) {
58
if
(data.size() > 1) {
59
const
quint8 byte0 = data.at(0);
60
const
quint8 byte1 = data.at(1);
61
62
if
((byte0 == 0xff && byte1 == 0xfe) || (byte0 == 0xfe && byte1 == 0xff)
63
|| (byte0 != 0 && byte1 == 0) || (byte0 == 0 && byte1 != 0)) {
64
QByteArray converted;
65
const
QString str = QString::fromUtf16(
66
reinterpret_cast
<
const
char16_t
*>(data.constData()), data.size() / 2);
67
if
(!str.isNull()) {
68
const
auto
urls = QStringView{str}.split(u'\n');
69
// Only the URL is interesting, skip the page title.
70
for
(
int
i = 0; i < urls.size(); i += 2) {
71
const
QUrl url(urls.at(i).trimmed().toString());
72
if
(url.isValid()) {
73
converted += url.toEncoded();
74
converted +=
"\r\n"
;
75
}
76
}
77
}
78
return
converted;
79
// 8 byte encoding, remove a possible 0 at the end.
80
}
else
{
81
QByteArray converted = data;
82
if
(converted.endsWith(
'\0'
))
83
converted.chop(1);
84
converted +=
"\r\n"
;
85
return
converted;
86
}
87
}
88
}
89
return
data;
90
}
91
92
QWaylandDataOffer
::
QWaylandDataOffer
(
QWaylandDisplay
*
display
,
struct
::wl_data_offer *
offer
)
93
:
QtWayland
::
wl_data_offer
(
offer
)
94
,
m_display
(
display
)
95
,
m_mimeData
(
new
QWaylandMimeData
(
this
))
96
{
97
}
98
99
QWaylandDataOffer
::~
QWaylandDataOffer
()
100
{
101
destroy
();
102
}
103
104
105
QString
QWaylandDataOffer
::
firstFormat
()
const
106
{
107
if
(
m_mimeData
->
formats
().
isEmpty
())
108
return
QString
();
109
110
return
m_mimeData
->
formats
().
first
();
111
}
112
113
QMimeData
*
QWaylandDataOffer
::
mimeData
()
114
{
115
return
m_mimeData
.
get
();
116
}
117
118
Qt
::
DropActions
QWaylandDataOffer
::
supportedActions
()
const
119
{
120
if
(
version
() < 3) {
121
return
Qt
::
MoveAction
|
Qt
::
CopyAction
;
122
}
123
124
return
m_supportedActions
;
125
}
126
127
void
QWaylandDataOffer
::
startReceiving
(
const
QString
&
mimeType
,
int
fd
)
128
{
129
receive
(
mimeType
,
fd
);
130
wl_display_flush
(
m_display
->
wl_display
());
131
}
132
133
void
QWaylandDataOffer
::
data_offer_offer
(
const
QString
&
mime_type
)
134
{
135
m_mimeData
->
appendFormat
(
mime_type
);
136
}
137
138
void
QWaylandDataOffer
::
data_offer_action
(
uint32_t
dnd_action
)
139
{
140
Q_UNUSED
(
dnd_action
);
141
// This is the compositor telling the drag target what action it should perform
142
// It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
143
}
144
145
void
QWaylandDataOffer
::
data_offer_source_actions
(
uint32_t
source_actions
)
146
{
147
m_supportedActions
=
Qt
::
DropActions
();
148
if
(
source_actions
&
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE
)
149
m_supportedActions
|=
Qt
::
MoveAction
;
150
if
(
source_actions
&
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY
)
151
m_supportedActions
|=
Qt
::
CopyAction
;
152
}
153
154
QWaylandMimeData
::
QWaylandMimeData
(
QWaylandAbstractDataOffer
*dataOffer)
155
: m_dataOffer(dataOffer)
156
{
157
}
158
159
QWaylandMimeData
::~
QWaylandMimeData
()
160
{
161
}
162
163
void
QWaylandMimeData
::
appendFormat
(
const
QString &mimeType)
164
{
165
// "DELETE" is a potential leftover from XdndActionMode sent by e.g. Firefox, ignore it.
166
if
(mimeType != QLatin1String(
"DELETE"
)) {
167
m_types << mimeType;
168
m_data.remove(mimeType);
// Clear previous contents
169
}
170
}
171
172
bool
QWaylandMimeData
::
hasFormat_sys
(
const
QString &mimeType)
const
173
{
174
return
formats().contains(mimeType);
175
}
176
177
QStringList
QWaylandMimeData
::
formats_sys
()
const
178
{
179
QStringList types;
180
types.reserve(m_types.size());
181
182
for
(
const
QString &type : m_types) {
183
QString mime = type;
184
185
if
(mime == utf8Text()) {
186
mime = plainText();
187
}
else
if
(mime == mozUrl()) {
188
mime = uriList();
189
}
190
191
if
(!types.contains(mime)) {
192
types << mime;
193
}
194
}
195
196
return
types;
197
}
198
199
QVariant
QWaylandMimeData
::
retrieveData_sys
(
const
QString &mimeType, QMetaType type)
const
200
{
201
Q_UNUSED(type);
202
auto
it = m_data.constFind(mimeType);
203
if
(it != m_data.constEnd())
204
return
*it;
205
206
QString mime = mimeType;
207
208
if
(!m_types.contains(mimeType)) {
209
if
(mimeType == plainText() && m_types.contains(utf8Text()))
210
mime = utf8Text();
211
else
if
(mimeType == uriList() && m_types.contains(mozUrl()))
212
mime = mozUrl();
213
else
214
return
QVariant();
215
}
216
217
#
if
QT_CONFIG
(
xdg_desktop_portal_file_transfer
)
218
const
bool
retrieveFilesFromPortal = mimeType == uriList() && m_types.contains(QXdgDesktopPortalFileTransfer::fileTransferMimeType());
219
if
(retrieveFilesFromPortal) {
220
mime = QXdgDesktopPortalFileTransfer::fileTransferMimeType();
221
}
222
#
endif
223
224
QByteArray content = readData(mime).value_or(QByteArray());
225
226
content = convertData(mimeType, mime, content);
227
228
#
if
QT_CONFIG
(
xdg_desktop_portal_file_transfer
)
229
if
(retrieveFilesFromPortal && !content.isEmpty()) {
230
const
auto
paths = QXdgDesktopPortalFileTransfer::retrieveFiles(QString::fromUtf8(content));
231
if
(!paths.empty()) {
232
content.clear();
233
for
(
const
auto
&path : paths) {
234
content += QUrl::fromLocalFile(path).toEncoded();
235
content +=
"\r\n"
;
236
}
237
}
else
{
238
qCInfo(lcQpaWayland) <<
"Failed retrieving files, falling back to uris"
;
239
content = readData(mime).value_or(QByteArray());
240
}
241
}
242
#
endif
243
244
if
(mimeType != portalFileTransfer())
245
m_data.insert(mimeType, content);
246
247
return
content;
248
}
249
250
std::optional<QByteArray>
QWaylandMimeData
::readData(
const
QString &mimeType)
const
251
{
252
int
pipefd[2];
253
if
(qt_safe_pipe(pipefd) == -1) {
254
qWarning(
"QWaylandMimeData: pipe2() failed"
);
255
return
std::nullopt;
256
}
257
258
m_dataOffer->startReceiving(mimeType, pipefd[1]);
259
260
close(pipefd[1]);
261
const
QScopeGuard closeGuard([fd = pipefd[0]] { close(fd); });
262
263
QByteArray data;
264
265
struct
pollfd readset;
266
readset.fd = pipefd[0];
267
readset.events = POLLIN;
268
269
Q_FOREVER {
270
int
ready = qt_safe_poll(&readset, 1, QDeadlineTimer(1s));
271
if
(ready < 0) {
272
qCWarning(lcQpaWayland) <<
"QWaylandDataOffer: qt_safe_poll() failed while reading data for mimeType %s"
, qPrintable(mimeType);
273
return
std::nullopt;
274
}
else
if
(ready == 0) {
275
qCWarning(lcQpaWayland,
"QWaylandDataOffer: timeout reading from pipe while reading data for mimeType %s"
, qPrintable(mimeType));
276
return
std::nullopt;
277
}
else
{
278
char
buf[4096];
279
int
n = QT_READ(pipefd[0], buf,
sizeof
buf);
280
281
if
(n < 0) {
282
qWarning(lcQpaWayland,
"QWaylandDataOffer: read() failed"
);
283
return
std::nullopt;
284
}
else
if
(n == 0) {
285
return
data;
286
}
else
if
(n > 0) {
287
data.append(buf, n);
288
}
289
}
290
}
291
}
292
293
}
294
295
QT_END_NAMESPACE
QtWaylandClient::QWaylandAbstractDataOffer
Definition
qwaylanddataoffer_p.h:39
QtWaylandClient::QWaylandMimeData
Definition
qwaylanddataoffer_p.h:73
QtWaylandClient::QWaylandMimeData::~QWaylandMimeData
~QWaylandMimeData() override
Definition
qwaylanddataoffer.cpp:159
QtWaylandClient::QWaylandMimeData::retrieveData_sys
QVariant retrieveData_sys(const QString &mimeType, QMetaType type) const override
Definition
qwaylanddataoffer.cpp:199
QtWaylandClient::QWaylandMimeData::appendFormat
void appendFormat(const QString &mimeType)
Definition
qwaylanddataoffer.cpp:163
QtWaylandClient::QWaylandMimeData::formats_sys
QStringList formats_sys() const override
Definition
qwaylanddataoffer.cpp:177
QtWaylandClient::QWaylandMimeData::QWaylandMimeData
QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
Definition
qwaylanddataoffer.cpp:154
QtWaylandClient::QWaylandMimeData::hasFormat_sys
bool hasFormat_sys(const QString &mimeType) const override
Definition
qwaylanddataoffer.cpp:172
QtWaylandClient
Definition
qwaylandclientextension.h:16
QtWaylandClient::portalFileTransfer
static QString portalFileTransfer()
Definition
qwaylanddataoffer.cpp:44
QtWaylandClient::convertData
static QByteArray convertData(const QString &originalMime, const QString &newMime, const QByteArray &data)
Definition
qwaylanddataoffer.cpp:49
QtWaylandClient::utf8Text
static QString utf8Text()
Definition
qwaylanddataoffer.cpp:29
QtWaylandClient::mozUrl
static QString mozUrl()
Definition
qwaylanddataoffer.cpp:39
QtWaylandClient::uriList
static QString uriList()
Definition
qwaylanddataoffer.cpp:34
QtWaylandClient::plainText
static QString plainText()
Definition
qwaylanddataoffer.cpp:24
qtbase
src
plugins
platforms
wayland
qwaylanddataoffer.cpp
Generated on
for Qt by
1.18.0