From 7c3d14fd256832cf147d268408b779b509311539 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 27 Aug 2011 02:44:05 +0000 Subject: [PATCH] support XEmbed, and therefore Chromium on Linux --- direct/src/plugin/p3d_plugin_config.h.pp | 3 ++ direct/src/plugin_npapi/Sources.pp | 2 +- direct/src/plugin_npapi/ppInstance.cxx | 51 ++++++++++++++++++++++-- direct/src/plugin_npapi/ppInstance.h | 2 + direct/src/plugin_npapi/startup.cxx | 37 ++++++++++++----- 5 files changed, 79 insertions(+), 16 deletions(-) diff --git a/direct/src/plugin/p3d_plugin_config.h.pp b/direct/src/plugin/p3d_plugin_config.h.pp index 2deedc8172..93b330cf6d 100644 --- a/direct/src/plugin/p3d_plugin_config.h.pp +++ b/direct/src/plugin/p3d_plugin_config.h.pp @@ -32,4 +32,7 @@ be found. Empty string for the default. */ #$[]define P3D_PLUGIN_P3D_PLUGIN "$[subst \,\\,$[osfilename $[P3D_PLUGIN_P3D_PLUGIN]]]" +/* We need to know whether GTK is enabled for XEmbed. */ +$[cdefine HAVE_GTK] + #end p3d_plugin_config.h diff --git a/direct/src/plugin_npapi/Sources.pp b/direct/src/plugin_npapi/Sources.pp index 2dce19a624..1c41e7b57d 100644 --- a/direct/src/plugin_npapi/Sources.pp +++ b/direct/src/plugin_npapi/Sources.pp @@ -7,7 +7,7 @@ #define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_NPAPI]] #define _MT $[if $[P3D_PLUGIN_MT],_mt] -#define USE_PACKAGES npapi +#define USE_PACKAGES npapi gtk #begin lib_target // By Mozilla convention, on Windows at least, the generated DLL diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 4155c05ca3..7b9d524ef9 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -38,6 +38,12 @@ #include #endif // _WIN32 +#if defined(HAVE_GTK) && defined(HAVE_X11) +#include +#include +#endif // HAVE_GTK + + PPInstance::FileDatas PPInstance::_file_datas; //////////////////////////////////////////////////////////////////// @@ -127,6 +133,7 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode, } } + _use_xembed = false; _got_window = false; _python_window_open = false; #ifdef _WIN32 @@ -946,6 +953,20 @@ get_panda_script_object() { return _script_object; } +//////////////////////////////////////////////////////////////////// +// Function: PPInstance::set_xembed +// Access: Public +// Description: Sets the use_xembed flag, telling the instance what +// kind of window object to expect from NPAPI. If this +// is true, the window object is an XID following the +// XEmbed specification; if false, it is a normal window +// handle. +//////////////////////////////////////////////////////////////////// +void PPInstance:: +set_xembed(bool use_xembed) { + _use_xembed = use_xembed; +} + //////////////////////////////////////////////////////////////////// // Function: PPInstance::p3dobj_to_variant // Access: Public @@ -1811,12 +1832,14 @@ send_window() { // (0, 0), since the window we were given is already placed in the // right spot. #ifdef _WIN32 + assert(!_use_xembed); parent_window._window_handle_type = P3D_WHT_win_hwnd; parent_window._handle._win_hwnd._hwnd = (HWND)(_window.window); x = 0; y = 0; #elif defined(__APPLE__) + assert(!_use_xembed); parent_window._window_handle_type = _window_handle_type; if (_window_handle_type == P3D_WHT_osx_port) { NP_Port *port = (NP_Port *)_window.window; @@ -1830,10 +1853,30 @@ send_window() { } #elif defined(HAVE_X11) - // We make it an 'unsigned long' instead of 'Window' - // to avoid nppanda3d.so getting a dependency on X11. - parent_window._window_handle_type = P3D_WHT_x11_window; - parent_window._handle._x11_window._xwindow = (unsigned long)(_window.window); + if (_use_xembed) { + // If we're using the XEmbed model, we've actually received an + // XID for a GtkSocket. +#ifdef HAVE_GTK + // Create the appropriate GtkPlug. + GtkWidget *plug = gtk_plug_new((GdkNativeWindow)_window.window); + gtk_widget_show(plug); + + // Now just get the X11 Window pointer to pass down to Panda, + // since that's what it will be expecting. (Hmm, it would be + // nice to pass the XID object and use this system in general + // within Panda, but that's for the future, I think.) + nout << "original XID is " << _window.window << ", created X11 window " + << GDK_DRAWABLE_XID(plug->window) << "\n"; + parent_window._window_handle_type = P3D_WHT_x11_window; + parent_window._handle._x11_window._xwindow = (unsigned long)GDK_DRAWABLE_XID(plug->window); +#endif // HAVE_GTK + } else { + // If we're not using XEmbed, this is just a standard X11 Window + // pointer. We make it an 'unsigned long' instead of 'Window' + // to avoid nppanda3d.so getting a dependency on X11. + parent_window._window_handle_type = P3D_WHT_x11_window; + parent_window._handle._x11_window._xwindow = (unsigned long)(_window.window); + } x = 0; y = 0; #endif diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index ef644b0a4e..9361a30f5c 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -63,6 +63,7 @@ public: bool handle_event(void *event); NPObject *get_panda_script_object(); + void set_xembed(bool use_xembed); void p3dobj_to_variant(NPVariant *result, P3D_object *object); P3D_object *variant_to_p3dobj(const NPVariant *variant); @@ -214,6 +215,7 @@ private: typedef vector FileDatas; static FileDatas _file_datas; + bool _use_xembed; bool _got_window; NPWindow _window; #ifdef _WIN32 diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index 134eb89c1d..5ec679293f 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -562,19 +562,34 @@ NPP_GetValue(NPP instance, NPPVariable variable, void *value) { *(NPObject **)value = obj; return NPERR_NO_ERROR; } + } else if (variable == NPPVpluginNeedsXEmbed) { - // We'll say yes if the browser supports it. - // This is necessary to support Chromium. - //NPBool supports_xembed = false; - //NPError err = browser->getvalue(instance, NPNVSupportsXEmbedBool, &supports_xembed); - //if (err != NPERR_NO_ERROR) { - // supports_xembed = false; - //} - // At the moment, setting it to true doesn't work - // at all on Linux. We'll have to fix that before - // we support Chromium, I suppose. - *((NPBool *)value) = false; + // If we have Gtk2 available, we can use it to support the XEmbed + // protocol, which Chromium (at least) requires. + + // In this case, we'll say we can do it, if the browser supports + // it. (Though probably the browser wouldn't be asking if it + // couldn't.) + + NPBool supports_xembed = false; + NPError err = browser->getvalue(instance, NPNVSupportsXEmbedBool, &supports_xembed); + if (err != NPERR_NO_ERROR) { + supports_xembed = false; + } + nout << "browser supports_xembed: " << (bool)supports_xembed << "\n"; +#ifdef HAVE_GTK + bool plugin_supports = true; +#else + bool plugin_supports = false; + supports_xembed = false; +#endif // HAVE_GTK + nout << "plugin supports_xembed: " << plugin_supports << "\n"; + + inst->set_xembed(supports_xembed); + *(NPBool *)value = supports_xembed; + return NPERR_NO_ERROR; + } else { return NP_GetValue(NULL, variable, value); }