11#include <private/qstdweb_p.h>
13#include <QCoreApplication>
14#include <qpa/qwindowsysteminterface.h>
18#include <emscripten/val.h>
21using namespace emscripten;
30 if (_mimes->hasText()) {
31 event[
"clipboardData"].call<
void>(
"setData", val(
"text/plain"),
32 _mimes->text().toEcmaString());
34 if (_mimes->hasHtml()) {
35 event[
"clipboardData"].call<
void>(
"setData", val(
"text/html"), _mimes->html().toEcmaString());
38 for (
auto mimetype : _mimes->formats()) {
39 if (mimetype.contains(
"text/"))
41 QByteArray ba = _mimes->data(mimetype);
43 event[
"clipboardData"].call<
void>(
"setData", mimetype.toEcmaString(),
47 event.call<
void>(
"preventDefault");
55 if (target.isNull() || target.isUndefined() || target[
"closest"].isUndefined())
57 return target.call<val>(
"closest", val(
".qt-window"));
63 return eventQtWindow(event).strictlyEquals(event[
"currentTarget"]);
68 if (!isEventForReceivingHandler(event))
73 QWindowSystemInterface::handleKeyEvent(
74 0, QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier,
"X");
77 commonCopyEvent(event);
82 if (!isEventForReceivingHandler(event))
87 QWindowSystemInterface::handleKeyEvent(
88 0, QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier,
"C");
90 commonCopyEvent(event);
95 if (!isEventForReceivingHandler(event))
100 event.call<
void>(
"preventDefault");
107 val clipboard = val::global(
"navigator")[
"clipboard"];
109 const bool hasPermissionsApi = !val::global(
"navigator")[
"permissions"].isUndefined();
110 m_hasClipboardApi = !clipboard.isUndefined() && !clipboard[
"readText"].isUndefined();
112 if (m_hasClipboardApi && hasPermissionsApi)
113 initClipboardPermissions();
122 if (mode != QClipboard::Clipboard)
125 return QPlatformClipboard::mimeData(mode);
131 QPlatformClipboard::setMimeData(mimeData, mode);
132 if (m_hasClipboardApi)
133 writeToClipboardApi();
140 if (event.type !=
EventType::KeyDown || !event.modifiers.testFlag(Qt::ControlModifier))
143 if (event.key != Qt::Key_C && event.key != Qt::Key_V && event.key != Qt::Key_X)
146 const bool isPaste = event.key == Qt::Key_V;
148 return m_hasClipboardApi && !isPaste
155 return mode == QClipboard::Clipboard;
166 val permissions = val::global(
"navigator")[
"permissions"];
168 qstdweb::Promise::make(permissions,
"query", { .catchFunc = [](emscripten::val) {} }, ([]() {
169 val readPermissionsMap = val::object();
170 readPermissionsMap.set(
"name", val(
"clipboard-read"));
171 return readPermissionsMap;
173 qstdweb::Promise::make(permissions,
"query", { .catchFunc = [](emscripten::val) {} }, ([]() {
174 val readPermissionsMap = val::object();
175 readPermissionsMap.set(
"name", val(
"clipboard-write"));
176 return readPermissionsMap;
182 return m_hasClipboardApi;
187 Q_ASSERT(m_hasClipboardApi);
189 QMimeData *mimeData =
this->mimeData(QClipboard::Clipboard);
195 emscripten::val clipboardData = emscripten::val::object();
196 for (
const QString &mimetype: mimeData->formats()) {
197 if (mimetype == QLatin1String(
"text/plain")) {
198 emscripten::val text = mimeData->text().toEcmaString();
199 clipboardData.set(mimetype.toEcmaString(), text);
200 }
else if (mimetype == QLatin1String(
"text/html")) {
201 emscripten::val html = mimeData->html().toEcmaString();
202 clipboardData.set(mimetype.toEcmaString(), html);
203 }
else if (mimetype.contains(QLatin1String(
"image"))) {
205 QImage img = qvariant_cast<QImage>(mimeData->imageData());
208 buffer.open(QIODevice::WriteOnly);
209 img.save(&buffer,
"PNG");
211 qstdweb::Blob blob = qstdweb::Blob::fromArrayBuffer(qstdweb::Uint8Array::copyFrom(ba).buffer());
212 clipboardData.set(std::string(
"image/png"), blob.val());
217 if (val::global(
"Object").call<val>(
"keys", clipboardData)[
"length"].as<
int>() == 0)
221 emscripten::val clipboardItem = val::global(
"ClipboardItem").new_(clipboardData);
222 emscripten::val clipboardItemArray = emscripten::val::array();
223 clipboardItemArray.call<
void>(
"push", clipboardItem);
224 val navigator = val::global(
"navigator");
225 qstdweb::Promise::make(
226 navigator[
"clipboard"],
"write",
228 .catchFunc = [](emscripten::val error) {
229 qWarning() <<
"clipboard error"
230 << QString::fromStdString(error[
"name"].as<std::string>())
231 << QString::fromStdString(error[
"message"].as<std::string>());
243 val document = val::global(
"document");
244 document.call<val>(
"execCommand", val(
"copy"));
250 const auto mimeCallback = std::function([transfer](QMimeData *data) {
254 QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
255 Qt::ControlModifier,
"V");
256 QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_V,
257 Qt::ControlModifier,
"V");
261 transfer->toMimeDataWithFile(mimeCallback);
virtual ~QWasmClipboard()
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()
Combined button and popup list for selecting options.
static val eventQtWindow(val event)
static bool isEventForReceivingHandler(val event)
static void commonCopyEvent(val event)
static emscripten::val composedTarget(emscripten::val webEvent)