From 26d066d369de27892de66d3eefb8d2a4a54e5b7c Mon Sep 17 00:00:00 2001 From: Bailey Gibbons Date: Fri, 22 Aug 2025 15:34:50 +1000 Subject: [PATCH] Add `add/remove_document_event_listener()` to `core:sys/wasm/js` --- core/sys/wasm/js/events.odin | 20 +++++++++++++ core/sys/wasm/js/events_all_targets.odin | 8 ++++++ core/sys/wasm/js/odin.js | 36 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/core/sys/wasm/js/events.odin b/core/sys/wasm/js/events.odin index 37a6e6c35..f5a47c06b 100644 --- a/core/sys/wasm/js/events.odin +++ b/core/sys/wasm/js/events.odin @@ -373,12 +373,32 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba return _remove_window_event_listener(event_kind_string[kind], user_data, callback, use_capture) } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="add_document_event_listener") + _add_document_event_listener :: proc(name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _add_document_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture) +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="remove_document_event_listener") + _remove_document_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _remove_document_event_listener(event_kind_string[kind], user_data, callback, use_capture) +} + remove_event_listener_from_event :: proc(e: Event) -> bool { from_use_capture_false: bool from_use_capture_true: bool if e.id == "" { from_use_capture_false = remove_window_event_listener(e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_window_event_listener(e.kind, e.user_data, e.callback, true) + from_use_capture_false |= remove_document_event_listener(e.kind, e.user_data, e.callback, false) + from_use_capture_true |= remove_document_event_listener(e.kind, e.user_data, e.callback, true) } else { from_use_capture_false = remove_event_listener(e.id, e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_event_listener(e.id, e.kind, e.user_data, e.callback, true) diff --git a/core/sys/wasm/js/events_all_targets.odin b/core/sys/wasm/js/events_all_targets.odin index 6439396c5..903252c7a 100644 --- a/core/sys/wasm/js/events_all_targets.odin +++ b/core/sys/wasm/js/events_all_targets.odin @@ -275,6 +275,14 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba panic("vendor:wasm/js not supported on non JS targets") } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + remove_event_listener_from_event :: proc(e: Event) -> bool { panic("vendor:wasm/js not supported on non JS targets") } diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index 1fbcc886e..2a8ccdd5e 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -1738,6 +1738,28 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { return true; }, + add_document_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + let key = listener_key('document', name, data, callback, !!use_capture); + if (wasmMemoryInterface.listenerMap.has(key)) { + return false; + } + + let listener = (e) => { + let event_data = {}; + event_data.id_ptr = 0; + event_data.id_len = 0; + event_data.event = e; + event_data.name_code = name_code; + + onEventReceived(event_data, data, callback); + }; + wasmMemoryInterface.listenerMap.set(key, listener); + element.addEventListener(name, listener, !!use_capture); + return true; + }, + remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback, use_capture) => { let id = wasmMemoryInterface.loadString(id_ptr, id_len); let name = wasmMemoryInterface.loadString(name_ptr, name_len); @@ -1770,6 +1792,20 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { element.removeEventListener(name, listener, !!use_capture); return true; }, + remove_document_event_listener: (name_ptr, name_len, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + + let key = listener_key('document', name, data, callback, !!use_capture); + let listener = wasmMemoryInterface.listenerMap.get(key); + if (listener === undefined) { + return false; + } + wasmMemoryInterface.listenerMap.delete(key); + + element.removeEventListener(name, listener, !!use_capture); + return true; + }, event_stop_propagation: () => { if (event_temp.data && event_temp.data.event) {