diff options
author | Lorn Potter <[email protected]> | 2023-10-19 16:33:25 +1000 |
---|---|---|
committer | Lorn Potter <[email protected]> | 2023-12-22 08:06:08 +1000 |
commit | 1f7d222cec1e8659d7bfa19ec3c1098a2bc00f35 (patch) | |
tree | c476f09ec2849c525805b9d6d714fff07b23fee4 | |
parent | 8cc84a1386b77701ebc9c9d4efbc1b033d0e326b (diff) |
wasm: write file to storage on drop
Change-Id: Ibd1b5d623da07ad611cce577929a23ba991b6738
Pick-to: 6.7
Reviewed-by: Morten Johan Sørvig <[email protected]>
-rw-r--r-- | src/plugins/platforms/wasm/qwasmclipboard.cpp | 29 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmclipboard.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmdom.cpp | 62 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmdom.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmdrag.cpp | 42 |
5 files changed, 102 insertions, 37 deletions
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp index 9c7088067eb..786267277af 100644 --- a/src/plugins/platforms/wasm/qwasmclipboard.cpp +++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp @@ -70,16 +70,7 @@ static void qClipboardPasteTo(val event) { event.call<void>("preventDefault"); // prevent browser from handling drop event - static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr; - dom::DataTransfer transfer(event["clipboardData"]); - auto data = transfer.toMimeDataWithFile(); - if (data->formats().isEmpty()) - return; - // Persist clipboard data so that the app can read it when handling the CTRL+V - QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(data, - QClipboard::Clipboard); - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V, - Qt::ControlModifier, "V"); + QWasmIntegration::get()->getWasmClipboard()->sendClipboardData(event); } EMSCRIPTEN_BINDINGS(qtClipboardModule) { @@ -292,4 +283,22 @@ void QWasmClipboard::writeToClipboard() document.call<val>("execCommand", val("copy")); } +void QWasmClipboard::sendClipboardData(emscripten::val event) +{ + dom::DataTransfer transfer(event["clipboardData"]); + QMimeData *mData; + const auto pointerCallback = std::function([&](QMimeData &data) { + mData = &data; + // Persist clipboard data so that the app can read it when handling the CTRL+V + QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(mData, + QClipboard::Clipboard); + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V, + Qt::ControlModifier, "V"); + QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_V, + Qt::ControlModifier, "V"); + }); + + transfer.toMimeDataWithFile(pointerCallback); // mimedata + +} QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h index 11e7e9f714d..86618dd5604 100644 --- a/src/plugins/platforms/wasm/qwasmclipboard.h +++ b/src/plugins/platforms/wasm/qwasmclipboard.h @@ -38,6 +38,7 @@ public: ProcessKeyboardResult processKeyboard(const KeyEvent &event); static void installEventHandlers(const emscripten::val &target); bool hasClipboardApi(); + void sendClipboardData(emscripten::val event); private: void initClipboardPermissions(); diff --git a/src/plugins/platforms/wasm/qwasmdom.cpp b/src/plugins/platforms/wasm/qwasmdom.cpp index 845aef3bc10..a2a9c129771 100644 --- a/src/plugins/platforms/wasm/qwasmdom.cpp +++ b/src/plugins/platforms/wasm/qwasmdom.cpp @@ -3,7 +3,6 @@ #include "qwasmdom.h" -#include <QMimeData> #include <QtCore/qpoint.h> #include <QtCore/qrect.h> #include <QtGui/qimage.h> @@ -15,6 +14,9 @@ QT_BEGIN_NAMESPACE +// this needs to live outside the life of DataTransfer +Q_GLOBAL_STATIC(QMimeData, resultMimeData); + namespace dom { namespace { std::string dropActionToDropEffect(Qt::DropAction action) @@ -36,7 +38,9 @@ std::string dropActionToDropEffect(Qt::DropAction action) } } // namespace -DataTransfer::DataTransfer(emscripten::val webDataTransfer) : webDataTransfer(webDataTransfer) { } +DataTransfer::DataTransfer(emscripten::val webDataTransfer) + : webDataTransfer(webDataTransfer) { +} DataTransfer::~DataTransfer() = default; @@ -78,10 +82,9 @@ void DataTransfer::setDataFromMimeData(const QMimeData &mimeData) } } -QMimeData *DataTransfer::toMimeDataWithFile() +QMimeData *DataTransfer::toMimeDataWithFile(std::function<void(QMimeData &)> callback) { - QMimeData *resultMimeData = new QMimeData(); // QScopedPointer? - + resultMimeData->clear(); enum class ItemKind { File, String, @@ -99,8 +102,43 @@ QMimeData *DataTransfer::toMimeDataWithFile() case ItemKind::File: { m_webFile = item.call<emscripten::val>("getAsFile"); qstdweb::File webfile(m_webFile); - QUrl fileUrl(QStringLiteral("file:///") + QString::fromStdString(webfile.name())); - uriList.append(fileUrl); + if (webfile.size() == 0 + || webfile.size() > 1e+9) { // limit file size to 1 GB + qWarning() << "Something happened, File size is" << webfile.size(); + continue; + } + QByteArray fileContent(webfile.size(), Qt::Uninitialized); + QString mimeFormat = QString::fromStdString(webfile.type()); + QString fileName = QString::fromStdString(webfile.name()); + + // there's a file, now read it + webfile.stream(fileContent.data(), [=]() { + QList<QUrl> fileUriList; + if (!fileContent.isEmpty()) { + if (mimeFormat.contains("image/")) { + QImage image; + image.loadFromData(fileContent, nullptr); + resultMimeData->setImageData(image); + } else { + QUrl fileUrl(QStringLiteral("file:///") + + QString::fromStdString(webfile.name())); + fileUriList.append(fileUrl); + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) { + qWarning() << "File was not opened"; + return; + } + + if (file.write(fileContent) < 0) + qWarning() << "Write failed"; + + file.close(); + resultMimeData->setUrls(fileUriList); + } + callback(*resultMimeData); + } + }); + break; } case ItemKind::String: @@ -131,9 +169,15 @@ QMimeData *DataTransfer::toMimeDataWithFile() } break; } - } - if (!uriList.isEmpty()) + } // end items + + if (!uriList.isEmpty()) { resultMimeData->setUrls(uriList); + } + + if (resultMimeData->formats().length() > 0) + callback(*resultMimeData); + return resultMimeData; } diff --git a/src/plugins/platforms/wasm/qwasmdom.h b/src/plugins/platforms/wasm/qwasmdom.h index 3ccafba534c..37c7bc97f13 100644 --- a/src/plugins/platforms/wasm/qwasmdom.h +++ b/src/plugins/platforms/wasm/qwasmdom.h @@ -15,13 +15,14 @@ #include <memory> #include <string> +#include <QMimeData> QT_BEGIN_NAMESPACE namespace qstdweb { struct CancellationFlag; } -class QMimeData; + class QPoint; class QRect; @@ -35,7 +36,7 @@ struct DataTransfer DataTransfer &operator=(const DataTransfer &other); DataTransfer &operator=(DataTransfer &&other); - QMimeData *toMimeDataWithFile() ; + QMimeData *toMimeDataWithFile(std::function<void(QMimeData &)> callback); QMimeData *toMimeDataPreview(); void setDragImage(emscripten::val element, const QPoint &hotspot); void setData(std::string format, std::string data); diff --git a/src/plugins/platforms/wasm/qwasmdrag.cpp b/src/plugins/platforms/wasm/qwasmdrag.cpp index 82f225158c8..b765fe8268d 100644 --- a/src/plugins/platforms/wasm/qwasmdrag.cpp +++ b/src/plugins/platforms/wasm/qwasmdrag.cpp @@ -14,6 +14,7 @@ #include <QtCore/qeventloop.h> #include <QtCore/qmimedata.h> #include <QtCore/qtimer.h> +#include <QFile> #include <functional> #include <string> @@ -152,22 +153,31 @@ void QWasmDrag::onNativeDrop(DragEvent *event) const QPointF pointInTargetWindowCoords = event->targetWindow->mapFromGlobal(pointInQtScreen); const Qt::DropActions actions = m_dragState - ? m_dragState->drag->supportedActions() - : (Qt::DropAction::CopyAction | Qt::DropAction::MoveAction - | Qt::DropAction::LinkAction); - - auto dropResponse = std::make_shared<QPlatformDropQtResponse>(true, Qt::DropAction::CopyAction); - QMimeData *data = event->dataTransfer.toMimeDataWithFile(); - *dropResponse = QWindowSystemInterface::handleDrop(event->targetWindow, data, - pointInTargetWindowCoords.toPoint(), actions, - event->mouseButton, event->modifiers); - - if (dropResponse->isAccepted()) { - event->acceptDrop(); - event->dataTransfer.setDropAction(dropResponse->acceptedAction()); - - m_dragState->dropAction = dropResponse->acceptedAction(); - } + ? m_dragState->drag->supportedActions() + : (Qt::DropAction::CopyAction | Qt::DropAction::MoveAction + | Qt::DropAction::LinkAction); + Qt::MouseButton mouseButton = event->mouseButton; + QFlags<Qt::KeyboardModifier> modifiers = event->modifiers; + + const auto pointerCallback = std::function([&, wasmWindow, pointInTargetWindowCoords, + actions, mouseButton, modifiers](QMimeData &data) { + if (data.formats().count() == 0) + return; + auto dropResponse = std::make_shared<QPlatformDropQtResponse>(true, Qt::DropAction::CopyAction); + + *dropResponse = QWindowSystemInterface::handleDrop(wasmWindow->window(), &data, + pointInTargetWindowCoords.toPoint(), actions, + mouseButton, modifiers); + + if (dropResponse->isAccepted()) { +// event->acceptDrop(); // boom +// event->dataTransfer.setDropAction(dropResponse->acceptedAction()); + + m_dragState->dropAction = dropResponse->acceptedAction(); + } + }); + + event->dataTransfer.toMimeDataWithFile(pointerCallback); } void QWasmDrag::onNativeDragFinished(DragEvent *event) |