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)  | 
