summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Uwe Broulik <kde@privat.broulik.de>2023-11-13 17:33:12 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-12-04 21:14:02 +0000
commitfffacab6bccfceefcdb9b71f476924772271e41f (patch)
tree89b536e11dce98af798d64adb16ed0c1dc381df7
parenta86998052176e0c013540635ea51033f16e33e6f (diff)
QWaylandMimeData: Check text/x-moz-urls for UTF-16
And fall back to UTF-8 if it's not. When dragging a picture out of Chrome, it sends a simple URL as UTF-8 under text/x-moz-urls. QXcbMime has this fall-back, too but I originally didn't consider it necessary. Pick-to: 6.5 Change-Id: I52378cfc354de342623e5dd3f7e1d028951e8dab Reviewed-by: David Edmundson <davidedmundson@kde.org> (cherry picked from commit 7de5d7c05276c179c9951c718c6fc5ccd18982aa) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/client/qwaylanddataoffer.cpp33
-rw-r--r--tests/auto/client/datadevicev1/tst_datadevicev1.cpp42
2 files changed, 65 insertions, 10 deletions
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index b22887495..095df47e4 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -40,20 +40,33 @@ static QByteArray convertData(const QString &originalMime, const QString &newMim
// see also qtbase/src/plugins/platforms/xcb/qxcbmime.cpp
if (originalMime == uriList() && newMime == mozUrl()) {
if (data.size() > 1) {
- const QString str = QString::fromUtf16(
- reinterpret_cast<const char16_t *>(data.constData()), data.size() / 2);
- if (!str.isNull()) {
+ const quint8 byte0 = data.at(0);
+ const quint8 byte1 = data.at(1);
+
+ if ((byte0 == 0xff && byte1 == 0xfe) || (byte0 == 0xfe && byte1 == 0xff)
+ || (byte0 != 0 && byte1 == 0) || (byte0 == 0 && byte1 != 0)) {
QByteArray converted;
- const auto urls = QStringView{str}.split(u'\n');
- // Only the URL is interesting, skip the page title.
- for (int i = 0; i < urls.size(); i += 2) {
- const QUrl url(urls.at(i).trimmed().toString());
- if (url.isValid()) {
- converted += url.toEncoded();
- converted += "\r\n";
+ const QString str = QString::fromUtf16(
+ reinterpret_cast<const char16_t *>(data.constData()), data.size() / 2);
+ if (!str.isNull()) {
+ const auto urls = QStringView{str}.split(u'\n');
+ // Only the URL is interesting, skip the page title.
+ for (int i = 0; i < urls.size(); i += 2) {
+ const QUrl url(urls.at(i).trimmed().toString());
+ if (url.isValid()) {
+ converted += url.toEncoded();
+ converted += "\r\n";
+ }
}
}
return converted;
+ // 8 byte encoding, remove a possible 0 at the end.
+ } else {
+ QByteArray converted = data;
+ if (converted.endsWith('\0'))
+ converted.chop(1);
+ converted += "\r\n";
+ return converted;
}
}
}
diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
index bb831564a..3464d0d78 100644
--- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
+++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
@@ -32,6 +32,7 @@ private slots:
void pasteAscii();
void pasteUtf8();
void pasteMozUrl();
+ void pasteSingleUtf8MozUrl();
void destroysPreviousSelection();
void destroysSelectionWithSurface();
void destroysSelectionOnLeave();
@@ -167,6 +168,47 @@ void tst_datadevicev1::pasteMozUrl()
QCOMPARE(window.m_urls.at(1), QUrl("https://www.example.com/"));
}
+void tst_datadevicev1::pasteSingleUtf8MozUrl()
+{
+ class Window : public QRasterWindow {
+ public:
+ void mousePressEvent(QMouseEvent *) override { m_urls = QGuiApplication::clipboard()->mimeData()->urls(); }
+ QList<QUrl> m_urls;
+ };
+
+ Window window;
+ window.resize(64, 64);
+ window.show();
+
+ QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
+ exec([&] {
+ auto *client = xdgSurface()->resource()->client();
+ auto *offer = dataDevice()->sendDataOffer(client, {"text/x-moz-url"});
+ connect(offer, &DataOffer::receive, [](QString mimeType, int fd) {
+ QFile file;
+ file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle);
+ QCOMPARE(mimeType, "text/x-moz-url");
+ const QString content("https://www.qt.io/");
+ file.write(content.toUtf8());
+ file.close();
+ });
+ dataDevice()->sendSelection(offer);
+
+ auto *surface = xdgSurface()->m_surface;
+ keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
+
+ pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client);
+ pointer()->sendButton(client, BTN_LEFT, 1);
+ pointer()->sendFrame(client);
+ pointer()->sendButton(client, BTN_LEFT, 0);
+ pointer()->sendFrame(client);
+ });
+
+ QTRY_COMPARE(window.m_urls.count(), 1);
+ QCOMPARE(window.m_urls.at(0), QUrl("https://www.qt.io/"));
+}
+
void tst_datadevicev1::destroysPreviousSelection()
{
QRasterWindow window;