emscripten: drag-and-drop fixes.
FS.mkdir() will throw a javascript exception if the scratch directory already exists, so catch/ignore that. Wrap the rest of the scratch i/o in a try/catch block; the event will only send if everything works out. Wrap some calls from Javascript to the C runtime's free() in an EMSCRIPTEN_KEEPALIVE function, so that the compiler doesn't optimize the function out and crash at runtime. Fixes #14999.
This commit is contained in:
@@ -26,6 +26,14 @@
|
|||||||
|
|
||||||
#include "joystick/SDL_joystick_c.h" // For SDL_GetGamepadTypeFromVIDPID()
|
#include "joystick/SDL_joystick_c.h" // For SDL_GetGamepadTypeFromVIDPID()
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_EMSCRIPTEN
|
||||||
|
#include <emscripten.h>
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void Emscripten_force_free(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr); // This should NOT be SDL_free()
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Common utility functions that aren't in the public API
|
// Common utility functions that aren't in the public API
|
||||||
|
|
||||||
|
|||||||
@@ -93,4 +93,11 @@ extern char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *ven
|
|||||||
// Log what backend a subsystem chose, if a hint was set to do so. Useful for debugging.
|
// Log what backend a subsystem chose, if a hint was set to do so. Useful for debugging.
|
||||||
extern void SDL_DebugLogBackend(const char *subsystem, const char *backend);
|
extern void SDL_DebugLogBackend(const char *subsystem, const char *backend);
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_EMSCRIPTEN
|
||||||
|
// even though we reference the C runtime's free() in other places, it appears
|
||||||
|
// to be inlined more aggressively in Emscripten 4, so we need a reference to
|
||||||
|
// it here, too, so inlined Javascript doesn't fail to find it.
|
||||||
|
extern void Emscripten_force_free(void *ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // SDL_utils_h_
|
#endif // SDL_utils_h_
|
||||||
|
|||||||
@@ -28,11 +28,6 @@
|
|||||||
|
|
||||||
EM_JS_DEPS(sdlrunapp, "$dynCall,$stringToNewUTF8");
|
EM_JS_DEPS(sdlrunapp, "$dynCall,$stringToNewUTF8");
|
||||||
|
|
||||||
// even though we reference the C runtime's free() in other places, it appears
|
|
||||||
// to be inlined more aggressively in Emscripten 4, so we need a reference to
|
|
||||||
// it here, too, so the inlined Javascript doesn't fail to find it.
|
|
||||||
EMSCRIPTEN_KEEPALIVE void force_free(void *ptr) { free(ptr); } // This should NOT be SDL_free()
|
|
||||||
|
|
||||||
int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved)
|
int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved)
|
||||||
{
|
{
|
||||||
(void)reserved;
|
(void)reserved;
|
||||||
@@ -51,8 +46,8 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserv
|
|||||||
//console.log("Setting SDL env var '" + key + "' to '" + value + "' ...");
|
//console.log("Setting SDL env var '" + key + "' to '" + value + "' ...");
|
||||||
dynCall('iiii', $0, [ckey, cvalue, 1]);
|
dynCall('iiii', $0, [ckey, cvalue, 1]);
|
||||||
}
|
}
|
||||||
_force_free(ckey); // these must use free(), not SDL_free()!
|
_Emscripten_force_free(ckey); // these must use free(), not SDL_free()!
|
||||||
_force_free(cvalue);
|
_Emscripten_force_free(cvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, SDL_setenv_unsafe);
|
}, SDL_setenv_unsafe);
|
||||||
|
|||||||
@@ -1164,13 +1164,17 @@ static void Emscripten_set_drag_event_callbacks(SDL_WindowData *data)
|
|||||||
target.addEventListener("dragover", SDL3.eventHandlerDropDragover);
|
target.addEventListener("dragover", SDL3.eventHandlerDropDragover);
|
||||||
|
|
||||||
SDL3.drop_count = 0;
|
SDL3.drop_count = 0;
|
||||||
FS.mkdir("/tmp/filedrop");
|
|
||||||
|
// FS.* functions throw exceptions when there are errors (such as the temp dir already existing),
|
||||||
|
// but we ignore all of these in a catch handler; you just won't get the drop event if there's a problem.
|
||||||
|
try { FS.mkdir("/tmp/filedrop"); } catch (e) {}
|
||||||
|
|
||||||
SDL3.eventHandlerDropDrop = function(event) {
|
SDL3.eventHandlerDropDrop = function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.dataTransfer.types.includes("text/plain")) {
|
if (event.dataTransfer.types.includes("text/plain")) {
|
||||||
let plain_text = stringToNewUTF8(event.dataTransfer.getData("text/plain"));
|
let plain_text = stringToNewUTF8(event.dataTransfer.getData("text/plain"));
|
||||||
_Emscripten_SendDragTextEvent(data, plain_text);
|
_Emscripten_SendDragTextEvent(data, plain_text);
|
||||||
_free(plain_text);
|
_Emscripten_force_free(plain_text);
|
||||||
} else if (event.dataTransfer.types.includes("Files")) {
|
} else if (event.dataTransfer.types.includes("Files")) {
|
||||||
let files_read = 0;
|
let files_read = 0;
|
||||||
const files_to_read = event.dataTransfer.files.length;
|
const files_to_read = event.dataTransfer.files.length;
|
||||||
@@ -1186,13 +1190,16 @@ static void Emscripten_set_drag_event_callbacks(SDL_WindowData *data)
|
|||||||
const c_fs_filepath = stringToNewUTF8(fs_filepath);
|
const c_fs_filepath = stringToNewUTF8(fs_filepath);
|
||||||
const contents_array8 = new Uint8Array(event.target.result);
|
const contents_array8 = new Uint8Array(event.target.result);
|
||||||
|
|
||||||
FS.mkdir(fs_dropdir);
|
try {
|
||||||
var stream = FS.open(fs_filepath, "w");
|
FS.mkdir(fs_dropdir);
|
||||||
FS.write(stream, contents_array8, 0, contents_array8.length, 0);
|
var stream = FS.open(fs_filepath, "w");
|
||||||
FS.close(stream);
|
FS.write(stream, contents_array8, 0, contents_array8.length, 0);
|
||||||
|
FS.close(stream);
|
||||||
_Emscripten_SendDragFileEvent(data, c_fs_filepath);
|
_Emscripten_SendDragFileEvent(data, c_fs_filepath);
|
||||||
_free(c_fs_filepath);
|
} catch (e) {
|
||||||
|
// if this threw an exception at any point, we skip this drop event. Sorry!
|
||||||
|
}
|
||||||
|
_Emscripten_force_free(c_fs_filepath);
|
||||||
onFileRead();
|
onFileRead();
|
||||||
};
|
};
|
||||||
file_reader.onerror = function(event) {
|
file_reader.onerror = function(event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user