]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_gecko.c
added prvm_offsets.h which centralizes field/global/function lookups for
[xonotic/darkplaces.git] / cl_gecko.c
index 133def8b9446b8f4bd5e721325f473a02190666e..e66482d68730e060e31d3ca90098c4f062ca1c0f 100644 (file)
@@ -1,4 +1,6 @@
 /* --- 8< --- 8< ---   OffscreenGecko headers   --- >8 --- >8 --- */
+/* NOTE: Documentation comments have been omitted. Documentation is
+   available in the OffscreenGecko SDK download. */
 
 /* OffscreenGecko/defs.h */
 
@@ -6,6 +8,7 @@
 #define OSGK_CLASSTYPE_REF     struct
 
 #include <assert.h>
+#include <stdlib.h>
 #define OSGK_ASSERT(x) assert(x)
 
 typedef unsigned int OSGK_GeckoResult;
@@ -34,10 +37,10 @@ typedef struct OSGK_BaseObject_s OSGK_BaseObject;
 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)
 {
@@ -68,11 +71,11 @@ static OSGK_Embedding* (*osgk_embedding_create2) (
   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)
@@ -229,6 +232,141 @@ typedef enum OSGK_AntiAliasType
 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"
@@ -244,6 +382,7 @@ static OSGK_Embedding *cl_geckoembedding;
 struct clgecko_s {
        qboolean active;
        char name[ MAX_QPATH + 32 ];
+       int ownerProg;
 
        OSGK_Browser *browser;
        int width, height;
@@ -252,10 +391,12 @@ struct clgecko_s {
        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++ ) {
@@ -264,9 +405,7 @@ static clgecko_t * cl_gecko_findunusedinstance( void ) {
                        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;
 }
 
@@ -274,9 +413,7 @@ clgecko_t * CL_Gecko_FindBrowser( const char *name ) {
        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;
        }
 
@@ -287,20 +424,18 @@ clgecko_t * CL_Gecko_FindBrowser( const char *name ) {
                }
        }
 
-       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 );
        }
 }
@@ -308,7 +443,7 @@ static void cl_gecko_updatecallback( rtexture_t *texture, void* callbackData ) {
 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 );
 }
@@ -360,49 +495,112 @@ void CL_Gecko_GetTextureExtent( clgecko_t *instance, float* pwidth, float* pheig
        *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 (PRVM_clientfunction(Gecko_Query))
+  {
+    OSGK_String* paramStr, *resultStr;
+
+    if (!osgk_variant_get_string (strVal, &paramStr)) return srFailed;
+        PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString (instance->name);
+        PRVM_G_INT(OFS_PARM1) = PRVM_SetTempString (osgk_string_get (paramStr));
+    PRVM_ExecuteProgram(PRVM_clientfunction(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 ) );
@@ -411,6 +609,9 @@ clgecko_t * CL_Gecko_CreateBrowser( const char *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;
@@ -505,9 +706,8 @@ static void cl_gecko_create_f( void ) {
                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 ) {
@@ -519,8 +719,7 @@ 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 ) );
 }
 
@@ -534,8 +733,7 @@ static void cl_gecko_navigate_f( void ) {
                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 );
 }
@@ -552,8 +750,7 @@ static void cl_gecko_injecttext_f( void ) {
                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 );
@@ -582,7 +779,7 @@ static void cl_gecko_injecttext_f( void ) {
                                break;
                }
 
-               CL_Gecko_Event_Key( instance, key, CLG_BET_PRESS );
+               CL_Gecko_Event_Key( instance, (keynum_t) key, CLG_BET_PRESS );
        }
 }
 
@@ -596,8 +793,7 @@ static void gl_gecko_movecursor_f( void ) {
                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 ) );
 
@@ -625,32 +821,47 @@ static const dllfunction_t osgkFuncs[] =
        {"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" );
@@ -658,7 +869,7 @@ void CL_Gecko_Init( void )
        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 ) {
@@ -679,8 +890,8 @@ void CL_Gecko_Event_CursorMove( clgecko_t *instance, float x, float y ) {
                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 );
 }