/* --- 8< --- 8< --- OffscreenGecko headers --- >8 --- >8 --- */
+/* NOTE: Documentation comments have been omitted. Documentation is
+ available in the OffscreenGecko SDK download. */
/* OffscreenGecko/defs.h */
#define OSGK_CLASSTYPE_REF struct
#include <assert.h>
+#include <stdlib.h>
#define OSGK_ASSERT(x) assert(x)
typedef unsigned int OSGK_GeckoResult;
static int (*osgk_addref) (OSGK_BaseObject* obj);
static int (*osgk_release) (OSGK_BaseObject* obj);
-static OSGK_INLINE int osgk_addref_real (OSGK_BaseObject* obj)
+/*static OSGK_INLINE int osgk_addref_real (OSGK_BaseObject* obj)
{
return osgk_addref (obj);
-}
+}*/
static OSGK_INLINE int osgk_release_real (OSGK_BaseObject* obj)
{
unsigned int apiVer, OSGK_EmbeddingOptions* options,
OSGK_GeckoResult* geckoResult);
-static OSGK_INLINE OSGK_Embedding* osgk_embedding_create (
+/*static OSGK_INLINE OSGK_Embedding* osgk_embedding_create (
OSGK_GeckoResult* geckoResult)
{
return osgk_embedding_create2 (OSGK_API_VERSION, 0, geckoResult);
-}
+}*/
static OSGK_INLINE OSGK_Embedding* osgk_embedding_create_with_options (
OSGK_EmbeddingOptions* options, OSGK_GeckoResult* geckoResult)
static void (*osgk_browser_resize) (OSGK_Browser* browser,
int width, int height);
+static int (*osgk_browser_set_user_data) (OSGK_Browser* browser,
+ unsigned int key, void* data, int overrideData);
+static int (*osgk_browser_get_user_data) (OSGK_Browser* browser,
+ unsigned int key, void** data);
+
+/* OffscreenGecko/string.h */
+OSGK_DERIVEDTYPE(OSGK_String);
+
+static const char* (*osgk_string_get) (OSGK_String* str);
+
+static OSGK_String* (*osgk_string_create) (const char* str);
+
+/* OffscreenGecko/scriptvariant.h */
+
+OSGK_CLASSTYPE_DEF nsISupports;
+
+OSGK_DERIVEDTYPE(OSGK_ScriptVariant);
+
+typedef enum OSGK_ScriptVariantType
+{
+ svtEmpty,
+ svtInt,
+ svtUint,
+ svtFloat,
+ svtDouble,
+ svtBool,
+ svtChar,
+ svtString,
+ svtISupports,
+ svtScriptObject,
+ svtArray
+} OSGK_ScriptVariantType;
+
+/*static OSGK_ScriptVariantType (*osgk_variant_get_type) (
+ OSGK_ScriptVariant* variant);*/
+static OSGK_ScriptVariant* (*osgk_variant_convert) (
+ OSGK_ScriptVariant* variant, OSGK_ScriptVariantType newType);
+
+/*static int (*osgk_variant_get_int) (OSGK_ScriptVariant* variant,
+ int* val);*/
+/*static int (*osgk_variant_get_uint) (OSGK_ScriptVariant* variant,
+ unsigned int* val);*/
+/*static int (*osgk_variant_get_float) (OSGK_ScriptVariant* variant,
+ float* val);*/
+/*static int (*osgk_variant_get_double) (OSGK_ScriptVariant* variant,
+ double* val);*/
+/*static int (*osgk_variant_get_bool) (OSGK_ScriptVariant* variant,
+ int* val);*/
+/*static int (*osgk_variant_get_char) (OSGK_ScriptVariant* variant,
+ unsigned int* val);*/
+// Does not increase ref count
+static int (*osgk_variant_get_string) (OSGK_ScriptVariant* variant,
+ OSGK_String** val);
+/*// Does not increase ref count
+static int (*osgk_variant_get_isupports) (OSGK_ScriptVariant* variant,
+ OSGK_CLASSTYPE_REF nsISupports** val);*/
+/*static int (*osgk_variant_get_script_object) (OSGK_ScriptVariant* variant,
+ void** tag);*/
+/*static int (*osgk_variant_get_array_size) (OSGK_ScriptVariant* variant,
+ size_t* size);*/
+/*static int (*osgk_variant_get_array_item) (OSGK_ScriptVariant* variant,
+ OSGK_ScriptVariant** val);*/
+
+/*static OSGK_ScriptVariant* (*osgk_variant_create_empty) (
+ OSGK_Embedding* embedding);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_int) (
+ OSGK_Embedding* embedding, int val);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_uint) (
+ OSGK_Embedding* embedding, unsigned int val);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_float) (
+ OSGK_Embedding* embedding, float val);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_double) (
+ OSGK_Embedding* embedding, double val);*/
+/*OSGK_ScriptVariant* (*osgk_variant_create_bool) (
+ OSGK_Embedding* embedding, int val);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_char) (
+ OSGK_Embedding* embedding, unsigned int val);*/
+static OSGK_ScriptVariant* (*osgk_variant_create_string) (
+ OSGK_Embedding* embedding, OSGK_String* val);
+/*static OSGK_ScriptVariant* (*osgk_variant_create_isupports) (
+ OSGK_Embedding* embedding, OSGK_CLASSTYPE_REF nsISupports* val);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_script_object) (
+ OSGK_Embedding* embedding, void* tag);*/
+/*static OSGK_ScriptVariant* (*osgk_variant_create_array) (
+ OSGK_Embedding* embedding, size_t numItems, OSGK_ScriptVariant** items);*/
+
+/* OffscreenGecko/scriptobjecttemplate.h */
+
+OSGK_DERIVEDTYPE(OSGK_ScriptObjectTemplate);
+
+typedef enum OSGK_ScriptResult
+{
+ srSuccess = 0,
+ srFailed = (int)0x80004005L /* actually NS_ERROR_FAILURE */
+} OSGK_ScriptResult;
+
+typedef struct OSGK_ScriptObjectCreateParams_s
+{
+ void* createParam;
+ OSGK_Browser* browser;
+} OSGK_ScriptObjectCreateParams;
+
+typedef OSGK_ScriptResult (*OSGK_CreateObjFunc) (
+ OSGK_ScriptObjectCreateParams* params, void** objTag);
+typedef void (*OSGK_DestroyObjFunc) (void* objTag);
+
+static OSGK_ScriptObjectTemplate* (*osgk_sot_create) (
+ OSGK_Embedding* embedding,
+ OSGK_CreateObjFunc createFunc, OSGK_DestroyObjFunc destroyFunc,
+ void* createParam);
+
+typedef OSGK_ScriptVariant* (*OSGK_GetPropertyFunc) (void* objTag,
+ void* propTag);
+typedef OSGK_ScriptResult (*OSGK_SetPropertyFunc) (void* objTag,
+ void* propTag, OSGK_ScriptVariant* val);
+
+/*static int (*osgk_sot_add_property) (
+ OSGK_ScriptObjectTemplate* templ, const char* propName, void* propTag,
+ OSGK_GetPropertyFunc getter, OSGK_SetPropertyFunc setter);*/
+
+typedef OSGK_ScriptResult (*OSGK_FunctionCallFunc) (void* objTag,
+ void* methTag, size_t numParams, OSGK_ScriptVariant** params,
+ OSGK_ScriptVariant** returnVal);
+
+static int (*osgk_sot_add_function) (
+ OSGK_ScriptObjectTemplate* templ, const char* funcName, void* funcTag,
+ OSGK_FunctionCallFunc callFunc);
+
+/*static OSGK_ScriptVariant* (*osgk_sot_instantiate) (
+ OSGK_ScriptObjectTemplate* templ, void** objTag); */
+
+static int (*osgk_sot_register) (
+ OSGK_ScriptObjectTemplate* templ, OSGK_Embedding* embedding,
+ const char* name, unsigned int flags);
+
/* --- >8 --- >8 --- End OffscreenGecko headers --- 8< --- 8< --- */
#include "quakedef.h"
struct clgecko_s {
qboolean active;
char name[ MAX_QPATH + 32 ];
+ int ownerProg;
OSGK_Browser *browser;
int width, height;
rtexture_t *texture;
};
-static clgecko_t cl_geckoinstances[ MAX_GECKO_INSTANCES ];
+#define USERDATAKEY_CL_GECKO_T 0
static dllhandle_t osgk_dll = NULL;
+static clgecko_t cl_geckoinstances[ MAX_GECKO_INSTANCES ];
+
static clgecko_t * cl_gecko_findunusedinstance( void ) {
int i;
for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {
return instance;
}
}
- if( developer.integer > 0 ) {
- Con_Printf( "cl_gecko_findunusedinstance: out of geckos\n" );
- }
+ Con_DPrintf( "cl_gecko_findunusedinstance: out of geckos\n" );
return NULL;
}
int i;
if( !name || !*name || strncmp( name, CLGECKOPREFIX, sizeof( CLGECKOPREFIX ) - 1 ) != 0 ) {
- if( developer.integer > 0 ) {
- Con_Printf( "CL_Gecko_FindBrowser: Bad gecko texture name '%s'!\n", name );
- }
+ Con_DPrintf( "CL_Gecko_FindBrowser: Bad gecko texture name '%s'!\n", name );
return NULL;
}
}
}
- if( developer.integer > 0 ) {
- Con_Printf( "CL_Gecko_FindBrowser: No browser named '%s'!\n", name );
- }
+ Con_DPrintf( "CL_Gecko_FindBrowser: No browser named '%s'!\n", name );
return NULL;
}
static void cl_gecko_updatecallback( rtexture_t *texture, void* callbackData ) {
- clgecko_t *instance = callbackData;
+ clgecko_t *instance = (clgecko_t *) callbackData;
const unsigned char *data;
if( instance->browser ) {
// TODO: OSGK only supports BGRA right now
TIMING_TIMESTATEMENT(data = osgk_browser_lock_data( instance->browser, NULL ));
- R_UpdateTexture( texture, data, 0, 0, instance->width, instance->height );
+ R_UpdateTexture( texture, data, 0, 0, 0, instance->width, instance->height, 1 );
osgk_browser_unlock_data( instance->browser, data );
}
}
static void cl_gecko_linktexture( clgecko_t *instance ) {
// TODO: assert that instance->texture == NULL
instance->texture = R_LoadTexture2D( cl_geckotexturepool, instance->name,
- instance->texWidth, instance->texHeight, NULL, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PERSISTENT, NULL );
+ instance->texWidth, instance->texHeight, NULL, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PERSISTENT, -1, NULL );
R_MakeTextureDynamic( instance->texture, cl_gecko_updatecallback, instance );
CL_LinkDynTexture( instance->name, instance->texture );
}
*pheight = (float)instance->height / instance->texHeight;
}
-#if defined(WIN64)
+static OSGK_ScriptResult dpGlobal_create (OSGK_ScriptObjectCreateParams* params,
+ void** objTag)
+{
+ if (!osgk_browser_get_user_data (params->browser, USERDATAKEY_CL_GECKO_T, objTag))
+ return srFailed;
+ return srSuccess;
+}
+
+static OSGK_ScriptResult dpGlobal_query (void* objTag, void* methTag,
+ size_t numParams,
+ OSGK_ScriptVariant** params,
+ OSGK_ScriptVariant** returnVal)
+{
+ clgecko_t *instance = (clgecko_t *) objTag;
+ OSGK_ScriptVariant* strVal;
+ OSGK_ScriptResult result = srFailed;
+ prvm_prog_t * saveProg;
+
+ /* Can happen when created from console */
+ if (instance->ownerProg < 0) return srFailed;
+
+ /* Require exactly one param, for now */
+ if (numParams != 1) return srFailed;
+
+ strVal = osgk_variant_convert (params[0], svtString);
+ if (strVal == 0) return srFailed;
+
+ saveProg = prog;
+ PRVM_SetProg(instance->ownerProg);
+
+ if (prog->funcoffsets.Gecko_Query)
+ {
+ OSGK_String* paramStr, *resultStr;
+
+ if (!osgk_variant_get_string (strVal, ¶mStr)) return srFailed;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString (instance->name);
+ PRVM_G_INT(OFS_PARM1) = PRVM_SetTempString (osgk_string_get (paramStr));
+ PRVM_ExecuteProgram(prog->funcoffsets.Gecko_Query,"Gecko_Query() required");
+ resultStr = osgk_string_create (PRVM_G_STRING (OFS_RETURN));
+ *returnVal = osgk_variant_create_string (cl_geckoembedding, resultStr);
+ osgk_release (resultStr);
+
+ result = srSuccess;
+ }
+
+ prog = saveProg;
+
+ return result;
+}
+
+#if defined(_WIN64)
# define XULRUNNER_DIR_SUFFIX "win64"
#elif defined(WIN32)
# define XULRUNNER_DIR_SUFFIX "win32"
-#elif defined(DP_ARCH) && defined(DP_MACHINE)
-# define XULRUNNER_DIR_SUFFIX DP_ARCH "-" DP_MACHINE
+#elif defined(DP_OS_STR) && defined(DP_ARCH_STR)
+# define XULRUNNER_DIR_SUFFIX DP_OS_STR "-" DP_ARCH_STR
#endif
-clgecko_t * CL_Gecko_CreateBrowser( const char *name ) {
+static qboolean CL_Gecko_Embedding_Init (void)
+{
+ char profile_path [MAX_OSPATH];
+ OSGK_GeckoResult grc;
+ OSGK_EmbeddingOptions *options;
+ OSGK_ScriptObjectTemplate* dpGlobalTemplate;
+
+ if (!osgk_dll) return false;
+
+ if( cl_geckoembedding != NULL ) return true;
+
+ Con_DPrintf( "CL_Gecko_Embedding_Init: setting up gecko embedding\n" );
+
+ options = osgk_embedding_options_create();
+#ifdef XULRUNNER_DIR_SUFFIX
+ osgk_embedding_options_add_search_path( options, "./xulrunner-" XULRUNNER_DIR_SUFFIX "/" );
+#endif
+ osgk_embedding_options_add_search_path( options, "./xulrunner/" );
+ dpsnprintf (profile_path, sizeof (profile_path), "%s/xulrunner_profile/", fs_gamedir);
+ osgk_embedding_options_set_profile_dir( options, profile_path, 0 );
+ cl_geckoembedding = osgk_embedding_create_with_options( options, &grc );
+ osgk_release( options );
+
+ if( cl_geckoembedding == NULL ) {
+ Con_Printf( "CL_Gecko_Embedding_Init: Couldn't retrieve gecko embedding object (%.8x)!\n", grc );
+ return false;
+ }
+
+ Con_DPrintf( "CL_Gecko_Embedding_Init: Embedding set up correctly\n" );
+
+ dpGlobalTemplate = osgk_sot_create( cl_geckoembedding, dpGlobal_create, NULL, NULL );
+
+ osgk_sot_add_function (dpGlobalTemplate, "query", 0, dpGlobal_query);
+
+ osgk_sot_register (dpGlobalTemplate, cl_geckoembedding, "Darkplaces", 0);
+ osgk_release( dpGlobalTemplate );
+
+ return true;
+}
+
+clgecko_t * CL_Gecko_CreateBrowser( const char *name, int ownerProg ) {
clgecko_t *instance;
- if (!osgk_dll) return NULL;
+ if (!CL_Gecko_Embedding_Init ()) return NULL;
// TODO: verify that we dont use a name twice
instance = cl_gecko_findunusedinstance();
// TODO: assert != NULL
-
- if( cl_geckoembedding == NULL ) {
- char profile_path [MAX_OSPATH];
- OSGK_GeckoResult grc;
- OSGK_EmbeddingOptions *options;
-
- if( developer.integer > 0 ) {
- Con_Printf( "CL_Gecko_CreateBrowser: setting up gecko embedding\n" );
- }
-
- options = osgk_embedding_options_create();
- #ifdef XULRUNNER_DIR_SUFFIX
- osgk_embedding_options_add_search_path( options, "./xulrunner-" XULRUNNER_DIR_SUFFIX "/" );
- #endif
- osgk_embedding_options_add_search_path( options, "./xulrunner/" );
- dpsnprintf (profile_path, sizeof (profile_path), "%s/xulrunner_profile/", fs_gamedir);
- osgk_embedding_options_set_profile_dir( options, profile_path, 0 );
- cl_geckoembedding = osgk_embedding_create_with_options( options, &grc );
- osgk_release( options );
-
- if( cl_geckoembedding == NULL ) {
- Con_Printf( "CL_Gecko_CreateBrowser: Couldn't retrieve gecko embedding object (%.8x)!\n", grc );
- return NULL;
- } else if( developer.integer > 0 ) {
- Con_Printf( "CL_Gecko_CreateBrowser: Embedding set up correctly\n" );
- }
- }
instance->active = true;
strlcpy( instance->name, name, sizeof( instance->name ) );
Con_Printf( "CL_Gecko_CreateBrowser: Browser object creation failed!\n" );
}
// TODO: assert != NULL
+ osgk_browser_set_user_data (instance->browser, USERDATAKEY_CL_GECKO_T,
+ instance, 0);
+ instance->ownerProg = ownerProg;
instance->width = instance->texWidth = DEFAULT_GECKO_SIZE;
instance->height = instance->texHeight = DEFAULT_GECKO_SIZE;
return;
}
- // TODO: use snprintf instead
- sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));
- CL_Gecko_CreateBrowser( name );
+ dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1));
+ CL_Gecko_CreateBrowser( name, -1 );
}
static void cl_gecko_destroy_f( void ) {
return;
}
- // TODO: use snprintf instead
- sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));
+ dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1));
CL_Gecko_DestroyBrowser( CL_Gecko_FindBrowser( name ) );
}
return;
}
- // TODO: use snprintf instead
- sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));
+ dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1));
URI = Cmd_Argv( 2 );
CL_Gecko_NavigateToURI( CL_Gecko_FindBrowser( name ), URI );
}
return;
}
- // TODO: use snprintf instead
- sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));
+ dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1));
instance = CL_Gecko_FindBrowser( name );
if( !instance ) {
Con_Printf( "cl_gecko_injecttext_f: gecko instance '%s' couldn't be found!\n", name );
break;
}
- CL_Gecko_Event_Key( instance, key, CLG_BET_PRESS );
+ CL_Gecko_Event_Key( instance, (keynum_t) key, CLG_BET_PRESS );
}
}
return;
}
- // TODO: use snprintf instead
- sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));
+ dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1));
x = atof( Cmd_Argv( 2 ) );
y = atof( Cmd_Argv( 3 ) );
{"osgk_browser_event_mouse_button", (void **) &osgk_browser_event_mouse_button},
{"osgk_browser_event_mouse_wheel", (void **) &osgk_browser_event_mouse_wheel},
{"osgk_browser_event_key", (void **) &osgk_browser_event_key},
+ {"osgk_browser_set_user_data", (void **) &osgk_browser_set_user_data},
+ {"osgk_browser_get_user_data", (void **) &osgk_browser_get_user_data},
+ {"osgk_sot_create", (void **) &osgk_sot_create},
+ {"osgk_sot_register", (void **) &osgk_sot_register},
+ {"osgk_sot_add_function", (void **) &osgk_sot_add_function},
+ {"osgk_string_get", (void **) &osgk_string_get},
+ {"osgk_string_create", (void **) &osgk_string_create},
+ {"osgk_variant_convert", (void **) &osgk_variant_convert},
+ {"osgk_variant_get_string", (void **) &osgk_variant_get_string},
+ {"osgk_variant_create_string", (void **) &osgk_variant_create_string},
{NULL, NULL}
};
-void CL_Gecko_Init( void )
+qboolean CL_Gecko_OpenLibrary (void)
{
- const char* dllnames [] =
+ const char* dllnames_gecko [] =
{
- #if defined(WIN64)
- "OffscreenGecko64.dll",
- #elif defined(WIN32)
+#if defined(WIN32)
"OffscreenGecko.dll",
- #elif defined(MACOSX)
+#elif defined(MACOSX)
"OffscreenGecko.dylib",
- #else
- "OffscreenGecko.so",
- #endif
+#else
+ "libOffscreenGecko.so",
+#endif
NULL
};
-
- if (!osgk_dll)
- {
- if (! Sys_LoadLibrary (dllnames, &osgk_dll, osgkFuncs))
- {
- Con_Printf ("Could not load OffscreenGecko, Gecko support unavailable\n");
- }
- }
+
+ // Already loaded?
+ if (osgk_dll)
+ return true;
+
+// COMMANDLINEOPTION: Sound: -nogecko disables gecko support (web browser support for menu and computer terminals)
+ if (COM_CheckParm("-nogecko"))
+ return false;
+
+ return Sys_LoadLibrary (dllnames_gecko, &osgk_dll, osgkFuncs);
+}
+
+void CL_Gecko_Init( void )
+{
+ CL_Gecko_OpenLibrary();
Cmd_AddCommand( "gecko_create", cl_gecko_create_f, "Create a gecko browser instance" );
Cmd_AddCommand( "gecko_destroy", cl_gecko_destroy_f, "Destroy a gecko browser instance" );
Cmd_AddCommand( "gecko_injecttext", cl_gecko_injecttext_f, "Injects text into a browser" );
Cmd_AddCommand( "gecko_movecursor", gl_gecko_movecursor_f, "Move the cursor to a certain position" );
- R_RegisterModule( "CL_Gecko", cl_gecko_start, cl_gecko_shutdown, cl_gecko_newmap );
+ R_RegisterModule( "CL_Gecko", cl_gecko_start, cl_gecko_shutdown, cl_gecko_newmap, NULL, NULL );
}
void CL_Gecko_NavigateToURI( clgecko_t *instance, const char *URI ) {
return;
}
- mappedx = x * instance->width;
- mappedy = y * instance->height;
+ mappedx = (int) (x * instance->width);
+ mappedy = (int) (y * instance->height);
osgk_browser_event_mouse_move( instance->browser, mappedx, mappedy );
}