diff --git a/premake4.lua b/premake4.lua index 729fafc5f..1f7952609 100644 --- a/premake4.lua +++ b/premake4.lua @@ -659,7 +659,7 @@ function build_link_configuration( package_name, use_ee_icon ) add_cross_config_links() configuration "emscripten" - linkoptions { "-s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web" } + linkoptions { "-s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web -s EXPORTED_RUNTIME_METHODS=ccall" } buildoptions { "-s USE_SDL=2" } buildoptions { "-s USE_PTHREADS=1" } linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" } diff --git a/premake5.lua b/premake5.lua index 773be9800..1cacbc912 100644 --- a/premake5.lua +++ b/premake5.lua @@ -625,7 +625,7 @@ function build_link_configuration( package_name, use_ee_icon ) if package_name ~= "eepp" and package_name ~= "eepp-static" then targetextension ".html" end - linkoptions { "-O3 -s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web" } + linkoptions { "-O3 -s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web -s EXPORTED_RUNTIME_METHODS=ccall" } buildoptions { "-O3 -s USE_SDL=2" } buildoptions { "-s USE_PTHREADS=1" } linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" } diff --git a/src/thirdparty/emscripten-browser-clipboard/emscripten_browser_clipboard.h b/src/thirdparty/emscripten-browser-clipboard/emscripten_browser_clipboard.h index 9e77261d7..d24a028cd 100644 --- a/src/thirdparty/emscripten-browser-clipboard/emscripten_browser_clipboard.h +++ b/src/thirdparty/emscripten-browser-clipboard/emscripten_browser_clipboard.h @@ -1,6 +1,8 @@ #ifndef EMSCRIPTEN_BROWSER_CLIPBOARD_H_INCLUDED #define EMSCRIPTEN_BROWSER_CLIPBOARD_H_INCLUDED +// clang-format off + #include #include @@ -33,8 +35,39 @@ EM_JS_INLINE(void, paste_js, (paste_handler callback, void *callback_data), { /// Register the given callback to handle paste events. Callback data pointer is passed through to the callback. /// Paste handler callback signature is: /// void my_handler(std::string const &paste_data, void *callback_data = nullptr); + /// SDL2's Emscripten backend prevents the default action for every Ctrl key event, which suppresses + /// the browser paste event. Let the browser handle Ctrl/Cmd+V first, then replay the keydown after + /// the clipboard contents have reached C++ so SDL delivers the normal application paste command. + let paste_key_event = null; + window.addEventListener('keydown', (event) => { + if (event.isTrusted && !event.altKey && (event.ctrlKey || event.metaKey) && + (event.code === 'KeyV' || event.key.toLowerCase() === 'v')) { + paste_key_event = event; + event.stopPropagation(); + } + }, true); + window.addEventListener('mousedown', (event) => { + if (event.isTrusted && event.button === 2 && navigator.clipboard && navigator.clipboard.readText) { + navigator.clipboard.readText().then((text) => { + Module["ccall"]('paste_return', 'number', ['string', 'number', 'number'], [text, callback, callback_data]); + }).catch(() => {}); + } + }, true); document.addEventListener('paste', (event) => { Module["ccall"]('paste_return', 'number', ['string', 'number', 'number'], [event.clipboardData.getData('text/plain'), callback, callback_data]); + if (paste_key_event) { + paste_key_event.target.dispatchEvent(new KeyboardEvent('keydown', { + key: paste_key_event.key, + code: paste_key_event.code, + location: paste_key_event.location, + ctrlKey: paste_key_event.ctrlKey, + metaKey: paste_key_event.metaKey, + shiftKey: paste_key_event.shiftKey, + bubbles: true, + cancelable: true + })); + paste_key_event = null; + } }); }); @@ -96,4 +129,6 @@ EMSCRIPTEN_KEEPALIVE inline char const *copy_return(copy_handler callback, void } +// clang-format on + #endif // EMSCRIPTEN_BROWSER_CLIPBOARD_H_INCLUDED