wasm: fix clipboard event handler leaks
Use QWasmEventHandler instead of calling addEventListener() directly (using QWasmEventHandler also allows supporting JSPI). The QWasmEventHandler destructor calls removeEventListener(), which should make sure everything gets cleaned up. Keep the Chrome-specific global (document) event handler code path, but register once at startup instead of once per window. Change-Id: If4314df738afc0dcfdb0f6f1ab9e1f176e1812ac Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
d4efce2119
commit
f4287c4531
@ -46,7 +46,7 @@ static void commonCopyEvent(val event)
|
||||
event.call<void>("preventDefault");
|
||||
}
|
||||
|
||||
static void qClipboardCutTo(val event)
|
||||
void QWasmClipboard::cut(val event)
|
||||
{
|
||||
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
|
||||
if (wasmInput && wasmInput->usingTextInput())
|
||||
@ -61,7 +61,7 @@ static void qClipboardCutTo(val event)
|
||||
commonCopyEvent(event);
|
||||
}
|
||||
|
||||
static void qClipboardCopyTo(val event)
|
||||
void QWasmClipboard::copy(val event)
|
||||
{
|
||||
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
|
||||
if (wasmInput && wasmInput->usingTextInput())
|
||||
@ -75,7 +75,7 @@ static void qClipboardCopyTo(val event)
|
||||
commonCopyEvent(event);
|
||||
}
|
||||
|
||||
static void qClipboardPasteTo(val event)
|
||||
void QWasmClipboard::paste(val event)
|
||||
{
|
||||
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
|
||||
if (wasmInput && wasmInput->usingTextInput())
|
||||
@ -86,12 +86,6 @@ static void qClipboardPasteTo(val event)
|
||||
QWasmIntegration::get()->getWasmClipboard()->sendClipboardData(event);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
|
||||
function("qtClipboardCutTo", &qClipboardCutTo);
|
||||
function("qtClipboardCopyTo", &qClipboardCopyTo);
|
||||
function("qtClipboardPasteTo", &qClipboardPasteTo);
|
||||
}
|
||||
|
||||
QWasmClipboard::QWasmClipboard()
|
||||
{
|
||||
val clipboard = val::global("navigator")["clipboard"];
|
||||
@ -101,6 +95,13 @@ QWasmClipboard::QWasmClipboard()
|
||||
|
||||
if (m_hasClipboardApi && hasPermissionsApi)
|
||||
initClipboardPermissions();
|
||||
|
||||
if (!shouldInstallWindowEventHandlers()) {
|
||||
val document = val::global("document");
|
||||
m_documentCut = QWasmEventHandler(document, "cut", QWasmClipboard::cut);
|
||||
m_documentCopy = QWasmEventHandler(document, "copy", QWasmClipboard::copy);
|
||||
m_documentPaste = QWasmEventHandler(document, "paste", QWasmClipboard::paste);
|
||||
}
|
||||
}
|
||||
|
||||
QWasmClipboard::~QWasmClipboard()
|
||||
@ -167,29 +168,17 @@ void QWasmClipboard::initClipboardPermissions()
|
||||
})());
|
||||
}
|
||||
|
||||
void QWasmClipboard::installEventHandlers(const emscripten::val &target)
|
||||
{
|
||||
emscripten::val cContext = val::undefined();
|
||||
emscripten::val isChromium = val::global("window")["chrome"];
|
||||
if (!isChromium.isUndefined()) {
|
||||
cContext = val::global("document");
|
||||
} else {
|
||||
cContext = target;
|
||||
}
|
||||
// Fallback path for browsers which do not support direct clipboard access
|
||||
cContext.call<void>("addEventListener", val("cut"),
|
||||
val::module_property("qtClipboardCutTo"), true);
|
||||
cContext.call<void>("addEventListener", val("copy"),
|
||||
val::module_property("qtClipboardCopyTo"), true);
|
||||
cContext.call<void>("addEventListener", val("paste"),
|
||||
val::module_property("qtClipboardPasteTo"), true);
|
||||
}
|
||||
|
||||
bool QWasmClipboard::hasClipboardApi()
|
||||
{
|
||||
return m_hasClipboardApi;
|
||||
}
|
||||
|
||||
bool QWasmClipboard::shouldInstallWindowEventHandlers()
|
||||
{
|
||||
// Chrome uses global handlers
|
||||
return val::global("window")["chrome"].isUndefined() == false;
|
||||
}
|
||||
|
||||
void QWasmClipboard::writeToClipboardApi()
|
||||
{
|
||||
Q_ASSERT(m_hasClipboardApi);
|
||||
|
@ -36,16 +36,23 @@ public:
|
||||
bool ownsMode(QClipboard::Mode mode) const override;
|
||||
|
||||
ProcessKeyboardResult processKeyboard(const KeyEvent &event);
|
||||
static void installEventHandlers(const emscripten::val &target);
|
||||
bool hasClipboardApi();
|
||||
static bool shouldInstallWindowEventHandlers();
|
||||
void sendClipboardData(emscripten::val event);
|
||||
|
||||
static void cut(emscripten::val event);
|
||||
static void copy(emscripten::val event);
|
||||
static void paste(emscripten::val event);
|
||||
|
||||
private:
|
||||
void initClipboardPermissions();
|
||||
void writeToClipboardApi();
|
||||
void writeToClipboard();
|
||||
|
||||
bool m_hasClipboardApi = false;
|
||||
QWasmEventHandler m_documentCut;
|
||||
QWasmEventHandler m_documentCopy;
|
||||
QWasmEventHandler m_documentPaste;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -95,7 +95,11 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
|
||||
m_window.set("contentEditable", std::string("true"));
|
||||
m_window["style"].set("outline", std::string("none"));
|
||||
|
||||
QWasmClipboard::installEventHandlers(m_window);
|
||||
if (QWasmClipboard::shouldInstallWindowEventHandlers()) {
|
||||
m_cutCallback = QWasmEventHandler(m_window, "cut", QWasmClipboard::cut);
|
||||
m_copyCallback = QWasmEventHandler(m_window, "copy", QWasmClipboard::copy);
|
||||
m_pasteCallback = QWasmEventHandler(m_window, "paste", QWasmClipboard::paste);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set inputMode to none to stop the mobile keyboard from opening
|
||||
|
@ -173,6 +173,10 @@ private:
|
||||
|
||||
QMap<int, QWindowSystemInterface::TouchPoint> m_pointerIdToTouchPoints;
|
||||
|
||||
QWasmEventHandler m_cutCallback;
|
||||
QWasmEventHandler m_copyCallback;
|
||||
QWasmEventHandler m_pasteCallback;
|
||||
|
||||
Qt::WindowStates m_state = Qt::WindowNoState;
|
||||
Qt::WindowStates m_previousWindowState = Qt::WindowNoState;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user