10#include <private/qstdweb_p.h>
12#include <QCoreApplication>
13#include <qpa/qwindowsysteminterface.h>
17#include <emscripten/val.h>
20using namespace emscripten;
24 QMimeData *_mimes = QWasmIntegration::get()->getWasmClipboard()->mimeData(QClipboard::Clipboard);
29 if (_mimes->hasText()) {
30 event[
"clipboardData"].call<
void>(
"setData", val(
"text/plain"),
31 _mimes->text().toEcmaString());
33 if (_mimes->hasHtml()) {
34 event[
"clipboardData"].call<
void>(
"setData", val(
"text/html"), _mimes->html().toEcmaString());
37 for (
auto mimetype : _mimes->formats()) {
38 if (mimetype.contains(
"text/"))
40 QByteArray ba = _mimes->data(mimetype);
42 event[
"clipboardData"].call<
void>(
"setData", mimetype.toEcmaString(),
46 event.call<
void>(
"preventDefault");
53 QWindowSystemInterface::handleKeyEvent(
54 0, QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier,
"X");
57 commonCopyEvent(event);
64 QWindowSystemInterface::handleKeyEvent(
65 0, QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier,
"C");
67 commonCopyEvent(event);
72 event.call<
void>(
"preventDefault");
79 val clipboard = val::global(
"navigator")[
"clipboard"];
81 const bool hasPermissionsApi = !val::global(
"navigator")[
"permissions"].isUndefined();
82 m_hasClipboardApi = !clipboard.isUndefined() && !clipboard[
"readText"].isUndefined();
84 if (m_hasClipboardApi && hasPermissionsApi)
85 initClipboardPermissions();
88 val document = val::global(
"document");
89 m_documentCut = QWasmEventHandler(document,
"cut", QWasmClipboard::cut);
90 m_documentCopy = QWasmEventHandler(document,
"copy", QWasmClipboard::copy);
91 m_documentPaste = QWasmEventHandler(document,
"paste", QWasmClipboard::paste);
101 if (mode != QClipboard::Clipboard)
104 return QPlatformClipboard::mimeData(mode);
110 QPlatformClipboard::setMimeData(mimeData, mode);
111 if (m_hasClipboardApi)
112 writeToClipboardApi();
119 if (event.type != EventType::KeyDown || !event.modifiers.testFlag(Qt::ControlModifier))
122 if (event.key != Qt::Key_C && event.key != Qt::Key_V && event.key != Qt::Key_X)
125 const bool isPaste = event.key == Qt::Key_V;
127 return m_hasClipboardApi && !isPaste
134 return mode == QClipboard::Clipboard;
145 val permissions = val::global(
"navigator")[
"permissions"];
147 qstdweb::Promise::make(permissions,
"query", { .catchFunc = [](emscripten::val) {} }, ([]() {
148 val readPermissionsMap = val::object();
149 readPermissionsMap.set(
"name", val(
"clipboard-read"));
150 return readPermissionsMap;
152 qstdweb::Promise::make(permissions,
"query", { .catchFunc = [](emscripten::val) {} }, ([]() {
153 val readPermissionsMap = val::object();
154 readPermissionsMap.set(
"name", val(
"clipboard-write"));
155 return readPermissionsMap;
161 return m_hasClipboardApi;
167 return val::global(
"window")[
"chrome"].isUndefined();
172 Q_ASSERT(m_hasClipboardApi);
174 QMimeData *mimeData =
this->mimeData(QClipboard::Clipboard);
180 emscripten::val clipboardData = emscripten::val::object();
181 for (
const QString &mimetype: mimeData->formats()) {
182 if (mimetype == QLatin1String(
"text/plain")) {
183 emscripten::val text = mimeData->text().toEcmaString();
184 clipboardData.set(mimetype.toEcmaString(), text);
185 }
else if (mimetype == QLatin1String(
"text/html")) {
186 emscripten::val html = mimeData->html().toEcmaString();
187 clipboardData.set(mimetype.toEcmaString(), html);
188 }
else if (mimetype.contains(QLatin1String(
"image"))) {
190 QImage img = qvariant_cast<QImage>(mimeData->imageData());
193 buffer.open(QIODevice::WriteOnly);
194 img.save(&buffer,
"PNG");
196 qstdweb::Blob blob = qstdweb::Blob::fromArrayBuffer(qstdweb::Uint8Array::copyFrom(ba).buffer());
197 clipboardData.set(std::string(
"image/png"), blob.val());
202 if (val::global(
"Object").call<val>(
"keys", clipboardData)[
"length"].as<
int>() == 0)
206 emscripten::val clipboardItem = val::global(
"ClipboardItem").new_(clipboardData);
207 emscripten::val clipboardItemArray = emscripten::val::array();
208 clipboardItemArray.call<
void>(
"push", clipboardItem);
209 val navigator = val::global(
"navigator");
210 qstdweb::Promise::make(
211 navigator[
"clipboard"],
"write",
213 .catchFunc = [](emscripten::val error) {
214 qWarning() <<
"clipboard error"
215 << QString::fromStdString(error[
"name"].as<std::string>())
216 << QString::fromStdString(error[
"message"].as<std::string>());
228 val document = val::global(
"document");
229 document.call<val>(
"execCommand", val(
"copy"));
235 const auto mimeCallback = std::function([transfer](QMimeData *data) {
238 QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(data, QClipboard::Clipboard);
239 QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
240 Qt::ControlModifier,
"V");
241 QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_V,
242 Qt::ControlModifier,
"V");
246 transfer->toMimeDataWithFile(mimeCallback);
virtual ~QWasmClipboard()
static bool shouldInstallWindowEventHandlers()
void setMimeData(QMimeData *data, QClipboard::Mode mode=QClipboard::Clipboard) override
@ NativeClipboardEventNeeded
@ NativeClipboardEventAndCopiedDataNeeded
bool supportsMode(QClipboard::Mode mode) const override
QMimeData * mimeData(QClipboard::Mode mode=QClipboard::Clipboard) override
ProcessKeyboardResult processKeyboard(const KeyEvent &event)
bool ownsMode(QClipboard::Mode mode) const override
static QWasmIntegration * get()
QWasmClipboard * getWasmClipboard()
static void commonCopyEvent(val event)