wasm: move DataTransfer to dom::
Change-Id: I069292154bafd1c08a0d0f2e8a62052f596a80f3 Done-with: Mikolaj.Boc@qt.io Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
d048249c33
commit
6b9270fd72
@ -376,112 +376,6 @@ bool jsHaveAsyncify() { return false; }
|
|||||||
bool jsHaveJspi() { return false; }
|
bool jsHaveJspi() { return false; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct DataTransferReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using DoneCallback = std::function<void(std::unique_ptr<QMimeData>)>;
|
|
||||||
|
|
||||||
static std::shared_ptr<CancellationFlag> read(emscripten::val webDataTransfer,
|
|
||||||
std::function<QVariant(QByteArray)> imageReader,
|
|
||||||
DoneCallback onCompleted)
|
|
||||||
{
|
|
||||||
auto cancellationFlag = std::make_shared<CancellationFlag>();
|
|
||||||
(new DataTransferReader(std::move(onCompleted), std::move(imageReader), cancellationFlag))
|
|
||||||
->read(webDataTransfer);
|
|
||||||
return cancellationFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
~DataTransferReader() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DataTransferReader(DoneCallback onCompleted, std::function<QVariant(QByteArray)> imageReader,
|
|
||||||
std::shared_ptr<CancellationFlag> cancellationFlag)
|
|
||||||
: mimeData(std::make_unique<QMimeData>()),
|
|
||||||
imageReader(std::move(imageReader)),
|
|
||||||
onCompleted(std::move(onCompleted)),
|
|
||||||
cancellationFlag(cancellationFlag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(emscripten::val webDataTransfer)
|
|
||||||
{
|
|
||||||
enum class ItemKind {
|
|
||||||
File,
|
|
||||||
String,
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto items = webDataTransfer["items"];
|
|
||||||
for (int i = 0; i < items["length"].as<int>(); ++i) {
|
|
||||||
const auto item = items[i];
|
|
||||||
const auto itemKind =
|
|
||||||
item["kind"].as<std::string>() == "string" ? ItemKind::String : ItemKind::File;
|
|
||||||
const auto itemMimeType = QString::fromStdString(item["type"].as<std::string>());
|
|
||||||
|
|
||||||
switch (itemKind) {
|
|
||||||
case ItemKind::File: {
|
|
||||||
++fileCount;
|
|
||||||
|
|
||||||
qstdweb::File file(item.call<emscripten::val>("getAsFile"));
|
|
||||||
|
|
||||||
QByteArray fileContent(file.size(), Qt::Uninitialized);
|
|
||||||
file.stream(fileContent.data(), [this, itemMimeType, fileContent]() {
|
|
||||||
if (!fileContent.isEmpty()) {
|
|
||||||
if (itemMimeType.startsWith("image/"_L1)) {
|
|
||||||
mimeData->setImageData(imageReader(fileContent));
|
|
||||||
} else {
|
|
||||||
mimeData->setData(itemMimeType, fileContent.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++doneCount;
|
|
||||||
onFileRead();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ItemKind::String:
|
|
||||||
if (itemMimeType.contains("STRING"_L1, Qt::CaseSensitive)
|
|
||||||
|| itemMimeType.contains("TEXT"_L1, Qt::CaseSensitive)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
QString a;
|
|
||||||
const QString data = QString::fromEcmaString(webDataTransfer.call<emscripten::val>(
|
|
||||||
"getData", emscripten::val(itemMimeType.toStdString())));
|
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
if (itemMimeType == "text/html"_L1)
|
|
||||||
mimeData->setHtml(data);
|
|
||||||
else if (itemMimeType.isEmpty() || itemMimeType == "text/plain"_L1)
|
|
||||||
mimeData->setText(data); // the type can be empty
|
|
||||||
else
|
|
||||||
mimeData->setData(itemMimeType, data.toLocal8Bit());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onFileRead()
|
|
||||||
{
|
|
||||||
Q_ASSERT(doneCount <= fileCount);
|
|
||||||
if (doneCount < fileCount)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::unique_ptr<DataTransferReader> deleteThisLater(this);
|
|
||||||
if (!cancellationFlag.expired())
|
|
||||||
onCompleted(std::move(mimeData));
|
|
||||||
}
|
|
||||||
|
|
||||||
int fileCount = 0;
|
|
||||||
int doneCount = 0;
|
|
||||||
std::unique_ptr<QMimeData> mimeData;
|
|
||||||
std::function<QVariant(QByteArray)> imageReader;
|
|
||||||
DoneCallback onCompleted;
|
|
||||||
|
|
||||||
std::weak_ptr<CancellationFlag> cancellationFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ArrayBuffer::ArrayBuffer(uint32_t size)
|
ArrayBuffer::ArrayBuffer(uint32_t size)
|
||||||
@ -948,13 +842,6 @@ bool canBlockCallingThread()
|
|||||||
return haveAsyncify() || !emscripten_is_main_runtime_thread();
|
return haveAsyncify() || !emscripten_is_main_runtime_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CancellationFlag>
|
|
||||||
readDataTransfer(emscripten::val webDataTransfer, std::function<QVariant(QByteArray)> imageReader,
|
|
||||||
std::function<void(std::unique_ptr<QMimeData>)> onDone)
|
|
||||||
{
|
|
||||||
return DataTransferReader::read(webDataTransfer, std::move(imageReader), std::move(onDone));
|
|
||||||
}
|
|
||||||
|
|
||||||
BlobIODevice::BlobIODevice(Blob blob)
|
BlobIODevice::BlobIODevice(Blob blob)
|
||||||
: m_blob(blob)
|
: m_blob(blob)
|
||||||
{
|
{
|
||||||
|
@ -290,11 +290,6 @@ namespace qstdweb {
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_CORE_EXPORT std::shared_ptr<CancellationFlag>
|
|
||||||
readDataTransfer(emscripten::val webObject, std::function<QVariant(QByteArray)> imageReader,
|
|
||||||
std::function<void(std::unique_ptr<QMimeData>)> onDone);
|
|
||||||
|
|
||||||
|
|
||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
template<class T>
|
template<class T>
|
||||||
T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
|
T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
|
||||||
|
@ -71,24 +71,15 @@ static void qClipboardPasteTo(val event)
|
|||||||
event.call<void>("preventDefault"); // prevent browser from handling drop event
|
event.call<void>("preventDefault"); // prevent browser from handling drop event
|
||||||
|
|
||||||
static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr;
|
static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr;
|
||||||
readDataCancellation = qstdweb::readDataTransfer(
|
dom::DataTransfer transfer(event["clipboardData"]);
|
||||||
event["clipboardData"],
|
auto data = transfer.toMimeDataWithFile();
|
||||||
[](QByteArray fileContent) {
|
if (data->formats().isEmpty())
|
||||||
QImage image;
|
return;
|
||||||
image.loadFromData(fileContent, nullptr);
|
// Persist clipboard data so that the app can read it when handling the CTRL+V
|
||||||
return image;
|
QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(data,
|
||||||
},
|
QClipboard::Clipboard);
|
||||||
[event](std::unique_ptr<QMimeData> data) {
|
QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
|
||||||
if (data->formats().isEmpty())
|
Qt::ControlModifier, "V");
|
||||||
return;
|
|
||||||
|
|
||||||
// Persist clipboard data so that the app can read it when handling the CTRL+V
|
|
||||||
QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(
|
|
||||||
data.release(), QClipboard::Clipboard);
|
|
||||||
|
|
||||||
QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
|
|
||||||
Qt::ControlModifier, "V");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
|
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
|
||||||
@ -300,4 +291,5 @@ void QWasmClipboard::writeToClipboard()
|
|||||||
val document = val::global("document");
|
val document = val::global("document");
|
||||||
document.call<val>("execCommand", val("copy"));
|
document.call<val>("execCommand", val("copy"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include <qpa/qplatformclipboard.h>
|
#include <qpa/qplatformclipboard.h>
|
||||||
|
#include <private/qstdweb_p.h>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
|
||||||
#include <emscripten/bind.h>
|
#include <emscripten/bind.h>
|
||||||
|
@ -8,12 +8,152 @@
|
|||||||
#include <QtCore/qrect.h>
|
#include <QtCore/qrect.h>
|
||||||
#include <QtGui/qimage.h>
|
#include <QtGui/qimage.h>
|
||||||
#include <private/qstdweb_p.h>
|
#include <private/qstdweb_p.h>
|
||||||
|
#include <QtCore/qurl.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <emscripten/wire.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
namespace {
|
||||||
|
std::string dropActionToDropEffect(Qt::DropAction action)
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case Qt::DropAction::CopyAction:
|
||||||
|
return "copy";
|
||||||
|
case Qt::DropAction::IgnoreAction:
|
||||||
|
return "none";
|
||||||
|
case Qt::DropAction::LinkAction:
|
||||||
|
return "link";
|
||||||
|
case Qt::DropAction::MoveAction:
|
||||||
|
case Qt::DropAction::TargetMoveAction:
|
||||||
|
return "move";
|
||||||
|
case Qt::DropAction::ActionMask:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
DataTransfer::DataTransfer(emscripten::val webDataTransfer) : webDataTransfer(webDataTransfer) { }
|
||||||
|
|
||||||
|
DataTransfer::~DataTransfer() = default;
|
||||||
|
|
||||||
|
DataTransfer::DataTransfer(const DataTransfer &other) = default;
|
||||||
|
|
||||||
|
DataTransfer::DataTransfer(DataTransfer &&other) = default;
|
||||||
|
|
||||||
|
DataTransfer &DataTransfer::operator=(const DataTransfer &other) = default;
|
||||||
|
|
||||||
|
DataTransfer &DataTransfer::operator=(DataTransfer &&other) = default;
|
||||||
|
|
||||||
|
void DataTransfer::setDragImage(emscripten::val element, const QPoint &hotspot)
|
||||||
|
{
|
||||||
|
webDataTransfer.call<void>("setDragImage", element, emscripten::val(hotspot.x()),
|
||||||
|
emscripten::val(hotspot.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataTransfer::setData(std::string format, std::string data)
|
||||||
|
{
|
||||||
|
webDataTransfer.call<void>("setData", emscripten::val(std::move(format)),
|
||||||
|
emscripten::val(std::move(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataTransfer::setDropAction(Qt::DropAction action)
|
||||||
|
{
|
||||||
|
webDataTransfer.set("dropEffect", emscripten::val(dropActionToDropEffect(action)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataTransfer::setDataFromMimeData(const QMimeData &mimeData)
|
||||||
|
{
|
||||||
|
for (const auto &format : mimeData.formats()) {
|
||||||
|
auto data = mimeData.data(format);
|
||||||
|
|
||||||
|
auto encoded = format.startsWith("text/")
|
||||||
|
? QString::fromLocal8Bit(data).toStdString()
|
||||||
|
: "QB64" + QString::fromLocal8Bit(data.toBase64()).toStdString();
|
||||||
|
|
||||||
|
setData(format.toStdString(), std::move(encoded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData *DataTransfer::toMimeDataWithFile()
|
||||||
|
{
|
||||||
|
QMimeData *resultMimeData = new QMimeData(); // QScopedPointer?
|
||||||
|
|
||||||
|
enum class ItemKind {
|
||||||
|
File,
|
||||||
|
String,
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto items = webDataTransfer["items"];
|
||||||
|
QList<QUrl> uriList;
|
||||||
|
for (int i = 0; i < items["length"].as<int>(); ++i) {
|
||||||
|
const auto item = items[i];
|
||||||
|
const auto itemKind =
|
||||||
|
item["kind"].as<std::string>() == "string" ? ItemKind::String : ItemKind::File;
|
||||||
|
const auto itemMimeType = QString::fromStdString(item["type"].as<std::string>());
|
||||||
|
|
||||||
|
switch (itemKind) {
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ItemKind::String:
|
||||||
|
if (itemMimeType.contains("STRING", Qt::CaseSensitive)
|
||||||
|
|| itemMimeType.contains("TEXT", Qt::CaseSensitive)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QString a;
|
||||||
|
QString data = QString::fromEcmaString(webDataTransfer.call<emscripten::val>(
|
||||||
|
"getData", emscripten::val(itemMimeType.toStdString())));
|
||||||
|
|
||||||
|
if (!data.isEmpty()) {
|
||||||
|
if (itemMimeType == "text/html")
|
||||||
|
resultMimeData->setHtml(data);
|
||||||
|
else if (itemMimeType.isEmpty() || itemMimeType == "text/plain")
|
||||||
|
resultMimeData->setText(data); // the type can be empty
|
||||||
|
else {
|
||||||
|
// TODO improve encoding
|
||||||
|
if (data.startsWith("QB64")) {
|
||||||
|
data.remove(0, 4);
|
||||||
|
resultMimeData->setData(itemMimeType,
|
||||||
|
QByteArray::fromBase64(QByteArray::fromStdString(
|
||||||
|
data.toStdString())));
|
||||||
|
} else {
|
||||||
|
resultMimeData->setData(itemMimeType, data.toLocal8Bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!uriList.isEmpty())
|
||||||
|
resultMimeData->setUrls(uriList);
|
||||||
|
return resultMimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData *DataTransfer::toMimeDataPreview()
|
||||||
|
{
|
||||||
|
auto data = new QMimeData();
|
||||||
|
|
||||||
|
QList<QUrl> uriList;
|
||||||
|
for (int i = 0; i < webDataTransfer["items"]["length"].as<int>(); ++i) {
|
||||||
|
const auto item = webDataTransfer["items"][i];
|
||||||
|
if (item["kind"].as<std::string>() == "file") {
|
||||||
|
uriList.append(QUrl("blob://placeholder"));
|
||||||
|
} else {
|
||||||
|
const auto itemMimeType = QString::fromStdString(item["type"].as<std::string>());
|
||||||
|
data->setData(itemMimeType, QByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data->setUrls(uriList);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
|
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include <QtCore/qtconfigmacros.h>
|
#include <QtCore/qtconfigmacros.h>
|
||||||
#include <QtCore/QPointF>
|
#include <QtCore/QPointF>
|
||||||
|
#include <private/qstdweb_p.h>
|
||||||
|
#include <QtCore/qnamespace.h>
|
||||||
|
|
||||||
#include <emscripten/val.h>
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
@ -15,10 +17,36 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace qstdweb {
|
||||||
|
struct CancellationFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QMimeData;
|
||||||
class QPoint;
|
class QPoint;
|
||||||
class QRect;
|
class QRect;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
struct DataTransfer
|
||||||
|
{
|
||||||
|
explicit DataTransfer(emscripten::val webDataTransfer);
|
||||||
|
~DataTransfer();
|
||||||
|
DataTransfer(const DataTransfer &other);
|
||||||
|
DataTransfer(DataTransfer &&other);
|
||||||
|
DataTransfer &operator=(const DataTransfer &other);
|
||||||
|
DataTransfer &operator=(DataTransfer &&other);
|
||||||
|
|
||||||
|
QMimeData *toMimeDataWithFile() ;
|
||||||
|
QMimeData *toMimeDataPreview();
|
||||||
|
void setDragImage(emscripten::val element, const QPoint &hotspot);
|
||||||
|
void setData(std::string format, std::string data);
|
||||||
|
void setDropAction(Qt::DropAction dropAction);
|
||||||
|
void setDataFromMimeData(const QMimeData &mimeData);
|
||||||
|
|
||||||
|
emscripten::val webDataTransfer;
|
||||||
|
emscripten::val m_webFile = emscripten::val::undefined();
|
||||||
|
qstdweb::File m_file;
|
||||||
|
};
|
||||||
|
|
||||||
inline emscripten::val document()
|
inline emscripten::val document()
|
||||||
{
|
{
|
||||||
return emscripten::val::global("document");
|
return emscripten::val::global("document");
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#define QWASMEVENT_H
|
#define QWASMEVENT_H
|
||||||
|
|
||||||
#include "qwasmplatform.h"
|
#include "qwasmplatform.h"
|
||||||
|
#include "qwasmdom.h"
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
@ -241,7 +242,7 @@ struct DragEvent : public MouseEvent
|
|||||||
void acceptDrop();
|
void acceptDrop();
|
||||||
|
|
||||||
Qt::DropAction dropAction;
|
Qt::DropAction dropAction;
|
||||||
emscripten::val dataTransfer;
|
dom::DataTransfer dataTransfer;
|
||||||
QWindow *targetWindow;
|
QWindow *targetWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,7 +114,6 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
|
|||||||
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter", pointerCallback);
|
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter", pointerCallback);
|
||||||
m_pointerLeaveCallback =
|
m_pointerLeaveCallback =
|
||||||
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave", pointerCallback);
|
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave", pointerCallback);
|
||||||
|
|
||||||
m_dropCallback = std::make_unique<qstdweb::EventCallback>(
|
m_dropCallback = std::make_unique<qstdweb::EventCallback>(
|
||||||
m_qtWindow, "drop", [this](emscripten::val event) {
|
m_qtWindow, "drop", [this](emscripten::val event) {
|
||||||
if (processDrop(*DragEvent::fromWeb(event, window())))
|
if (processDrop(*DragEvent::fromWeb(event, window())))
|
||||||
@ -538,25 +537,19 @@ bool QWasmWindow::processPointer(const PointerEvent &event)
|
|||||||
|
|
||||||
bool QWasmWindow::processDrop(const DragEvent &event)
|
bool QWasmWindow::processDrop(const DragEvent &event)
|
||||||
{
|
{
|
||||||
m_dropDataReadCancellationFlag = qstdweb::readDataTransfer(
|
dom::DataTransfer transfer(event.dataTransfer.webDataTransfer["clipboardData"]);
|
||||||
event.dataTransfer,
|
QMimeData *data = transfer.toMimeDataWithFile();
|
||||||
[](QByteArray fileContent) {
|
// TODO handle file
|
||||||
QImage image;
|
QWindowSystemInterface::handleDrag(window(), data,
|
||||||
image.loadFromData(fileContent, nullptr);
|
event.pointInPage.toPoint(), event.dropAction,
|
||||||
return image;
|
event.mouseButton, event.modifiers);
|
||||||
},
|
|
||||||
[this, event](std::unique_ptr<QMimeData> data) {
|
|
||||||
QWindowSystemInterface::handleDrag(window(), data.get(),
|
|
||||||
event.pointInPage.toPoint(), event.dropAction,
|
|
||||||
event.mouseButton, event.modifiers);
|
|
||||||
|
|
||||||
QWindowSystemInterface::handleDrop(window(), data.get(),
|
QWindowSystemInterface::handleDrop(window(), data,
|
||||||
event.pointInPage.toPoint(), event.dropAction,
|
event.pointInPage.toPoint(), event.dropAction,
|
||||||
event.mouseButton, event.modifiers);
|
event.mouseButton, event.modifiers);
|
||||||
|
|
||||||
QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction,
|
QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction,
|
||||||
{}, {});
|
{}, {});
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user