From 7ca831ae0b4cbd60ca9899fc240615d81bf63460 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 3 Nov 2009 22:29:30 +0000 Subject: [PATCH] support builds with WebKit's NPAPI, as well as Mozilla's --- direct/src/plugin/p3dInstance.cxx | 4 +- direct/src/plugin_npapi/nppanda3d_common.h | 18 +++++- direct/src/plugin_npapi/ppBrowserObject.cxx | 4 +- direct/src/plugin_npapi/ppInstance.cxx | 26 +++++++-- direct/src/plugin_npapi/startup.cxx | 65 ++++++++++++++++++--- direct/src/plugin_npapi/startup.h | 4 ++ 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 0714ddbcd2..edb64dd728 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -2533,14 +2533,14 @@ report_package_progress(P3DPackage *package, double progress) { time_t elapsed = time(NULL) - _download_begin; _panda_script_object->set_int_property("downloadElapsedSeconds", elapsed); - sprintf(buffer, "%d:%02d", elapsed / 60, elapsed % 60); + sprintf(buffer, "%d:%02d", (int)(elapsed / 60), (int)(elapsed % 60)); _panda_script_object->set_string_property("downloadElapsedFormatted", buffer); if (progress > 0 && (elapsed > 5 || progress > 0.2)) { time_t total = (time_t)((double)elapsed / progress); time_t remaining = max(total, elapsed) - elapsed; _panda_script_object->set_int_property("downloadRemainingSeconds", remaining); - sprintf(buffer, "%d:%02d", remaining / 60, remaining % 60); + sprintf(buffer, "%d:%02d", (int)(remaining / 60), (int)(remaining % 60)); _panda_script_object->set_string_property("downloadRemainingFormatted", buffer); } } diff --git a/direct/src/plugin_npapi/nppanda3d_common.h b/direct/src/plugin_npapi/nppanda3d_common.h index 58d4390bd7..d87b08c289 100644 --- a/direct/src/plugin_npapi/nppanda3d_common.h +++ b/direct/src/plugin_npapi/nppanda3d_common.h @@ -66,10 +66,26 @@ extern string global_root_dir; #endif // _WIN32, __APPLE__ #include "npapi.h" -#include "npupp.h" +#if NP_VERSION_MAJOR == 0 && NP_VERSION_MINOR <= 19 + #include "npupp.h" +#else + // Somewhere between version 0.19 and 0.22, Mozilla renamed npupp.h to + // npfunctions.h. + #include "npfunctions.h" +#endif #include "load_plugin.h" +// Mozilla's version of NPAPI has these names lowercase. WebKit's +// version has them uppercase. What a mess. We have to define a +// duplicate of the structure to allow us to reference them +// consistently. +struct UC_NPString { + const NPUTF8 *UTF8Characters; + uint32_t UTF8Length; +}; + + // If we are building with a version of Gecko that supports the // asynchronous callback function, we should use it--it's just so // handy. diff --git a/direct/src/plugin_npapi/ppBrowserObject.cxx b/direct/src/plugin_npapi/ppBrowserObject.cxx index 1b4f623ad1..597f9befb1 100644 --- a/direct/src/plugin_npapi/ppBrowserObject.cxx +++ b/direct/src/plugin_npapi/ppBrowserObject.cxx @@ -230,9 +230,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const { //////////////////////////////////////////////////////////////////// P3D_object *PPBrowserObject:: eval(const string &expression) const { - NPString npexpr; - npexpr.utf8characters = expression.c_str(); - npexpr.utf8length = expression.length(); + NPString npexpr = { expression.c_str(), expression.length() }; NPVariant result; if (!browser->evaluate(_instance->get_npp_instance(), _npobj, diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 53f46bdb88..869590fbb7 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -138,6 +138,8 @@ begin() { PPDownloadRequest *req = new PPDownloadRequest(PPDownloadRequest::RT_contents_file); start_download(url, req); } + + handle_request_loop(); } //////////////////////////////////////////////////////////////////// @@ -740,7 +742,8 @@ variant_to_p3dobj(const NPVariant *variant) { return P3D_new_float_object(NPVARIANT_TO_DOUBLE(*variant)); } else if (NPVARIANT_IS_STRING(*variant)) { NPString str = NPVARIANT_TO_STRING(*variant); - return P3D_new_string_object(str.utf8characters, str.utf8length); + const UC_NPString &uc_str = *(UC_NPString *)(&str); + return P3D_new_string_object(uc_str.UTF8Characters, uc_str.UTF8Length); } else if (NPVARIANT_IS_OBJECT(*variant)) { NPObject *object = NPVARIANT_TO_OBJECT(*variant); if (object->_class == &PPPandaObject::_object_class) { @@ -890,7 +893,10 @@ request_ready(P3D_instance *instance) { // Since we are running at least Gecko 1.9, and we have this very // useful function, let's use it to ask the browser to call us back // in the main thread. - browser->pluginthreadasynccall(inst->_npp_instance, browser_sync_callback, NULL); + // nout << "async: " << (void *)browser->pluginthreadasynccall << "\n"; + if (browser->pluginthreadasynccall != 0) { + browser->pluginthreadasynccall(inst->_npp_instance, browser_sync_callback, NULL); + } #else // HAS_PLUGIN_THREAD_ASYNC_CALL // If we're using an older version of Gecko, we have to do this some @@ -1245,7 +1251,8 @@ create_instance() { 0, NULL, this); if (_p3d_inst != NULL) { - // Now get the browser's window object, to pass to the plugin. + // Now get the browser's toplevel DOM object (called the "window" + // object in JavaScript), to pass to the plugin. NPObject *window_object = NULL; if (browser->getvalue(_npp_instance, NPNVWindowNPObject, &window_object) == NPERR_NO_ERROR) { @@ -1298,6 +1305,11 @@ send_window() { #elif defined(__APPLE__) NP_Port *port = (NP_Port *)_window.window; parent_window._port = port->port; + /* + NP_CGContext *context = (NP_CGContext *)_window.window; + parent_window._context = context->context; + parent_window._window = (WindowRef)context->window; + */ #elif defined(HAVE_X11) // We make it an 'unsigned long' instead of 'Window' @@ -1321,6 +1333,11 @@ send_window() { #elif defined(__APPLE__) NP_Port *port = (NP_Port *)_window.window; parent_window._port = port->port; + /* + NP_CGContext *context = (NP_CGContext *)_window.window; + parent_window._context = context->context; + parent_window._window = (WindowRef)context->window; + */ #elif defined(HAVE_X11) parent_window._xwindow = 0; @@ -1428,7 +1445,8 @@ output_np_variant(ostream &out, const NPVariant &result) { out << "double " << NPVARIANT_TO_DOUBLE(result); } else if (NPVARIANT_IS_STRING(result)) { NPString str = NPVARIANT_TO_STRING(result); - out << "string " << string(str.utf8characters, str.utf8length); + const UC_NPString &uc_str = *(UC_NPString *)(&str); + out << "string " << string(uc_str.UTF8Characters, uc_str.UTF8Length); } else if (NPVARIANT_IS_OBJECT(result)) { NPObject *child = NPVARIANT_TO_OBJECT(result); out << "object " << child; diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index 9028b18169..6ba0eab95a 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -118,9 +118,11 @@ NP_GetValue(void*, NPPVariable variable, void* value) { case NPPVpluginDescriptionString: *(const char **)value = "Runs 3-D games and interactive applets"; break; + /* case NPPVpluginNeedsXEmbed: - *((PRBool *)value) = PR_FALSE; + *((NPBool *)value) = false; break; + */ default: nout << "Ignoring GetValue request " << variable << "\n"; return NPERR_INVALID_PARAM; @@ -172,13 +174,16 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs, int expected_major = NP_VERSION_MAJOR; int expected_minor = NP_VERSION_MINOR; - nout << "Expected version " << expected_major << "." << expected_minor - << "\n"; - if (browser_major < expected_major || - (browser_major == expected_major && browser_minor < expected_minor)) { + nout << "Plugin compiled with version " + << expected_major << "." << expected_minor << "\n"; + +#ifdef HAS_PLUGIN_THREAD_ASYNC_CALL + // We expect to find at least version NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL. + if (browser_major == 0 && browser_minor < NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) { nout << "Cannot run: unsupported version of NPAPI detected.\n"; return NPERR_GENERIC_ERROR; } +#endif // Seed the lame random number generator in rand(); we use it to // select a mirror for downloading. @@ -200,8 +205,21 @@ NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) { // open_logfile() also assigns global_root_dir. open_logfile(); nout << "NP_GetEntryPoints, pluginFuncs = " << pluginFuncs << "\n"; - pluginFuncs->version = 11; - pluginFuncs->size = sizeof(pluginFuncs); + if (pluginFuncs->size == 0) { + pluginFuncs->size = sizeof(*pluginFuncs); + } + if (pluginFuncs->size < sizeof(*pluginFuncs)) { + nout << "Invalid NPPPluginFuncs size\n"; + return NPERR_INVALID_FUNCTABLE_ERROR; + } + + // Not entirely sure what version number we should send back here. + // Sending the verion number of the NPAPI library we're compiled + // against doesn't seem 100% right, because there's no reason to + // think that *this* code knows about all of the functions provided + // by the particular library version it's compiled against. + pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + pluginFuncs->newp = NPP_New; pluginFuncs->destroy = NPP_Destroy; pluginFuncs->setwindow = NPP_SetWindow; @@ -209,7 +227,16 @@ NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) { pluginFuncs->destroystream = NPP_DestroyStream; pluginFuncs->asfile = NPP_StreamAsFile; pluginFuncs->writeready = NPP_WriteReady; - pluginFuncs->write = NPP_Write; + + // WebKit's NPAPI defines the wrong prototype for this type, so we + // have to cast it. But the casting typename isn't consistent + // between WebKit and Mozilla's NPAPI headers. +#ifdef NewNPP_WriteProc + pluginFuncs->write = NewNPP_WriteProc(NPP_Write); +#else + pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; +#endif + pluginFuncs->print = NPP_Print; pluginFuncs->event = NPP_HandleEvent; pluginFuncs->urlnotify = NPP_URLNotify; @@ -246,6 +273,28 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) { nout << "new instance " << instance << "\n"; + /* +#ifdef __APPLE__ + // We have to request the "core graphics" drawing model to be + // compatible with Snow Leopard. + NPBool supportsCoreGraphics = false; + NPError err = browser->getvalue(instance, + NPNVsupportsCoreGraphicsBool, + &supportsCoreGraphics); + if (err != NPERR_NO_ERROR || !supportsCoreGraphics) { + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } + + // Set the drawing model + err = browser->setvalue(instance, + (NPPVariable)NPNVpluginDrawingModel, + (void *)NPDrawingModelCoreGraphics); + if (err != NPERR_NO_ERROR) { + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } +#endif + */ + PPInstance *inst = new PPInstance(pluginType, instance, mode, argc, argn, argv, saved); instance->pdata = inst; diff --git a/direct/src/plugin_npapi/startup.h b/direct/src/plugin_npapi/startup.h index 60c1bbfdaa..2980a3d18e 100644 --- a/direct/src/plugin_npapi/startup.h +++ b/direct/src/plugin_npapi/startup.h @@ -17,6 +17,10 @@ #include "nppanda3d_common.h" +#ifndef OSCALL +#define OSCALL +#endif + extern "C" { #ifdef _WIN32 NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs);