From 897acff532415ed81f9066b8b811ae744918da84 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 4 Dec 2012 18:01:11 +0000 Subject: make events work on elements --- javascript/js.h | 14 ++- javascript/jsapi.c | 120 ++++++++++++++++--- javascript/jsapi/htmlelement.bnd | 246 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 353 insertions(+), 27 deletions(-) (limited to 'javascript') diff --git a/javascript/js.h b/javascript/js.h index 643ce5a56..44de4fe3d 100644 --- a/javascript/js.h +++ b/javascript/js.h @@ -26,6 +26,10 @@ typedef struct jscontext jscontext; typedef struct jsobject jsobject; +struct dom_document; +struct dom_node; +struct dom_string; + /** Initialise javascript interpreter */ void js_initialise(void); @@ -51,10 +55,16 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv); /* execute some javascript in a context */ bool js_exec(jscontext *ctx, const char *txt, size_t txtlen); -struct dom_document; -struct dom_node; /* fire an event at a dom node */ bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target); +bool +js_dom_event_add_listener(jscontext *ctx, + struct dom_document *document, + struct dom_node *node, + struct dom_string *event_type_dom, + void *js_funcval); + + #endif /* _NETSURF_JAVASCRIPT_JS_H_ */ diff --git a/javascript/jsapi.c b/javascript/jsapi.c index e5b4ddf6e..eebb33fee 100644 --- a/javascript/jsapi.c +++ b/javascript/jsapi.c @@ -32,7 +32,7 @@ void js_initialise(void) /* Create a JS runtime. */ #if JS_VERSION >= 180 - JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */ + JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */ #endif rt = JS_NewRuntime(8L * 1024L * 1024L); @@ -97,7 +97,7 @@ void js_destroycontext(jscontext *ctx) * * This performs the following actions * 1. constructs a new global object by initialising a window class - * 2. Instantiate the global a window object + * 2. Instantiate the global a window object */ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv) { @@ -116,7 +116,7 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv) } window = jsapi_new_Window(cx, window_proto, NULL, win_priv, doc_priv); - + return (jsobject *)window; } @@ -139,9 +139,9 @@ bool js_exec(jscontext *ctx, const char *txt, size_t txtlen) return false; } - if (JS_EvaluateScript(cx, - JS_GetGlobalObject(cx), - txt, txtlen, + if (JS_EvaluateScript(cx, + JS_GetGlobalObject(cx), + txt, txtlen, "", 0, &rval) == JS_TRUE) { return true; @@ -174,8 +174,8 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node JSLOG("Dispatching event %s at window", type); /* create and initialise and event object */ - exc = dom_string_create((unsigned char*)type, - strlen(type), + exc = dom_string_create((unsigned char*)type, + strlen(type), &type_dom); if (exc != DOM_NO_ERR) { return false; @@ -200,18 +200,18 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node /* dispatch event at the window object */ argv[0] = OBJECT_TO_JSVAL(jsevent); - ret = JS_CallFunctionName(cx, - JS_GetGlobalObject(cx), - "dispatchEvent", - 1, - argv, + ret = JS_CallFunctionName(cx, + JS_GetGlobalObject(cx), + "dispatchEvent", + 1, + argv, &rval); } else { JSLOG("Dispatching event %s at %p", type, node); /* create and initialise and event object */ - exc = dom_string_create((unsigned char*)type, - strlen(type), + exc = dom_string_create((unsigned char*)type, + strlen(type), &type_dom); if (exc != DOM_NO_ERR) { return false; @@ -237,3 +237,93 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node } return false; } + +struct js_dom_event_private { + JSContext *cx; /* javascript context */ + jsval funcval; /* javascript function to call */ + struct dom_node *node; /* dom node event listening on */ + dom_string *type; /* event type */ + dom_event_listener *listener; /* the listener containing this */ +}; + +static void +js_dom_event_listener(struct dom_event *event, void *pw) +{ + struct js_dom_event_private *private = pw; + jsval event_argv[1]; + jsval event_rval; + JSObject *jsevent; + + JSLOG("WOOT dom event with %p", private); + + if (!JSVAL_IS_VOID(private->funcval)) { + jsevent = jsapi_new_Event(private->cx, NULL, NULL, event); + if (jsevent != NULL) { + + /* dispatch event at the window object */ + event_argv[0] = OBJECT_TO_JSVAL(jsevent); + + JS_CallFunctionValue(private->cx, + NULL, + private->funcval, + 1, + event_argv, + &event_rval); + } + } +} + +/* add a listener to a dom node + * + * 1. Create a dom_event_listener From a handle_event function pointer + * and a private word In a document context + * + * 2. Register for your events on a target (dom nodes are targets) + * dom_event_target_add_event_listener(node, evt_name, listener, + * capture_or_not) + * + */ + +bool +js_dom_event_add_listener(jscontext *ctx, + struct dom_document *document, + struct dom_node *node, + struct dom_string *event_type_dom, + void *js_funcval) +{ + JSContext *cx = (JSContext *)ctx; + dom_exception exc; + struct js_dom_event_private *private; + + private = malloc(sizeof(struct js_dom_event_private)); + if (private == NULL) { + return false; + } + + exc = dom_event_listener_create(document, + js_dom_event_listener, + private, + &private->listener); + if (exc != DOM_NO_ERR) { + return false; + } + + private->cx = cx; + private->funcval = *(jsval *)js_funcval; + private->node = node; + private->type = event_type_dom; + + JSLOG("adding %p to listener", private); + + JS_AddValueRoot(cx, &private->funcval); + exc = dom_event_target_add_event_listener(private->node, + private->type, + private->listener, + true); + if (exc != DOM_NO_ERR) { + JSLOG("failed to add listener"); + JS_RemoveValueRoot(cx, &private->funcval); + } + + return true; +} diff --git a/javascript/jsapi/htmlelement.bnd b/javascript/jsapi/htmlelement.bnd index 15fe83e9c..e1bd2c813 100644 --- a/javascript/jsapi/htmlelement.bnd +++ b/javascript/jsapi/htmlelement.bnd @@ -23,7 +23,9 @@ preamble %{ #include "utils/config.h" #include "utils/log.h" +#include "utils/corestrings.h" +#include "javascript/js.h" #include "javascript/jsapi.h" #include "javascript/jsapi/binding.h" @@ -218,24 +220,248 @@ getter childElementCount %{ %} getter EventHandler %{ - JSLOG("propname[%d]=\"%s\"", + JSLOG("propname[%d].name=\"%s\"", tinyid, jsclass_properties[tinyid].name); %} + setter EventHandler %{ - JSLOG("propname[%d]=\"%s\"", - tinyid, + dom_string *event_type_dom; + + JSLOG("propname[%d].name=\"%s\"", + tinyid, jsclass_properties[tinyid].name); -/* -1. Create a dom_event_listener From a handle_event function pointer - and a private word In a document context + switch (tinyid) { + case JSAPI_PROP_TINYID_onabort: + event_type_dom = corestring_dom_abort; + break; -2. Register for your events on a target (dom nodes are targets) - dom_event_target_add_event_listener(node, evt_name, listener, - capture_or_not) + case JSAPI_PROP_TINYID_onblur: + event_type_dom = corestring_dom_blur; + break; - */ + case JSAPI_PROP_TINYID_oncancel: + event_type_dom = corestring_dom_cancel; + break; + + case JSAPI_PROP_TINYID_oncanplay: + event_type_dom = corestring_dom_canplay; + break; + + case JSAPI_PROP_TINYID_oncanplaythrough: + event_type_dom = corestring_dom_canplaythrough; + break; + + case JSAPI_PROP_TINYID_onchange: + event_type_dom = corestring_dom_change; + break; + + case JSAPI_PROP_TINYID_onclick: + event_type_dom = corestring_dom_click; + break; + + case JSAPI_PROP_TINYID_onclose: + event_type_dom = corestring_dom_close; + break; + + case JSAPI_PROP_TINYID_oncontextmenu: + event_type_dom = corestring_dom_contextmenu; + break; + + case JSAPI_PROP_TINYID_oncuechange: + event_type_dom = corestring_dom_cuechange; + break; + + case JSAPI_PROP_TINYID_ondblclick: + event_type_dom = corestring_dom_dblclick; + break; + + case JSAPI_PROP_TINYID_ondrag: + event_type_dom = corestring_dom_drag; + break; + + case JSAPI_PROP_TINYID_ondragend: + event_type_dom = corestring_dom_dragend; + break; + + case JSAPI_PROP_TINYID_ondragenter: + event_type_dom = corestring_dom_dragenter; + break; + + case JSAPI_PROP_TINYID_ondragleave: + event_type_dom = corestring_dom_dragleave; + break; + + case JSAPI_PROP_TINYID_ondragover: + event_type_dom = corestring_dom_dragover; + break; + + case JSAPI_PROP_TINYID_ondragstart: + event_type_dom = corestring_dom_dragstart; + break; + + case JSAPI_PROP_TINYID_ondrop: + event_type_dom = corestring_dom_drop; + break; + + case JSAPI_PROP_TINYID_ondurationchange: + event_type_dom = corestring_dom_durationchange; + break; + + case JSAPI_PROP_TINYID_onemptied: + event_type_dom = corestring_dom_emptied; + break; + + case JSAPI_PROP_TINYID_onended: + event_type_dom = corestring_dom_ended; + break; + + case JSAPI_PROP_TINYID_onerror: + event_type_dom = corestring_dom_error; + break; + + case JSAPI_PROP_TINYID_onfocus: + event_type_dom = corestring_dom_focus; + break; + + case JSAPI_PROP_TINYID_oninput: + event_type_dom = corestring_dom_input; + break; + + case JSAPI_PROP_TINYID_oninvalid: + event_type_dom = corestring_dom_invalid; + break; + + case JSAPI_PROP_TINYID_onkeydown: + event_type_dom = corestring_dom_keydown; + break; + + case JSAPI_PROP_TINYID_onkeypress: + event_type_dom = corestring_dom_keypress; + break; + + case JSAPI_PROP_TINYID_onkeyup: + event_type_dom = corestring_dom_keyup; + break; + + case JSAPI_PROP_TINYID_onload: + event_type_dom = corestring_dom_load; + break; + + case JSAPI_PROP_TINYID_onloadeddata: + event_type_dom = corestring_dom_loadeddata; + break; + + case JSAPI_PROP_TINYID_onloadedmetadata: + event_type_dom = corestring_dom_loadedmetadata; + break; + + case JSAPI_PROP_TINYID_onloadstart: + event_type_dom = corestring_dom_loadstart; + break; + + case JSAPI_PROP_TINYID_onmousedown: + event_type_dom = corestring_dom_mousedown; + break; + + case JSAPI_PROP_TINYID_onmousemove: + event_type_dom = corestring_dom_mousemove; + break; + + case JSAPI_PROP_TINYID_onmouseout: + event_type_dom = corestring_dom_mouseout; + break; + + case JSAPI_PROP_TINYID_onmouseover: + event_type_dom = corestring_dom_mouseover; + break; + + case JSAPI_PROP_TINYID_onmouseup: + event_type_dom = corestring_dom_mouseup; + break; + + case JSAPI_PROP_TINYID_onmousewheel: + event_type_dom = corestring_dom_mousewheel; + break; + + case JSAPI_PROP_TINYID_onpause: + event_type_dom = corestring_dom_pause; + break; + + case JSAPI_PROP_TINYID_onplay: + event_type_dom = corestring_dom_play; + break; + + case JSAPI_PROP_TINYID_onplaying: + event_type_dom = corestring_dom_playing; + break; + + case JSAPI_PROP_TINYID_onprogress: + event_type_dom = corestring_dom_progress; + break; + + case JSAPI_PROP_TINYID_onratechange: + event_type_dom = corestring_dom_ratechange; + break; + + case JSAPI_PROP_TINYID_onreset: + event_type_dom = corestring_dom_reset; + break; + + case JSAPI_PROP_TINYID_onscroll: + event_type_dom = corestring_dom_scroll; + break; + + case JSAPI_PROP_TINYID_onseeked: + event_type_dom = corestring_dom_seeked; + break; + + case JSAPI_PROP_TINYID_onseeking: + event_type_dom = corestring_dom_seeking; + break; + + case JSAPI_PROP_TINYID_onselect: + event_type_dom = corestring_dom_select; + break; + + case JSAPI_PROP_TINYID_onshow: + event_type_dom = corestring_dom_show; + break; + + case JSAPI_PROP_TINYID_onstalled: + event_type_dom = corestring_dom_stalled; + break; + + case JSAPI_PROP_TINYID_onsubmit: + event_type_dom = corestring_dom_submit; + break; + + case JSAPI_PROP_TINYID_onsuspend: + event_type_dom = corestring_dom_suspend; + break; + + case JSAPI_PROP_TINYID_ontimeupdate: + event_type_dom = corestring_dom_timeupdate; + break; + + case JSAPI_PROP_TINYID_onvolumechange: + event_type_dom = corestring_dom_volumechange; + break; + + case JSAPI_PROP_TINYID_onwaiting: + event_type_dom = corestring_dom_waiting; + break; + + default: + JSLOG("called with unknown tinyid"); + return JS_TRUE; + } + js_dom_event_add_listener((struct jscontext *)cx, + private->htmlc->document, + (dom_node *)private->node, + event_type_dom, + vp); %} -- cgit v1.2.3