diff --git a/wasm/reset_events.js b/wasm/reset_events.js index 48af9c617dd2..e93277281860 100644 --- a/wasm/reset_events.js +++ b/wasm/reset_events.js @@ -82,6 +82,114 @@ var preventFunc = function (event) { event.preventDefault(); } +var drop_files_or_dir = function (event) { + if (!GLFW.active || !GLFW.active.dropFunc) return; + if (!event.dataTransfer || !event.dataTransfer.files || event.dataTransfer.files.length == 0) return; + event.preventDefault(); + + var drop_dir = ".glfw_dropped_files"; + var filenames = _malloc(event.dataTransfer.files.length * getPointerSize()); + var filenamesArray = []; + for (var i = 0; i < event.dataTransfer.files.length; ++i) { + var path = "/" + drop_dir + "/" + event.dataTransfer.files[i].name.replace(/\//g, "_"); + var filename = stringToNewUTF8(path); + filenamesArray.push(filename); + if (getPointerSize() == 8) + HEAPU64[(filenames + i * 8) / 8] = BigInt(filename); + else if (typeof GROWABLE_HEAP_U32 !== 'undefined') + GROWABLE_HEAP_U32()[filenames + i * 4 >> 2] = filename; + else + HEAPU32[filenames + i * 4 >> 2] = filename; + } + + // Read and save the files to emscripten's FS + var written = 0; + FS.createPath("/", drop_dir); + function save(file, in_path, numfiles) { + var path = "/" + drop_dir + in_path + "/" + file.name.replace(/\//g, "_"); + var reader = new FileReader; + reader.onloadend = e => { + if (reader.readyState != 2) { + // not DONE + ++written; + out("failed to read dropped file: " + file.name + ": " + reader.error); + return; + } + var data = e.target.result; + FS.writeFile(path, new Uint8Array(data)); + if (++written === numfiles) { + if (typeof (dynCall_viii) == 'function') + dynCall_viii(GLFW.active.dropFunc, GLFW.active.id, filenamesArray.length, filenames); + else if (typeof (dynCall_vjij) == 'function') + dynCall_vjij(GLFW.active.dropFunc, BigInt(GLFW.active.id), filenamesArray.length, filenames); + else + getWasmTableEntry(GLFW.active.dropFunc)(toPointer(GLFW.active.id), filenamesArray.length, filenames); + for (var i = 0; i < filenamesArray.length; ++i) { + _free(filenamesArray[i]); + } + _free(filenames); + } + }; + reader.readAsArrayBuffer(file); + } + + let filesQ = []; + var finalize = function () { + count = filesQ.length; + for (var i = 0; i < count; ++i) + save(filesQ[i].file, filesQ[i].path, count); + } + + if (typeof DataTransferItem.prototype.webkitGetAsEntry !== "undefined") { + let entriesTree = {}; + var markDone = function (fullpath, recursive) { + if (entriesTree[fullpath].subpaths.length != 0) return; + delete entriesTree[fullpath]; + let parentpath = fullpath.substring(0, fullpath.lastIndexOf('/')); + if (!entriesTree.hasOwnProperty(parentpath)) { + if (Object.keys(entriesTree).length == 0) finalize(); + return; + } + const fpIndex = entriesTree[parentpath].subpaths.indexOf(fullpath); + if (fpIndex > -1) entriesTree[parentpath].subpaths.splice(fpIndex, 1); + if (recursive) markDone(parentpath, true); + if (Object.keys(entriesTree).length == 0) finalize(); + }; + var processEntry = function (entry) { + let fp = entry.fullPath; + let pp = fp.substring(0, fp.lastIndexOf('/')); + entriesTree[fp] = { subpaths: [] }; + if (entry.isFile) { + entry.file((f) => { filesQ.push({ file: f, path: pp }); markDone(fp, false); }) + } else if (entry.isDirectory) { + if (entriesTree.hasOwnProperty(pp)) entriesTree[pp].subpaths.push(fp); + FS.createPath("/" + drop_dir + pp, entry.name); + var reader = entry.createReader(); + var rRead = function (dirEntries) { + if (dirEntries.length == 0) { + markDone(fp, true); + return; + } + for (const ent of dirEntries) processEntry(ent); + reader.readEntries(rRead); + }; + reader.readEntries(rRead); + } + }; + for (const item of event.dataTransfer.items) { + processEntry(item.webkitGetAsEntry()); + } + } + else { + // fallback for browsers that does not support `webkitGetAsEntry` + for (var i = 0; i < event.dataTransfer.files.length; ++i) { + filesQ.push({ file: event.dataTransfer.files[i], path: "" }); + } + finalize(); + } + return false; +} + var updateEvents = function () { // remove all touch events Module["canvas"].removeEventListener("touchmove", GLFW.onMousemove, true); @@ -96,6 +204,7 @@ var updateEvents = function () { Module["canvas"].removeEventListener("wheel", GLFW.onMouseWheel, true); Module["canvas"].removeEventListener("mousewheel", GLFW.onMouseWheel, true); Module["canvas"].removeEventListener("dragover", GLFW.onDragover, true); + Module["canvas"].removeEventListener("drop", GLFW.onDrop, true); // make own touch events callbacks var touchEventProcess = function (event, funcName) { @@ -246,6 +355,8 @@ var updateEvents = function () { return false } + GLFW.onDrop = drop_files_or_dir; + // add new events Module["canvas"].addEventListener("pointermove", GLFW.onMousemove, true); Module["canvas"].addEventListener("pointerdown", GLFW.onMouseButtonDown, true); @@ -254,6 +365,7 @@ var updateEvents = function () { Module["canvas"].addEventListener("wheel", GLFW.onMouseWheel, true); Module["canvas"].addEventListener("mousewheel", GLFW.onMouseWheel, true); Module["canvas"].addEventListener("dragover", GLFW.onDragover, true); + Module["canvas"].addEventListener("drop", GLFW.onDrop, true); Module["canvas"].addEventListener("dragenter", (e) => { Module.ccall('emsDragEnter', 'void', [], []); }, true);