diff options
author | Kai Uwe Broulik <kde@privat.broulik.de> | 2023-11-13 17:33:12 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-12-04 21:14:02 +0000 |
commit | fffacab6bccfceefcdb9b71f476924772271e41f (patch) | |
tree | 89b536e11dce98af798d64adb16ed0c1dc381df7 | |
parent | a86998052176e0c013540635ea51033f16e33e6f (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.cpp | 33 | ||||
-rw-r--r-- | tests/auto/client/datadevicev1/tst_datadevicev1.cpp | 42 |
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; |