mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-05 07:09:32 +00:00
emscripten: send drag and drop events
This commit is contained in:
committed by
Ryan C. Gordon
parent
e14d939ead
commit
88926f2b73
@@ -26,6 +26,7 @@
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/dom_pk_codes.h>
|
||||
|
||||
#include "../../events/SDL_dropevents_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
@@ -806,6 +807,144 @@ static void Emscripten_unset_pointer_event_callbacks(SDL_WindowData *data)
|
||||
}, data->canvas_id);
|
||||
}
|
||||
|
||||
// IF YOU CHANGE THIS STRUCTURE, YOU NEED TO UPDATE THE JAVASCRIPT THAT FILLS IT IN: makeDropEventCStruct, below.
|
||||
typedef struct Emscripten_DropEvent
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} Emscripten_DropEvent;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Emscripten_SendDragEvent(SDL_WindowData *window_data, const Emscripten_DropEvent *event)
|
||||
{
|
||||
SDL_SendDropPosition(window_data->window, event->x, event->y);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Emscripten_SendDragCompleteEvent(SDL_WindowData *window_data)
|
||||
{
|
||||
SDL_SendDropComplete(window_data->window);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Emscripten_SendDragTextEvent(SDL_WindowData *window_data, char *text)
|
||||
{
|
||||
SDL_SendDropText(window_data->window, text);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Emscripten_SendDragFileEvent(SDL_WindowData *window_data, char *filename)
|
||||
{
|
||||
SDL_SendDropFile(window_data->window, NULL, filename);
|
||||
}
|
||||
|
||||
EM_JS_DEPS(dragndrop, "$writeArrayToMemory");
|
||||
|
||||
static void Emscripten_set_drag_event_callbacks(SDL_WindowData *data)
|
||||
{
|
||||
MAIN_THREAD_EM_ASM({
|
||||
var target = document.querySelector(UTF8ToString($1));
|
||||
if (target) {
|
||||
var data = $0;
|
||||
|
||||
if (typeof(Module['SDL3']) === 'undefined') {
|
||||
Module['SDL3'] = {};
|
||||
}
|
||||
var SDL3 = Module['SDL3'];
|
||||
|
||||
var makeDropEventCStruct = function(event) {
|
||||
var ptr = 0;
|
||||
ptr = _SDL_malloc($2);
|
||||
if (ptr != 0) {
|
||||
var idx = ptr >> 2;
|
||||
var rect = target.getBoundingClientRect();
|
||||
HEAP32[idx++] = event.clientX - rect.left;
|
||||
HEAP32[idx++] = event.clientY - rect.top;
|
||||
}
|
||||
return ptr;
|
||||
};
|
||||
|
||||
SDL3.eventHandlerDropDragover = function(event) {
|
||||
event.preventDefault();
|
||||
var d = makeDropEventCStruct(event); if (d != 0) { _Emscripten_SendDragEvent(data, d); _SDL_free(d); }
|
||||
};
|
||||
target.addEventListener("dragover", SDL3.eventHandlerDropDragover);
|
||||
|
||||
SDL3.drop_count = 0;
|
||||
FS.mkdir("/tmp/filedrop");
|
||||
SDL3.eventHandlerDropDrop = function(event) {
|
||||
event.preventDefault();
|
||||
if (event.dataTransfer.types.includes("text/plain")) {
|
||||
let plain_text = stringToNewUTF8(event.dataTransfer.getData("text/plain"));
|
||||
_Emscripten_SendDragTextEvent(data, plain_text);
|
||||
_free(plain_text);
|
||||
} else if (event.dataTransfer.types.includes("Files")) {
|
||||
for (let i = 0; i < event.dataTransfer.files.length; i++) {
|
||||
const file = event.dataTransfer.files.item(i);
|
||||
const file_reader = new FileReader();
|
||||
file_reader.readAsArrayBuffer(file);
|
||||
file_reader.onload = function(event) {
|
||||
const fs_dropdir = `/tmp/filedrop/${SDL3.drop_count}`;
|
||||
SDL3.drop_count += 1;
|
||||
|
||||
const fs_filepath = `${fs_dropdir}/${file.name}`;
|
||||
const c_fs_filepath = stringToNewUTF8(fs_filepath);
|
||||
const contents_array8 = new Uint8Array(event.target.result);
|
||||
|
||||
FS.mkdir(fs_dropdir);
|
||||
var stream = FS.open(fs_filepath, "w");
|
||||
FS.write(stream, contents_array8, 0, contents_array8.length, 0);
|
||||
FS.close(stream);
|
||||
|
||||
_Emscripten_SendDragFileEvent(data, c_fs_filepath);
|
||||
_free(c_fs_filepath);
|
||||
_Emscripten_SendDragCompleteEvent(data);
|
||||
};
|
||||
}
|
||||
}
|
||||
_Emscripten_SendDragCompleteEvent(data);
|
||||
};
|
||||
target.addEventListener("drop", SDL3.eventHandlerDropDrop);
|
||||
|
||||
SDL3.eventHandlerDropDragend = function(event) {
|
||||
event.preventDefault();
|
||||
_Emscripten_SendDragCompleteEvent(data);
|
||||
};
|
||||
target.addEventListener("dragend", SDL3.eventHandlerDropDragend);
|
||||
target.addEventListener("dragleave", SDL3.eventHandlerDropDragend);
|
||||
}
|
||||
}, data, data->canvas_id, sizeof (Emscripten_DropEvent));
|
||||
}
|
||||
|
||||
static void Emscripten_unset_drag_event_callbacks(SDL_WindowData *data)
|
||||
{
|
||||
MAIN_THREAD_EM_ASM({
|
||||
var target = document.querySelector(UTF8ToString($0));
|
||||
if (target) {
|
||||
var SDL3 = Module['SDL3'];
|
||||
target.removeEventListener("dragleave", SDL3.eventHandlerDropDragend);
|
||||
target.removeEventListener("dragend", SDL3.eventHandlerDropDragend);
|
||||
target.removeEventListener("drop", SDL3.eventHandlerDropDrop);
|
||||
SDL3.drop_count = undefined;
|
||||
|
||||
function recursive_remove(dirpath) {
|
||||
FS.readdir(dirpath).forEach((filename) => {
|
||||
const p = `${dirpath}/${filename}`;
|
||||
const p_s = FS.stat(p);
|
||||
if (FS.isFile(p_s.mode)) {
|
||||
FS.unlink(p);
|
||||
} else if (FS.isDir(p)) {
|
||||
recursive_remove(p);
|
||||
}
|
||||
});
|
||||
FS.rmdir(dirpath);
|
||||
}("/tmp/filedrop");
|
||||
|
||||
FS.rmdir("/tmp/filedrop");
|
||||
target.removeEventListener("dragover", SDL3.eventHandlerDropDragover);
|
||||
SDL3.eventHandlerDropDragover = undefined;
|
||||
SDL3.eventHandlerDropDrop = undefined;
|
||||
SDL3.eventHandlerDropDragend = undefined;
|
||||
}
|
||||
}, data->canvas_id);
|
||||
}
|
||||
|
||||
void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
||||
{
|
||||
const char *keyElement;
|
||||
@@ -852,12 +991,18 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
||||
// !!! FIXME: currently Emscripten doesn't have a Pointer Events functions like emscripten_set_*_callback, but we should use those when they do:
|
||||
// !!! FIXME: https://github.com/emscripten-core/emscripten/issues/7278#issuecomment-2280024621
|
||||
Emscripten_set_pointer_event_callbacks(data);
|
||||
|
||||
// !!! FIXME: currently Emscripten doesn't have a Drop Events functions like emscripten_set_*_callback, but we should use those when they do:
|
||||
Emscripten_set_drag_event_callbacks(data);
|
||||
}
|
||||
|
||||
void Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
|
||||
{
|
||||
const char *target;
|
||||
|
||||
// !!! FIXME: currently Emscripten doesn't have a Drop Events functions like emscripten_set_*_callback, but we should use those when they do:
|
||||
Emscripten_unset_drag_event_callbacks(data);
|
||||
|
||||
// !!! FIXME: currently Emscripten doesn't have a Pointer Events functions like emscripten_set_*_callback, but we should use those when they do:
|
||||
// !!! FIXME: https://github.com/emscripten-core/emscripten/issues/7278#issuecomment-2280024621
|
||||
Emscripten_unset_pointer_event_callbacks(data);
|
||||
|
||||
Reference in New Issue
Block a user