DEFINE_CONSTRUCTOR() { JL_ASSERT_CONSTRUCTING(); JL_DEFINE_CONSTRUCTOR_OBJ; // JSClass *test = JL_GetClass(obj); HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL); JL_ASSERT( hInst != NULL, "Unable to GetModuleHandle." ); // hCursor doc: To use a predefined cursors, the application must set the hInstance parameter to NULL and the lpCursorName parameter to one the cursor values. WNDCLASS wc = { CS_HREDRAW | CS_VREDRAW | CS_OWNDC, (WNDPROC)WndProc, 0, 0, hInst, LoadIcon((HINSTANCE)NULL, IDI_APPLICATION), LoadCursor((HINSTANCE) NULL, IDC_ARROW), NULL, NULL, WINDOW_CLASS_NAME }; ATOM rc = RegisterClass(&wc); JL_ASSERT( rc != 0, "Unable to RegisterClass." ); // http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=01 // AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); HWND hWnd = CreateWindow( (LPSTR)rc, NULL, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL, (HMENU)NULL, hInst, (LPVOID)NULL); JL_ASSERT( hWnd != NULL, "Unable to CreateWindow." ); CxObj *cxobj = (CxObj*)jl_malloc(sizeof(CxObj)); JL_ASSERT_ALLOC( cxobj ); cxobj->cx = cx; cxobj->obj = obj; DWORD err; JL_SAFE(SetLastError(0)); LONG prevWindowLong = SetWindowLong(hWnd, GWL_USERDATA, (LONG)cxobj ); JL_ASSERT( prevWindowLong != 0 || (err=GetLastError()) == 0, "Unable to SetWindowLong. (error %d)", err ); JL_SetPrivate(obj, hWnd); return true; }
bool32 runNormalizationTest(int32 numVectors, float32 scalarMin, float32 scalarMax) { JL_ASSERT(numVectors > 0); JL_ASSERT(scalarMin <= scalarMax); jlVector4 *arr = generateRandomVectors(numVectors, scalarMin, scalarMax); if (!arr) return 0; normalizeVectors(arr, numVectors); delete [] arr; return 1; }
// The Effects of Double Buffering on Animation Frame Rates // http://www.futuretech.blinkenlights.nl/dbuffer.html bool _SwapBuffers(JSContext *cx, JSObject *obj, unsigned argc, jsval *argv, jsval *rval) { // glFlush(); // glFinish(); // JL_ASSERT( JL_GetClass(obj) == _class, RT_ERROR_INVALID_CLASS ); HDC hDC = wglGetCurrentDC(); // (TBD) un-specialize from OpenGL JL_ASSERT( hDC != NULL, "Could not get the Current Device Context." ); BOOL res = SwapBuffers(hDC); // Doc: With multithread applications, flush the drawing commands in any other threads drawing to the same window before calling SwapBuffers. JL_ASSERT( res, "Unable to SwapBuffers.(%x)", GetLastError() ); return true; }
jlMatrix4 * generateRandomMatrices(int32 numMatrices, float32 scalarMin, float32 scalarMax) { JL_ASSERT(numMatrices > 0); jlMatrix4 *matrices = new jlMatrix4[numMatrices]; if (matrices) { jlRandom random; random.init(numMatrices); random.seed(jlRandom::DEFAULT_SEED); for (int32 i = 0; i < numMatrices; ++i) { float32 m00, m01, m02, m03; float32 m10, m11, m12, m13; float32 m20, m21, m22, m23; float32 m30, m31, m32, m33; m00 = random.randFloat32(scalarMin, scalarMax); m01 = random.randFloat32(scalarMin, scalarMax); m02 = random.randFloat32(scalarMin, scalarMax); m03 = random.randFloat32(scalarMin, scalarMax); m10 = random.randFloat32(scalarMin, scalarMax); m11 = random.randFloat32(scalarMin, scalarMax); m12 = random.randFloat32(scalarMin, scalarMax); m13 = random.randFloat32(scalarMin, scalarMax); m20 = random.randFloat32(scalarMin, scalarMax); m21 = random.randFloat32(scalarMin, scalarMax); m22 = random.randFloat32(scalarMin, scalarMax); m23 = random.randFloat32(scalarMin, scalarMax); m30 = random.randFloat32(scalarMin, scalarMax); m31 = random.randFloat32(scalarMin, scalarMax); m32 = random.randFloat32(scalarMin, scalarMax); m33 = random.randFloat32(scalarMin, scalarMax); matrices[i] = jlMatrix4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33); } } return matrices; }
/**doc $TOC_MEMBER $INAME $INAME( world, [ jointGroup ] ) TBD **/ DEFINE_CONSTRUCTOR() { ode::dJointID jointId = NULL; JL_ASSERT_ARGC_RANGE(1,2); JL_ASSERT_CONSTRUCTING(); JL_DEFINE_CONSTRUCTOR_OBJ; ode::dJointGroupID groupId; if ( JL_ARG_ISDEF(2) ) { JL_ASSERT_ARG_IS_OBJECT(2); JL_ASSERT_INSTANCE( &JL_ARG(2).toObject(), JL_CLASS(JointGroup) ); groupId = (ode::dJointGroupID)JL_GetPrivate(&JL_ARG(2).toObject()); } else { groupId = 0; } ode::dWorldID worldId; JL_CHK( JL_JsvalToWorldID( cx, JL_ARG(1), &worldId) ); jointId = ode::dJointCreatePiston(worldId, groupId); // The joint group ID is 0 to allocate the joint normally. JL_ASSERT( jointId, E_STR(JL_THIS_CLASS_NAME), E_CREATE ); ode::dJointSetData(jointId, obj); ode::dJointSetFeedback(jointId, NULL); JL_SetPrivate(obj, jointId); return true; bad: if ( jointId ) ode::dJointDestroy(jointId); return false; }
/**doc $TOC_MEMBER $INAME $INAME( [ space ] ) TBD **/ DEFINE_CONSTRUCTOR() { ode::dGeomID geomId = NULL; JL_ASSERT_ARGC_RANGE(0, 1); JL_ASSERT_CONSTRUCTING(); JL_DEFINE_CONSTRUCTOR_OBJ; ode::dSpaceID space; if ( JL_ARG_ISDEF(1) ) { // place it in a space ? JL_CHK( JL_JsvalToSpaceID(cx, JL_ARG(1), &space) ); JL_CHK( JL_SetReservedSlot( obj, SLOT_GEOM_SPACEOBJECT, JL_ARG(1)) ); } else { space = 0; } geomId = ode::dCreatePlane(space, 0,0,1,0); // default lengths are 1 JL_ASSERT( geomId, E_STR(JL_THIS_CLASS_NAME), E_CREATE ); JL_CHK( SetupReadMatrix(cx, obj) ); ode::dGeomSetData(geomId, obj); // 'obj' do not need to be rooted because Goem's data is reset to NULL when 'obj' is finalized. JL_SetPrivate(obj, geomId); return true; bad: if ( geomId ) ode::dGeomDestroy(geomId); return false; }
bool ReconstructBody(JSContext *cx, ode::dBodyID bodyId, JSObject **obj) { // (TBD) JSObject** = Conservative Stack Scanning issue ? if (unlikely( bodyId == (ode::dBodyID)0 )) { // bodyId may be null if body is world.env *obj = jl::newObjectWithGivenProto(cx, JL_CLASS(Body), JL_CLASS_PROTOTYPE(cx, Body)); JL_CHK( *obj ); } else { //JL_ASSERT( ode::dBodyGetData(bodyId) == NULL, "Invalid case (object not finalized)." ); JL_ASSERT( ode::dBodyGetData(bodyId) == NULL, E_MODULE, E_INTERNAL, E_SEP, E_STR(JL_CLASS_NAME(Body)), E_STATE, E_INVALID ); *obj = jl::newObjectWithGivenProto(cx, JL_CLASS(Body), JL_CLASS_PROTOTYPE(cx, Body), NULL); JL_CHK( *obj ); // BodyPrivate *bodypv = (BodyPrivate*)jl_malloc(sizeof(BodyPrivate)); // JL_ASSERT_ALLOC( bodypv ); // bodypv->obj = *obj; // ode::dBodySetData(bodyId, bodypv); ode::dBodySetData(bodyId, *obj); } JL_CHK( SetMatrix44GetInterface(cx, *obj, BodyReadMatrix) ); JL_SetPrivate( *obj, bodyId); return true; JL_BAD; }
DEFINE_CONSTRUCTOR() { ode::dBodyID bodyId = NULL; JL_ASSERT_ARGC_MIN(1); JL_ASSERT_CONSTRUCTING(); JL_DEFINE_CONSTRUCTOR_OBJ; ode::dWorldID worldId; JL_CHK( JL_JsvalToWorldID(cx, JL_ARG(1), &worldId) ); // BodyPrivate *bodypv = (BodyPrivate*)jl_malloc(sizeof(BodyPrivate)); // JL_ASSERT_ALLOC( bodypv ); // bodypv->obj bodyId = ode::dBodyCreate(worldId); JL_ASSERT( bodyId != NULL, E_LIB, E_NAME("ODE"), E_SEP, E_STR(JL_THIS_CLASS_NAME), E_CREATE ); JL_CHK( SetMatrix44GetInterface(cx, obj, BodyReadMatrix) ); ode::dBodySetData(bodyId, obj); S_ASSERT( sizeof(bodyId) == sizeof(void*) ); JL_SetPrivate(obj, bodyId); return true; bad: if ( bodyId ) ode::dBodyDestroy(bodyId); return false; }
void jl::PreallocatedObjectPool::Init( void* pBuffer, unsigned nCapacity, unsigned nStride, unsigned nFlags /*= eFlag_Default */ ) { JL_ASSERT( m_pObjectBuffer == NULL ); m_pObjectBuffer = (unsigned char*)pBuffer; m_pFreeListHead = ObjectPool::InitFreeList( m_pObjectBuffer, nCapacity, nStride ); m_nCapacity = nCapacity; m_nStride = nStride; m_nFlags = nFlags; }
/**doc $TOC_MEMBER $INAME $INAME( filename ) Constructs a new inflater or deflater object. $H example {{{ var f = new ZipFile('test.zip'); f.open(ZipFile.CREATE); f.select('file1.txt'); f.write('data1'); f.close(); }}} **/ DEFINE_CONSTRUCTOR() { Private *pv = NULL; JL_DEFINE_ARGS; JL_ASSERT_CONSTRUCTING(); JL_ASSERT_ARGC(1); JL_DEFINE_CONSTRUCTOR_OBJ; //JL_CHK( JL_SetReservedSlot(JL_OBJ, SLOT_FILENAME, JL_ARG(1)) ); JL_CHK( jl::setSlot(cx, JL_OBJ, SLOT_FILENAME, JL_ARG(1)) ); pv = (Private*)jl_calloc(sizeof(Private), 1); JL_ASSERT_ALLOC(pv); pv->uf = NULL; pv->zf = NULL; JL_updateMallocCounter(cx, sizeof(Private)); JL_ASSERT( !pv->uf && !pv->zf ); JL_ASSERT( !pv->inZipOpened ); //JL_CHK( ReserveStreamReadInterface(cx, obj) ); JL_CHK( jl::setStreamReadInterface(cx, JL_OBJ, NativeInterfaceStreamRead) ); JL_SetPrivate(JL_OBJ, pv); return true; bad: if ( pv ) { if ( pv->zf ) zipClose(pv->zf, NULL); if ( pv->uf ) unzClose(pv->uf); jl_free(pv); } return false; }
/* BEGIN RANDOM GENERATION FUNCTIONS */ jlVector4 * generateRandomVectors(int32 numVectors, float32 scalarMin, float32 scalarMax) { JL_ASSERT(numVectors > 0); jlVector4 *vectors = new jlVector4[numVectors]; if (vectors) { jlRandom random; random.init(numVectors); random.seed(jlRandom::DEFAULT_SEED); for (int32 i = 0; i < numVectors; i++) { float32 x = random.randFloat32(scalarMin, scalarMax); float32 y = random.randFloat32(scalarMin, scalarMax); float32 z = random.randFloat32(scalarMin, scalarMax); //float32 w = random.randFloat32(scalarMin, scalarMax); vectors[i].set(x, y, z, 0.0f); } } return vectors; }
bool ModuleInit( JSContext *cx, JS::HandleObject obj ) { JLDisableThreadNotifications(); JL_ASSERT( jl::Host::getJLHost(cx)->checkCompatId( JL_HOST_VERSIONID ), E_MODULE, E_NOTCOMPATIBLE, E_HOST ); // JL_ASSERT( vi == NULL, E_LIB, E_STR("videoinput"), E_INIT ); // "Invalid case: videoInput already initialized'" videoInput::setVerbose(false); videoInput *vi = new videoInput(); JL_ASSERT_ALLOC( vi ); jl::Host::getJLHost(cx)->moduleManager().modulePrivateT<videoInput*>( moduleId() ) = vi; struct ReleaseModule : jl::Callback { jl::HostRuntime &_hostRuntime; videoInput *_vi; ReleaseModule(jl::HostRuntime &hostRuntime, videoInput *vi) : _hostRuntime(hostRuntime), _vi(vi) { } bool operator()( EventType &ev ) { ASSERT( _hostRuntime ); if ( _hostRuntime.skipCleanup() ) return true; if ( _vi != NULL ) delete _vi; return true; } }; jl::HostRuntime &hostRuntime = jl::HostRuntime::getJLRuntime(cx); hostRuntime.addListener(jl::EventId::AFTER_DESTROY_RUNTIME, new ReleaseModule(hostRuntime, vi)); // frees mpv after rt and cx has been destroyed INIT_CLASS( VideoInput ); return true; JL_BAD; }
bool SlotGetPrng(JSContext *cx, JS::HandleObject obj, int *prngIndex, prng_state **prngState) { JS::RootedValue prngVal(cx); JL_CHK( JL_GetReservedSlot( obj, ASYMMETRIC_CIPHER_PRNG_SLOT, &prngVal) ); JL_ASSERT_OBJECT_STATE( prngVal.isObject(), JL_CLASS_NAME(Prng) ); { JS::RootedObject prngObj(cx, &prngVal.toObject()); JL_ASSERT_INSTANCE( prngObj, JL_CLASS(Prng) ); PrngPrivate *prngPrivate; prngPrivate = (PrngPrivate *)JL_GetPrivate(prngObj); JL_ASSERT_OBJECT_STATE( prngPrivate, JL_CLASS_NAME(Prng) ); *prngState = &prngPrivate->state; *prngIndex = find_prng(prngPrivate->prng.name); JL_ASSERT( *prngIndex != -1, E_STR("PRNG"), E_NAME(prngPrivate->prng.name), E_NOTFOUND ); } return true; JL_BAD; }
bool DoStep(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue rval) { sqlite3_stmt *pStmt = (sqlite3_stmt*)JL_GetPrivate(obj); JL_ASSERT_THIS_OBJECT_STATE( pStmt ); DatabasePrivate *dbpv; { JS::RootedValue dbVal(cx); JL_CHK( JL_GetReservedSlot(obj, SLOT_RESULT_DATABASE, &dbVal) ); JL_ASSERT( dbVal.isObject() ); JS::RootedObject dbValObj(cx, &dbVal.toObject()); dbpv = (DatabasePrivate*)JL_GetPrivate(dbValObj); JL_ASSERT_OBJECT_STATE(dbpv, JL_GetClassName(dbValObj)); } sqlite3 *db; db = dbpv->db; ASSERT( db == sqlite3_db_handle(pStmt) ); { // check if bindings are up to date JS::RootedValue bindingUpToDate(cx); JL_CHK( JL_GetReservedSlot(obj, SLOT_RESULT_BINDING_UP_TO_DATE, &bindingUpToDate) ); if ( bindingUpToDate != JSVAL_TRUE ) { JS::RootedValue queryArgument(cx); JS::RootedObject queryArgumentObj(cx); JL_CHK(jl::getSlot(cx, obj, SLOT_RESULT_QUERY_ARGUMENT_OBJECT, &queryArgumentObj)); JL_CHK(SqliteSetupBindings(cx, pStmt, queryArgumentObj, obj)); // ":" use result object. "@" is the object passed to Query() JL_CHK( JL_SetReservedSlot(obj, SLOT_RESULT_BINDING_UP_TO_DATE, JL_TRUE) ); // doc: The sqlite3_bind_*() routines must be called AFTER sqlite3_prepare() or sqlite3_reset() and BEFORE sqlite3_step(). // Bindings are not cleared by the sqlite3_reset() routine. Unbound parameters are interpreted as NULL. } } dbpv->tmpcx = cx; int status; status = sqlite3_step( pStmt ); // The return value will be either SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE. dbpv->tmpcx = NULL; JL_CHK( !JL_IsExceptionPending(cx) ); switch ( status ) { case SQLITE_ROW: // SQLITE_ROW is returned each time a new row of data is ready for processing by the caller rval.setBoolean(true); return true; case SQLITE_DONE: // means that the statement has finished executing successfully. sqlite3_step() should not be called again on this virtual machine without first calling sqlite3_reset() to reset the virtual machine back to its initial state. rval.setBoolean(false); return true; case SQLITE_MISUSE: // doc. means that the this routine was called inappropriately. Perhaps it was called on a virtual machine that had already been finalized or on one that had previously returned SQLITE_ERROR or SQLITE_DONE. // Or it could be the case that a database connection is being used by a different thread than the one it was created it. // doc. If an interface fails with SQLITE_MISUSE, that means the interface was invoked incorrectly by the application. In that case, the error code and message may or may not be set. JL_CHK( SqliteThrowError(cx, db) ); // case SQLITE_ERROR: // case SQLITE_SCHEMA: // (TBD) check for another error (doc. The database schema changed) // JL_CHK( SqliteThrowError(cx, db) ); } // JL_REPORT_ERROR("invalid case (status:%d)", status ); JL_CHK( SqliteThrowError(cx, db) ); JL_BAD; }
/* NORMALIZATION/MATRIX MULTIPLY TEST */ void normalizeVectors(jlVector4 *ptr, int32 n) { JL_ASSERT(ptr != NULL && n > 0); for (int i = 0; i < n; i++) { ptr[i].normalize3(); } }
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CxObj *cxobj = (CxObj*)GetWindowLong(hWnd, GWL_USERDATA); if ( cxobj == NULL ) return DefWindowProc(hWnd, message, wParam, lParam); JSContext *cx = cxobj->cx; JS::RootedObject obj(cx, cxobj->obj); jsval rval; jsval functionVal; LRESULT returnValue = 0; switch (message) { //case WM_COMMAND: //case WM_PAINT case WM_DESTROY: PostQuitMessage(0); return 0; case WM_CHAR: JS_GetProperty(cx, obj, "onchar", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) char c = wParam; jsval argv[] = { STRING_TO_JSVAL(JS_NewStringCopyN(cx, &c, 1)), INT_TO_JSVAL(lParam) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // needed to protect the new string bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_KEYUP: JS_GetProperty(cx, obj, "onkeyup", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL(wParam), INT_TO_JSVAL(lParam) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_KEYDOWN: JS_GetProperty(cx, obj, "onkeydown", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL(wParam), INT_TO_JSVAL(lParam) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_ACTIVATE: JS_GetProperty(cx, obj, "onactivate", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { BOOLEAN_TO_JSVAL(wParam != WA_INACTIVE) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; // case WM_SIZING: case WM_SIZE: JS_GetProperty(cx, obj, "onsize", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL((short)LOWORD(lParam)), INT_TO_JSVAL((short)HIWORD(lParam)) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_MOUSEMOVE: JS_GetProperty(cx, obj, "onmousemove", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL(MAKEPOINTS(lParam).x), INT_TO_JSVAL(MAKEPOINTS(lParam).y), BOOLEAN_TO_JSVAL(wParam & MK_LBUTTON), BOOLEAN_TO_JSVAL(wParam & MK_RBUTTON), BOOLEAN_TO_JSVAL(wParam & MK_MBUTTON) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_MOUSEWHEEL: JS_GetProperty(cx, obj, "onmousewheel", &functionVal); if ( !functionVal.isUndefined() ) { JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL( GET_WHEEL_DELTA_WPARAM(wParam)/WHEEL_DELTA ), BOOLEAN_TO_JSVAL(wParam & MK_LBUTTON), BOOLEAN_TO_JSVAL(wParam & MK_RBUTTON), BOOLEAN_TO_JSVAL(wParam & MK_MBUTTON) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: JS_GetProperty(cx, obj, "onmousedown", &functionVal); if ( !functionVal.isUndefined() ) { // xPos = GET_X_LPARAM(lParam); // yPos = GET_Y_LPARAM(lParam); JL_ASSERT_FUNCTION(functionVal); // (TBD) return value of assert is not compatible with this function (WndProc) jsval argv[] = { INT_TO_JSVAL( message==WM_LBUTTONDOWN ? 1 : message==WM_RBUTTONDOWN ? 2 : message==WM_MBUTTONDOWN ? 3 : 0 ), JSVAL_TRUE }; // BOOLEAN_TO_JSVAL(wParam & MK_LBUTTON), // BOOLEAN_TO_JSVAL(wParam & MK_RBUTTON), // BOOLEAN_TO_JSVAL(wParam & MK_MBUTTON) }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: JS_GetProperty(cx, obj, "onmouseup", &functionVal); if ( !functionVal.isUndefined() ) { // xPos = GET_X_LPARAM(lParam); // yPos = GET_Y_LPARAM(lParam); JL_ASSERT( JS_TypeOfValue( cx, functionVal ) == JSTYPE_FUNCTION, "Need a function." ); jsval argv[] = { INT_TO_JSVAL( message==WM_LBUTTONUP ? 1 : message==WM_RBUTTONUP ? 2 : message==WM_MBUTTONUP ? 3 : 0 ), JSVAL_FALSE }; JSTempValueRooter tvr; JS_PUSH_TEMP_ROOT(cx, COUNTOF(argv), argv, &tvr); // not really needed bool status = JS_CallFunctionValue(cx, obj, functionVal, COUNTOF(argv), argv, &rval); JS_POP_TEMP_ROOT(cx, &tvr); JL_CHK( status ); return 0; } break; //case WM_MOUSELEAVE: // need TrackMouseEvent() ... // JS_GetProperty(cx, obj, "onmouseleave", &functionVal); // if ( !JSVAL_IS_VOID( functionVal ) ) { // JS_CallFunctionValue(cx, obj, functionVal, 0, NULL, &rval); // } // break; } return DefWindowProc(hWnd, message, wParam, lParam); // We do not want to handle this message so pass back to Windows to handle it in a default way }