mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
592 lines
15 KiB
C
592 lines
15 KiB
C
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
|
|
/*
|
|
* JS event class.
|
|
*/
|
|
#include "lm.h"
|
|
#include "lo_ele.h"
|
|
#include "pa_tags.h"
|
|
#include "xp.h"
|
|
#include "prbit.h"
|
|
#include "prtypes.h"
|
|
#include "mkhelp.h" /* For onhelp support */
|
|
#include "jsapi.h" /* For onhelp support */
|
|
|
|
static JSEventNames event_names[] = {
|
|
/* ordered by log2(event_bit) */
|
|
{"mousedown", "MouseDown"},
|
|
{"mouseup", "MouseUp"},
|
|
{"mouseover", "MouseOver"},
|
|
{"mouseout", "MouseOut"},
|
|
{"mousemove", "MouseMove"},
|
|
{"mousedrag", "MouseDrag"},
|
|
{"click", "Click"},
|
|
{"dblclick", "DblClick"},
|
|
{"keydown", "KeyDown"},
|
|
{"keyup", "KeyUp"},
|
|
{"keypress", "KeyPress"},
|
|
{"dragdrop", "DragDrop"},
|
|
{"focus", "Focus"},
|
|
{"blur", "Blur"},
|
|
{"select", "Select"},
|
|
{"change", "Change"},
|
|
{"reset", "Reset"},
|
|
{"submit", "Submit"},
|
|
{"scroll", "Scroll"},
|
|
{"load", "Load"},
|
|
{"unload", "Unload"},
|
|
{"xferdone", "XferDone"},
|
|
{"abort", "Abort"},
|
|
{"error", "Error"},
|
|
{"locate", "Locate"},
|
|
{"move", "Move"},
|
|
{"resize", "Resize"},
|
|
{"forward", "Forward"},
|
|
{"help", "Help"},
|
|
{"back", "Back"},
|
|
};
|
|
|
|
#define NUM_EVENTS (sizeof event_names / sizeof event_names[0])
|
|
|
|
static JSConstDoubleSpec event_constants[] = {
|
|
{EVENT_ALT_MASK , "ALT_MASK"},
|
|
{EVENT_CONTROL_MASK , "CONTROL_MASK"},
|
|
{EVENT_SHIFT_MASK , "SHIFT_MASK"},
|
|
{EVENT_META_MASK , "META_MASK"},
|
|
{EVENT_MOUSEDOWN , "MOUSEDOWN"},
|
|
{EVENT_MOUSEUP , "MOUSEUP"},
|
|
{EVENT_MOUSEOVER , "MOUSEOVER"},
|
|
{EVENT_MOUSEOUT , "MOUSEOUT"},
|
|
{EVENT_MOUSEMOVE , "MOUSEMOVE"},
|
|
{EVENT_MOUSEDRAG , "MOUSEDRAG"},
|
|
{EVENT_CLICK , "CLICK"},
|
|
{EVENT_DBLCLICK , "DBLCLICK"},
|
|
{EVENT_KEYDOWN , "KEYDOWN"},
|
|
{EVENT_KEYUP , "KEYUP"},
|
|
{EVENT_KEYPRESS , "KEYPRESS"},
|
|
{EVENT_DRAGDROP , "DRAGDROP"},
|
|
{EVENT_FOCUS , "FOCUS"},
|
|
{EVENT_BLUR , "BLUR"},
|
|
{EVENT_SELECT , "SELECT"},
|
|
{EVENT_CHANGE , "CHANGE"},
|
|
{EVENT_RESET , "RESET"},
|
|
{EVENT_SUBMIT , "SUBMIT"},
|
|
{EVENT_SCROLL , "SCROLL"},
|
|
{EVENT_LOAD , "LOAD"},
|
|
{EVENT_UNLOAD , "UNLOAD"},
|
|
{EVENT_XFER_DONE , "XFER_DONE"},
|
|
{EVENT_ABORT , "ABORT"},
|
|
{EVENT_ERROR , "ERROR"},
|
|
{EVENT_LOCATE , "LOCATE"},
|
|
{EVENT_MOVE , "MOVE"},
|
|
{EVENT_RESIZE , "RESIZE"},
|
|
{EVENT_FORWARD , "FORWARD"},
|
|
{EVENT_HELP , "HELP"},
|
|
{EVENT_BACK , "BACK"},
|
|
{0, 0}
|
|
};
|
|
|
|
const char *
|
|
lm_EventName(uint32 event_bit)
|
|
{
|
|
uint index = (uint)PR_CeilingLog2(event_bit);
|
|
|
|
if (index >= NUM_EVENTS)
|
|
return "unknown event";
|
|
return event_names[index].lowerName;
|
|
}
|
|
|
|
JSEventNames *
|
|
lm_GetEventNames(uint32 event_bit)
|
|
{
|
|
uint index = (uint)PR_CeilingLog2(event_bit);
|
|
|
|
if (index >= NUM_EVENTS)
|
|
return NULL;
|
|
return &event_names[index];
|
|
}
|
|
|
|
uint32
|
|
lm_FindEventInMWContext(MWContext *context)
|
|
{
|
|
int i;
|
|
XP_List *kids;
|
|
MWContext *kid;
|
|
uint32 events;
|
|
|
|
|
|
if (!context->grid_children)
|
|
return context->event_bit;
|
|
|
|
events = 0;
|
|
|
|
if ((kids = context->grid_children) != NULL) {
|
|
for (i = 1; ((kid = XP_ListGetObjectNum(kids, i)) != NULL); i++) {
|
|
events |= lm_FindEventInMWContext(kid);
|
|
}
|
|
}
|
|
return events;
|
|
}
|
|
|
|
XP_Bool
|
|
LM_EventCaptureCheck(MWContext * context, uint32 current_event) {
|
|
|
|
if (context->event_bit & current_event)
|
|
return TRUE;
|
|
if (context->grid_parent)
|
|
return LM_EventCaptureCheck(context->grid_parent, current_event);
|
|
return FALSE;
|
|
}
|
|
|
|
enum event_tinyid {
|
|
EVENT_TYPE = -1,
|
|
EVENT_X = -2,
|
|
EVENT_Y = -3,
|
|
EVENT_LAYERX = -4,
|
|
EVENT_LAYERY = -5,
|
|
EVENT_WHICH = -6,
|
|
EVENT_MODIFIERS = -7,
|
|
EVENT_DATA = -8,
|
|
EVENT_DOCX = -9,
|
|
EVENT_DOCY = -10,
|
|
EVENT_SCREENX = -11,
|
|
EVENT_SCREENY = -12,
|
|
EVENT_OBJECT = -13
|
|
};
|
|
|
|
static JSPropertySpec event_props[] = {
|
|
{"type" , EVENT_TYPE, JSPROP_ENUMERATE},
|
|
{"x" , EVENT_X, JSPROP_ENUMERATE},
|
|
{"y" , EVENT_Y, JSPROP_ENUMERATE},
|
|
{"width" , EVENT_X, JSPROP_ENUMERATE},
|
|
{"height" , EVENT_Y, JSPROP_ENUMERATE},
|
|
{"layerX" , EVENT_LAYERX, JSPROP_ENUMERATE},
|
|
{"layerY" , EVENT_LAYERY, JSPROP_ENUMERATE},
|
|
{"which" , EVENT_WHICH, JSPROP_ENUMERATE},
|
|
{"modifiers" , EVENT_MODIFIERS, JSPROP_ENUMERATE},
|
|
{"data" , EVENT_DATA, JSPROP_ENUMERATE},
|
|
{"pageX" , EVENT_DOCX, JSPROP_ENUMERATE},
|
|
{"pageY" , EVENT_DOCY, JSPROP_ENUMERATE},
|
|
{"screenX" , EVENT_SCREENX, JSPROP_ENUMERATE},
|
|
{"screenY" , EVENT_SCREENY, JSPROP_ENUMERATE},
|
|
{"target" , EVENT_OBJECT, JSPROP_ENUMERATE},
|
|
{0}
|
|
};
|
|
|
|
extern JSClass lm_event_class;
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|
{
|
|
JSEvent *event;
|
|
JSString *str;
|
|
char ** urlArray;
|
|
jsval urlVal;
|
|
JSObject *array;
|
|
jsint slot;
|
|
|
|
if (!JSVAL_IS_INT(id))
|
|
return JS_TRUE;
|
|
|
|
event = JS_GetInstancePrivate(cx, obj, &lm_event_class, NULL);
|
|
if (!event)
|
|
return JS_TRUE;
|
|
|
|
if (!JSVAL_IS_INT(id))
|
|
return JS_TRUE;
|
|
|
|
/*
|
|
* You might think the following would make a real nice
|
|
* switch() statement. But if you make it into one be
|
|
* ready to battle the Win16 internal compiler error
|
|
* demons.
|
|
*/
|
|
if (JSVAL_TO_INT(id) == EVENT_TYPE) {
|
|
str = JS_NewStringCopyZ(cx, lm_EventName(event->type));
|
|
if (!str)
|
|
return JS_FALSE;
|
|
*vp = STRING_TO_JSVAL(str);
|
|
}
|
|
else if ((JSVAL_TO_INT(id) == EVENT_X) || (JSVAL_TO_INT(id) == EVENT_LAYERX)) {
|
|
* vp = INT_TO_JSVAL(event->x);
|
|
}
|
|
else if ((JSVAL_TO_INT(id) == EVENT_Y) || (JSVAL_TO_INT(id) == EVENT_LAYERY)){
|
|
* vp = INT_TO_JSVAL(event->y);
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_DOCX) {
|
|
* vp = INT_TO_JSVAL(event->docx);
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_DOCY) {
|
|
* vp = INT_TO_JSVAL(event->docy);
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_SCREENX) {
|
|
* vp = INT_TO_JSVAL(event->screenx);
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_SCREENY) {
|
|
* vp = INT_TO_JSVAL(event->screeny);
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_WHICH) {
|
|
if (event->type == EVENT_HELP) {
|
|
/* For onHelp events, the which parameter holds the
|
|
URL of the help topic, as given in the pHelpInfo
|
|
field of the MWContext associated with this window. */
|
|
MWContext *context;
|
|
|
|
context = event->ce.context;
|
|
if (context->pHelpInfo) {
|
|
char *topicID;
|
|
JSString *topicStr;
|
|
|
|
topicID = ((HelpInfoStruct *) (context->pHelpInfo))->topicURL;
|
|
topicStr = JS_NewStringCopyZ(cx, topicID);
|
|
|
|
* vp = STRING_TO_JSVAL(topicStr);
|
|
|
|
}
|
|
else {
|
|
JSString *topicStr;
|
|
|
|
topicStr = JS_NewStringCopyZ(cx, "about:blank"); /* Do not localize */
|
|
* vp = STRING_TO_JSVAL(topicStr);
|
|
}
|
|
|
|
}
|
|
else {
|
|
* vp = INT_TO_JSVAL(event->which);
|
|
}
|
|
}
|
|
else if (JSVAL_TO_INT(id) == EVENT_MODIFIERS) {
|
|
* vp = INT_TO_JSVAL(event->modifiers);
|
|
}
|
|
|
|
else if (JSVAL_TO_INT(id) == EVENT_OBJECT) {
|
|
if (event->object)
|
|
* vp = OBJECT_TO_JSVAL(event->object);
|
|
}
|
|
|
|
else if (JSVAL_TO_INT(id) == EVENT_DATA) {
|
|
if (event->type == EVENT_DRAGDROP) {
|
|
if (lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ)) {
|
|
array = JS_NewArrayObject(cx, 0, NULL);
|
|
if (!array)
|
|
return JS_FALSE;
|
|
|
|
urlArray = (char**)event->data;
|
|
if (!urlArray)
|
|
return JS_TRUE;
|
|
for (slot=0; slot<(jsint)event->dataSize; slot++) {
|
|
str = JS_NewStringCopyZ(cx, urlArray[slot]);
|
|
if (!str)
|
|
return JS_FALSE;
|
|
urlVal = STRING_TO_JSVAL(str);
|
|
if (!JS_SetElement(cx, array, slot, &urlVal))
|
|
return JS_FALSE;
|
|
}
|
|
|
|
*vp = OBJECT_TO_JSVAL(array);
|
|
}
|
|
}
|
|
}
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
static JSBool
|
|
GetUint32(JSContext *cx, jsval v, uint32 *uip)
|
|
{
|
|
jsdouble d;
|
|
|
|
if (!JS_ValueToNumber(cx, v, &d))
|
|
return JS_FALSE;
|
|
*uip = (uint32)d;
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|
{
|
|
JSEvent *event;
|
|
jsint slot, i;
|
|
JSString *str;
|
|
const char *name;
|
|
uint32 temp;
|
|
|
|
if (!JSVAL_IS_INT(id))
|
|
return JS_TRUE;
|
|
|
|
event = JS_GetInstancePrivate(cx, obj, &lm_event_class, NULL);
|
|
if (!event)
|
|
return JS_TRUE;
|
|
|
|
slot = JSVAL_TO_INT(id);
|
|
|
|
if (slot==EVENT_TYPE) {
|
|
if (!JSVAL_IS_STRING(*vp) || !(str = JS_ValueToString(cx, *vp)))
|
|
return JS_FALSE;
|
|
name = JS_GetStringBytes(str);
|
|
for (i = 0; i < NUM_EVENTS; i++) {
|
|
if (!XP_STRCASECMP(event_names[i].lowerName, name))
|
|
event->type = PR_BIT(i);
|
|
}
|
|
}
|
|
else if ((slot==EVENT_X) || (slot==EVENT_LAYERX))
|
|
return JS_ValueToInt32(cx, *vp, &event->x);
|
|
else if ((slot==EVENT_Y) || (slot==EVENT_LAYERY))
|
|
return JS_ValueToInt32(cx, *vp, &event->y);
|
|
else if (slot==EVENT_DOCX)
|
|
return JS_ValueToInt32(cx, *vp, &event->docx);
|
|
else if (slot==EVENT_DOCY)
|
|
return JS_ValueToInt32(cx, *vp, &event->docy);
|
|
else if (slot==EVENT_SCREENX)
|
|
return JS_ValueToInt32(cx, *vp, &event->screenx);
|
|
else if (slot==EVENT_SCREENY)
|
|
return JS_ValueToInt32(cx, *vp, &event->screeny);
|
|
else if (slot==EVENT_WHICH)
|
|
return GetUint32(cx, *vp, &event->which);
|
|
else if (slot==EVENT_MODIFIERS)
|
|
GetUint32(cx, *vp, &temp);
|
|
event->modifiers = temp;
|
|
return JS_TRUE;
|
|
/* Win16 hack */
|
|
/*else if (slot==EVENT_DATA) {
|
|
GetUint32(cx, *vp, &temp);
|
|
event->data = temp;
|
|
return JS_TRUE;
|
|
} */
|
|
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
event_finalize(JSContext *cx, JSObject *obj)
|
|
{
|
|
JSEvent *event;
|
|
|
|
event = JS_GetPrivate(cx, obj);
|
|
if (!event)
|
|
return;
|
|
DROP_BACK_COUNT(event->decoder);
|
|
JS_free(cx, event);
|
|
}
|
|
|
|
JSClass lm_event_class = {
|
|
"Event", JSCLASS_HAS_PRIVATE,
|
|
JS_PropertyStub, JS_PropertyStub, event_getProperty, event_setProperty,
|
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, event_finalize
|
|
};
|
|
|
|
|
|
static JSBool
|
|
InitEventObject(JSContext *cx, JSObject *obj, JSEvent *pEvent)
|
|
|
|
{
|
|
MochaDecoder *decoder;
|
|
|
|
XP_ASSERT(JS_InstanceOf(cx, obj, &lm_event_class, NULL));
|
|
|
|
if (!JS_SetPrivate(cx, obj, pEvent)) {
|
|
JS_free(cx, pEvent);
|
|
return JS_FALSE;
|
|
}
|
|
|
|
decoder = JS_GetPrivate(cx, JS_GetGlobalObject(cx));
|
|
pEvent->decoder = HOLD_BACK_COUNT(decoder);
|
|
pEvent->saved = JS_TRUE;
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
lm_Event(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
JSEvent *pEvent;
|
|
|
|
if (!JS_InstanceOf(cx, obj, &lm_event_class, argv))
|
|
return JS_FALSE;
|
|
|
|
pEvent = JS_malloc(cx, sizeof(JSEvent));
|
|
if (!pEvent)
|
|
return JS_FALSE;
|
|
XP_BZERO(pEvent, sizeof(JSEvent));
|
|
|
|
/* Need to decide what arguments can be used */
|
|
|
|
if (!InitEventObject(cx, obj, pEvent))
|
|
return JS_FALSE;
|
|
*rval = OBJECT_TO_JSVAL(obj);
|
|
return JS_TRUE;
|
|
}
|
|
|
|
static JSClass event_receiver_class = {
|
|
"EventReceiver", 0,
|
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
|
};
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
EventReceiver(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_receiver_handle_event(JSContext *cx, JSObject *obj,
|
|
uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
JSObject *eventObj;
|
|
|
|
if (argc != 1)
|
|
return JS_TRUE;
|
|
|
|
if (!JSVAL_IS_OBJECT(argv[0]) &&
|
|
!JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0]))
|
|
return JS_FALSE;
|
|
|
|
eventObj = JSVAL_TO_OBJECT(argv[0]);
|
|
if (!JS_InstanceOf(cx, eventObj, &lm_event_class, argv))
|
|
return JS_FALSE;
|
|
|
|
return lm_HandleEvent(cx, obj, eventObj, JSVAL_NULL, rval);
|
|
}
|
|
|
|
static JSFunctionSpec event_receiver_methods[] = {
|
|
{"handleEvent", event_receiver_handle_event, 1},
|
|
{0}
|
|
};
|
|
|
|
static JSClass event_capturer_class = {
|
|
"EventCapturer", 0,
|
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
|
};
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
EventCapturer(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_capturer_route_event(JSContext *cx, JSObject *obj,
|
|
uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
JSObject *eventObj;
|
|
JSEvent *event;
|
|
|
|
if (argc != 1)
|
|
return JS_TRUE;
|
|
|
|
if (!JSVAL_IS_OBJECT(argv[0]) &&
|
|
!JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0]))
|
|
return JS_FALSE;
|
|
|
|
eventObj = JSVAL_TO_OBJECT(argv[0]);
|
|
if (!(event = JS_GetInstancePrivate (cx, eventObj, &lm_event_class, argv)))
|
|
return JS_FALSE;
|
|
|
|
/* Routing objects to themselves causes infinite recursion.
|
|
* And that's a big no-no.
|
|
*/
|
|
if (event->object == obj)
|
|
return JS_TRUE;
|
|
|
|
if (!event->object || !event->decoder || !event->decoder->window_context)
|
|
return JS_TRUE;
|
|
return lm_FindEventHandler(event->decoder->window_context,
|
|
event->object, eventObj, JSVAL_NULL,
|
|
rval);
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_capturer_capture_events(JSContext *cx, JSObject *obj,
|
|
uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
return JS_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(JSBool)
|
|
event_capturer_release_events(JSContext *cx, JSObject *obj,
|
|
uint argc, jsval *argv, jsval *rval)
|
|
{
|
|
return JS_TRUE;
|
|
}
|
|
|
|
static JSFunctionSpec event_capturer_methods[] = {
|
|
{"routeEvent", event_capturer_route_event, 1},
|
|
{"captureEvents", event_capturer_capture_events, 1},
|
|
{"releaseEvents", event_capturer_release_events, 1},
|
|
{0}
|
|
};
|
|
|
|
JSBool
|
|
lm_InitEventClasses(MochaDecoder *decoder)
|
|
{
|
|
JSContext *cx;
|
|
JSObject *prototype, *ctor;
|
|
|
|
cx = decoder->js_context;
|
|
|
|
prototype = JS_InitClass(cx, decoder->window_object, NULL, &lm_event_class,
|
|
lm_Event, 0, event_props, NULL, NULL, NULL);
|
|
|
|
if (!prototype|| !(ctor = JS_GetConstructor(cx, prototype)))
|
|
return JS_FALSE;
|
|
|
|
if (!JS_DefineConstDoubles(cx, ctor, event_constants))
|
|
return JS_FALSE;
|
|
|
|
decoder->event_prototype = prototype;
|
|
|
|
prototype = JS_InitClass(cx, decoder->window_object, NULL,
|
|
&event_receiver_class, EventReceiver, 0,
|
|
NULL, event_receiver_methods, NULL, NULL);
|
|
|
|
if (!prototype)
|
|
return JS_FALSE;
|
|
decoder->event_receiver_prototype = prototype;
|
|
|
|
prototype = JS_InitClass(cx, decoder->window_object,
|
|
decoder->event_receiver_prototype,
|
|
&event_capturer_class, EventCapturer, 0,
|
|
NULL, event_capturer_methods, NULL, NULL);
|
|
|
|
|
|
if (!prototype)
|
|
return JS_FALSE;
|
|
decoder->event_capturer_prototype = prototype;
|
|
return JS_TRUE;
|
|
}
|
|
|
|
|
|
JSObject *
|
|
lm_NewEventObject(MochaDecoder * decoder, JSEvent *pEvent)
|
|
{
|
|
JSContext * cx;
|
|
JSObject *obj;
|
|
|
|
cx = decoder->js_context;
|
|
obj = JS_NewObject(cx, &lm_event_class, decoder->event_prototype, 0);
|
|
if (!obj)
|
|
return NULL;
|
|
if (!InitEventObject(cx, obj, pEvent))
|
|
return NULL;
|
|
return obj;
|
|
}
|