Browse Source

Add custom event handling to wasm

gingerBill 3 years ago
parent
commit
7420fbd95b
2 changed files with 71 additions and 17 deletions
  1. 30 3
      vendor/wasm/js/events.odin
  2. 41 14
      vendor/wasm/js/runtime.js

+ 30 - 3
vendor/wasm/js/events.odin

@@ -79,6 +79,8 @@ Event_Kind :: enum u32 {
 
 	Context_Menu,
 
+	Custom,
+
 }
 event_kind_string := [Event_Kind]string{
 	.Invalid = "",
@@ -155,6 +157,8 @@ event_kind_string := [Event_Kind]string{
 	.Touch_Start  = "touchstart",
 
 	.Context_Menu = "contextmenu",
+
+	.Custom = "?custom?",
 }
 
 Delta_Mode :: enum u32 {
@@ -186,6 +190,13 @@ Event_Phase :: enum u8 {
 	Bubbling_Phase  = 3,
 }
 
+Event_Option :: enum u8 {
+	Bubbles    = 0,
+	Cancelable = 1,
+	Composed   = 2,
+}
+Event_Options :: distinct bit_set[Event_Option; u8]
+
 Event :: struct {
 	kind:                 Event_Kind,
 	target_kind:          Event_Target_Kind,
@@ -194,9 +205,7 @@ Event :: struct {
 	timestamp:    f64,
 
 	phase:        Event_Phase,
-	bubbles:      bool,
-	cancelable:   bool,
-	composed:     bool,
+	options:      Event_Options,
 	is_composing: bool,
 	is_trusted:   bool,
 
@@ -255,6 +264,7 @@ foreign dom_lib {
 	event_stop_propagation           :: proc() ---
 	event_stop_immediate_propagation :: proc() ---
 	event_prevent_default            :: proc() ---
+	dispatch_custom_event            :: proc(id: string, name: string, options := Event_Options{}) -> bool ---
 }
 
 add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@@ -301,6 +311,23 @@ remove_event_listener_from_event :: proc(e: Event) -> bool {
 	return remove_event_listener(e.id, e.kind, e.user_data, e.callback)
 }
 
+add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
+	@(default_calling_convention="contextless")
+	foreign dom_lib {
+		@(link_name="add_event_listener")
+		_add_event_listener :: proc(id: string, name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
+	}
+	return _add_event_listener(id, name, .Custom, user_data, callback, use_capture)
+}
+remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
+	@(default_calling_convention="contextless")
+	foreign dom_lib {
+		@(link_name="remove_event_listener")
+		_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
+	}
+	return _remove_event_listener(id, name, user_data, callback)
+}
+
 
 
 

+ 41 - 14
vendor/wasm/js/runtime.js

@@ -1,6 +1,14 @@
 "use strict";
 
 (function() {
+
+function getElement(name) {
+	if (name) {
+		return document.getElementById(name);
+	}
+	return undefined;
+}
+
 class WasmMemoryInterface {
 	constructor() {
 		this.memory = null;
@@ -204,12 +212,12 @@ class WebGLInterface {
 		return {
 			SetCurrentContextById: (name_ptr, name_len) => {
 				let name = this.mem.loadString(name_ptr, name_len);
-				let element = document.getElementById(name);
+				let element = getElement(name);
 				return this.setCurrentContext(element, {alpha: true, antialias: true, depth: true, premultipliedAlpha: true});
 			},
 			CreateCurrentContextById: (name_ptr, name_len, attributes) => {
 				let name = this.mem.loadString(name_ptr, name_len);
-				let element = document.getElementById(name);
+				let element = getElement(name);
 
 				let contextSettings = {
 					alpha:                        !(attributes & (1<<0)),
@@ -1380,9 +1388,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 				wmi.storeF64(off(8), e.timeStamp*1e-3);
 
 				wmi.storeU8(off(1), e.eventPhase);
-				wmi.storeU8(off(1), !!e.bubbles);
-				wmi.storeU8(off(1), !!e.cancelable);
-				wmi.storeU8(off(1), !!e.composed);
+				let options = 0;
+				if (!!e.bubbles)    { options |= 1<<0; }
+				if (!!e.cancelable) { options |= 1<<1; }
+				if (!!e.composed)   { options |= 1<<2; }
+				wmi.storeU8(off(1), options);
 				wmi.storeU8(off(1), !!e.isComposing);
 				wmi.storeU8(off(1), !!e.isTrusted);
 
@@ -1433,7 +1443,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			add_event_listener: (id_ptr, id_len, name_ptr, name_len, name_code, data, callback, use_capture) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
 				let name = wasmMemoryInterface.loadString(name_ptr, name_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element == undefined) {
 					return false;
 				}
@@ -1454,7 +1464,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
 				let name = wasmMemoryInterface.loadString(name_ptr, name_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element == undefined) {
 					return false;
 				}
@@ -1514,14 +1524,31 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 				}
 			},
 
+			dispatch_custom_event: (id_ptr, id_len, name_ptr, name_len, options_bits) => {
+				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
+				let name = wasmMemoryInterface.loadString(name_ptr, name_len);
+				let options = {
+					bubbles:   (options_bits & (1<<0)) !== 0,
+					cancelabe: (options_bits & (1<<1)) !== 0,
+					composed:  (options_bits & (1<<2)) !== 0,
+				};
+
+				let element = getElement(id);
+				if (element) {
+					element.dispatchEvent(new Event(name, options));
+					return true;
+				}
+				return false;
+			},
+
 			get_element_value_f64: (id_ptr, id_len) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				return element ? element.value : 0;
 			},
 			get_element_value_string: (id_ptr, id_len, buf_ptr, buf_len) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					let str = element.value;
 					if (buf_len > 0 && buf_ptr) {
@@ -1535,7 +1562,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			},
 			get_element_value_string_length: (id_ptr, id_len) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					return element.value.length;
 				}
@@ -1543,7 +1570,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			},
 			get_element_min_max: (ptr_array2_f64, id_ptr, id_len) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					let values = wasmMemoryInterface.loadF64Array(ptr_array2_f64, 2);
 					values[0] = element.min;
@@ -1552,7 +1579,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			},
 			set_element_value_f64: (id_ptr, id_len, value) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					element.value = value;
 				}
@@ -1560,7 +1587,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 			set_element_value_string: (id_ptr, id_len, value_ptr, value_id) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
 				let value = wasmMemoryInterface.loadString(value_ptr, value_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					element.value = value;
 				}
@@ -1569,7 +1596,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
 
 			get_bounding_client_rect: (rect_ptr, id_ptr, id_len) => {
 				let id = wasmMemoryInterface.loadString(id_ptr, id_len);
-				let element = document.getElementById(id);
+				let element = getElement(id);
 				if (element) {
 					let values = wasmMemoryInterface.loadF64Array(rect_ptr, 4);
 					let rect = element.getBoundingClientRect();