diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index dbb30259d2..20f0430ae3 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -6,6 +6,8 @@ #define USE_PACKAGES tinyxml openssl zlib jpeg x11 #define TARGET p3d_plugin #define LIB_PREFIX + + #define OTHER_LIBS subprocbuffer // We need this because we don't // include dtool_config.h. diff --git a/direct/src/plugin/handleStream.I b/direct/src/plugin/handleStream.I index 5e26f288e9..37b00c4bc1 100644 --- a/direct/src/plugin/handleStream.I +++ b/direct/src/plugin/handleStream.I @@ -39,7 +39,7 @@ inline HandleStream:: // output. //////////////////////////////////////////////////////////////////// inline void HandleStream:: -open_read(Handle handle) { +open_read(FHandle handle) { clear((ios::iostate)0); _buf.open_read(handle); if (!_buf.is_open_read()) { @@ -55,7 +55,7 @@ open_read(Handle handle) { // output. //////////////////////////////////////////////////////////////////// inline void HandleStream:: -open_write(Handle handle) { +open_write(FHandle handle) { clear((ios::iostate)0); _buf.open_write(handle); if (!_buf.is_open_write()) { diff --git a/direct/src/plugin/handleStream.h b/direct/src/plugin/handleStream.h index 5eafcb11a4..080e82719a 100644 --- a/direct/src/plugin/handleStream.h +++ b/direct/src/plugin/handleStream.h @@ -29,8 +29,8 @@ public: inline HandleStream(); inline ~HandleStream(); - inline void open_read(Handle handle); - inline void open_write(Handle handle); + inline void open_read(FHandle handle); + inline void open_write(FHandle handle); inline void close(); private: diff --git a/direct/src/plugin/handleStreamBuf.cxx b/direct/src/plugin/handleStreamBuf.cxx index deffd2a98b..7761bfa71b 100644 --- a/direct/src/plugin/handleStreamBuf.cxx +++ b/direct/src/plugin/handleStreamBuf.cxx @@ -69,7 +69,7 @@ HandleStreamBuf:: // output. //////////////////////////////////////////////////////////////////// void HandleStreamBuf:: -open_read(Handle handle) { +open_read(FHandle handle) { close(); _handle = handle; @@ -84,7 +84,7 @@ open_read(Handle handle) { // output. //////////////////////////////////////////////////////////////////// void HandleStreamBuf:: -open_write(Handle handle) { +open_write(FHandle handle) { close(); _handle = handle; diff --git a/direct/src/plugin/handleStreamBuf.h b/direct/src/plugin/handleStreamBuf.h index f5245467fa..6c2df240ff 100644 --- a/direct/src/plugin/handleStreamBuf.h +++ b/direct/src/plugin/handleStreamBuf.h @@ -17,10 +17,10 @@ #ifdef _WIN32 #include -typedef HANDLE Handle; +typedef HANDLE FHandle; #else // On POSIX, we use a file descriptor as a "handle". -typedef int Handle; +typedef int FHandle; #endif #include @@ -37,8 +37,8 @@ public: HandleStreamBuf(); virtual ~HandleStreamBuf(); - void open_read(Handle handle); - void open_write(Handle handle); + void open_read(FHandle handle); + void open_write(FHandle handle); bool is_open_read() const; bool is_open_write() const; void close(); @@ -56,7 +56,7 @@ private: bool _is_open_read; bool _is_open_write; - Handle _handle; + FHandle _handle; char *_buffer; }; diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 82ea7851c0..8d75310020 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -69,6 +69,7 @@ P3D_instance_get_request_func *P3D_instance_get_request; P3D_check_request_func *P3D_check_request; P3D_request_finish_func *P3D_request_finish; P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream; +P3D_instance_handle_event_func *P3D_instance_handle_event; #ifdef _WIN32 static HMODULE module = NULL; @@ -206,6 +207,7 @@ load_plugin(const string &p3d_plugin_filename) { P3D_check_request = (P3D_check_request_func *)get_func(module, "P3D_check_request"); P3D_request_finish = (P3D_request_finish_func *)get_func(module, "P3D_request_finish"); P3D_instance_feed_url_stream = (P3D_instance_feed_url_stream_func *)get_func(module, "P3D_instance_feed_url_stream"); + P3D_instance_handle_event = (P3D_instance_handle_event_func *)get_func(module, "P3D_instance_handle_event"); #undef get_func @@ -244,7 +246,8 @@ load_plugin(const string &p3d_plugin_filename) { P3D_instance_get_request == NULL || P3D_check_request == NULL || P3D_request_finish == NULL || - P3D_instance_feed_url_stream == NULL) { + P3D_instance_feed_url_stream == NULL || + P3D_instance_handle_event == NULL) { cerr << "Some function pointers not found:" @@ -283,6 +286,7 @@ load_plugin(const string &p3d_plugin_filename) { << "\nP3D_check_request = " << P3D_check_request << "\nP3D_request_finish = " << P3D_request_finish << "\nP3D_instance_feed_url_stream = " << P3D_instance_feed_url_stream + << "\nP3D_instance_handle_event = " << P3D_instance_handle_event << "\n"; return false; } @@ -376,6 +380,7 @@ unload_dso() { P3D_check_request = NULL; P3D_request_finish = NULL; P3D_instance_feed_url_stream = NULL; + P3D_instance_handle_event = NULL; plugin_loaded = false; } diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index b8a55a21aa..4edf19ecd7 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -55,6 +55,7 @@ extern P3D_instance_get_request_func *P3D_instance_get_request; extern P3D_check_request_func *P3D_check_request; extern P3D_request_finish_func *P3D_request_finish; extern P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream; +extern P3D_instance_handle_event_func *P3D_instance_handle_event; string get_plugin_basename(); bool load_plugin(const string &p3d_plugin_filename); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 54d751a411..eca7e98bcb 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -27,15 +27,17 @@ #include #include +#ifdef __APPLE__ +#include +#endif // __APPLE__ + #ifdef _WIN32 typedef P3DWinSplashWindow SplashWindowType; -#else -#ifdef HAVE_X11 +#elif defined(HAVE_X11) typedef P3DX11SplashWindow SplashWindowType; #else typedef P3DSplashWindow SplashWindowType; #endif -#endif //////////////////////////////////////////////////////////////////// // Function: P3DInstance::Constructor @@ -63,6 +65,13 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) : _instance_window_opened = false; _requested_stop = false; +#ifdef __APPLE__ + _shared_fd = -1; + _shared_mmap_size = 0; + _swbuffer = NULL; + _reversed_buffer = NULL; +#endif // __APPLE__ + // Set some initial properties. _panda_script_object->set_float_property("downloadProgress", 0.0); } @@ -95,6 +104,19 @@ P3DInstance:: _splash_window = NULL; } +#ifdef __APPLE__ + if (_swbuffer != NULL) { + SubprocessWindowBuffer::destroy_buffer(_shared_fd, _shared_mmap_size, + _shared_filename, _swbuffer); + _swbuffer = NULL; + } + + if (_reversed_buffer != NULL) { + delete[] _reversed_buffer; + _reversed_buffer = NULL; + } +#endif + DESTROY_LOCK(_request_lock); // TODO: empty _raw_requests and _baked_requests queues, and @@ -184,6 +206,24 @@ set_wparams(const P3DWindowParams &wparams) { xcommand->SetAttribute("cmd", "setup_window"); xcommand->SetAttribute("instance_id", get_instance_id()); TiXmlElement *xwparams = _wparams.make_xml(); + +#ifdef __APPLE__ + // On Mac, we have to communicate the results of the rendering + // back via shared memory, instead of directly parenting windows + // to the browser. Set up this mechanism. + int x_size = _wparams.get_win_width(); + int y_size = _wparams.get_win_height(); + nout << "size = " << x_size << " * " << y_size << "\n" << flush; + if (_shared_fd == -1 && x_size != 0 && y_size != 0) { + _swbuffer = SubprocessWindowBuffer::new_buffer + (_shared_fd, _shared_mmap_size, _shared_filename, x_size, y_size); + if (_swbuffer != NULL) { + _reversed_buffer = new char[_swbuffer->get_framebuffer_size()]; + } + + xwparams->SetAttribute("subprocess_window", _shared_filename); + } +#endif // __APPLE__ doc->LinkEndChild(decl); doc->LinkEndChild(xcommand); @@ -425,6 +465,85 @@ feed_url_stream(int unique_id, return download_ok; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::handle_event +// Access: Public +// Description: Responds to the os-generated window event. +//////////////////////////////////////////////////////////////////// +void P3DInstance:: +handle_event(P3D_event_data event) { +#ifdef _WIN32 + // This function is not used in Win32 and does nothing. + +#elif defined(__APPLE__) + EventRecord *er = event._event; + + switch (er->what) { + case nullEvent: + break; + + case mouseDown: + case mouseUp: + { + Point pt = er->where; + GlobalToLocal(&pt); + P3D_window_handle window = _wparams.get_parent_window(); + cerr << "mouse " << pt.h << " " << pt.v << "\n"; + if (_swbuffer != NULL) { + SubprocessWindowBuffer::Event swb_event; + swb_event._up = (er->what == mouseUp); + swb_event._x = pt.h; + swb_event._y = pt.v; + _swbuffer->add_event(swb_event); + } + } + break; + + case keyDown: + case keyUp: + case autoKey: + cerr << "keycode: " << (er->message & 0xffff) << "\n"; + break; + + case updateEvt: + paint_window(); + break; + + case activateEvt: + cerr << "activate window: " << er->message << "\n"; + break; + + case diskEvt: + break; + + case osEvt: + if ((er->message & 0xf0000000) == suspendResumeMessage) { + if (er->message & 1) { + cerr << "suspend\n"; + } else { + cerr << "resume\n"; + } + } else if ((er->message & 0xf0000000) == mouseMovedMessage) { + cerr << "mouse moved\n"; + } else { + cerr << "unhandled osEvt: " << hex << er->message << dec << "\n"; + } + break; + + case kHighLevelEvent: + cerr << "high level: " << er->message << "\n"; + break; + + default: + cerr << "unhandled event: " << er->what << ", " << er->message << "\n"; + break; + } + +#elif defined(HAVE_X11) + +#endif +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstance::add_package // Access: Public @@ -811,6 +930,81 @@ install_progress(P3DPackage *package, double progress) { _panda_script_object->set_float_property("downloadProgress", progress); } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::paint_window +// Access: Private +// Description: Actually paints the rendered image to the browser +// window. This is only implemented (and needed) for +// OSX, where the child process isn't allowed to do it +// directly. +//////////////////////////////////////////////////////////////////// +void P3DInstance:: +paint_window() { +#ifdef __APPLE__ + if (_swbuffer == NULL) { + nout << "no _swbuffer\n"; + return; + } + + QDErr err; + + // blit rendered framebuffer into window backing store + int x_size = min(_wparams.get_win_width(), _swbuffer->get_x_size()); + int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size()); + Rect src_rect = {0, 0, y_size, x_size}; + Rect ddrc_rect = {0, 0, y_size, x_size}; + + size_t rowsize = _swbuffer->get_row_size(); + + if (_swbuffer->ready_for_read()) { + // Copy the new framebuffer image from the child process. + const void *framebuffer = _swbuffer->open_read_framebuffer(); + + // We have to reverse the image vertically first (different + // conventions between Panda and Mac). + for (int yi = 0; yi < y_size; ++yi) { + memcpy(_reversed_buffer + (y_size - 1 - yi) * rowsize, + (char *)framebuffer + yi * rowsize, + rowsize); + } + + _swbuffer->close_read_framebuffer(); + + } else { + // No frame ready. Just re-paint the frame we had saved last + // time. + } + + // create a GWorld containing our image + GWorldPtr pGWorld; + err = NewGWorldFromPtr(&pGWorld, k32BGRAPixelFormat, &src_rect, 0, 0, 0, + _reversed_buffer, rowsize); + if (err != noErr) { + nout << " error in NewGWorldFromPtr, called from paint_window()\n"; + return; + } + + GrafPtr out_port = _wparams.get_parent_window()._port; + GrafPtr portSave = NULL; + Boolean portChanged = QDSwapPort(out_port, &portSave); + + // Make sure the clipping rectangle isn't in the way. Is there a + // better way to eliminate the cliprect from consideration? + Rect r = { 0, 0, 0x7fff, 0x7fff }; + ClipRect(&r); + + CopyBits(GetPortBitMapForCopyBits(pGWorld), + GetPortBitMapForCopyBits(out_port), + &src_rect, &ddrc_rect, srcCopy, 0); + + if (portChanged) { + QDSwapPort(portSave, NULL); + } + + DisposeGWorld(pGWorld); +#endif // __APPLE__ +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstance::SplashDownload::Constructor // Access: Public diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index 912e8e0a49..c3598dc9ca 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -22,6 +22,10 @@ #include "p3dReferenceCount.h" #include "get_tinyxml.h" +#ifdef __APPLE__ +#include "subprocessWindowBuffer.h" +#endif + #include #include @@ -65,6 +69,8 @@ public: const unsigned char *this_data, size_t this_data_size); + void handle_event(P3D_event_data event); + inline int get_instance_id() const; inline const string &get_session_key() const; inline const string &get_python_version() const; @@ -101,6 +107,8 @@ private: void make_splash_window(); void install_progress(P3DPackage *package, double progress); + void paint_window(); + P3D_request_ready_func *_func; P3D_object *_browser_script_object; P3DToplevelObject *_panda_script_object; @@ -118,6 +126,17 @@ private: // Not ref-counted: session is the parent. P3DSession *_session; +#ifdef __APPLE__ + // On OSX, we have to get a copy of the framebuffer data back from + // the child process, and draw it to the window, here in the parent + // process. Crazy! + int _shared_fd; + size_t _shared_mmap_size; + string _shared_filename; + SubprocessWindowBuffer *_swbuffer; + char *_reversed_buffer; +#endif __APPLE__ + P3DSplashWindow *_splash_window; bool _instance_window_opened; diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 828dff5d81..efc6370d80 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -889,27 +889,37 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) { xwparams->Attribute("win_height", &win_height); long parent_window_handle = 0; + const char *subprocess_window = ""; #ifdef _WIN32 int hwnd; if (xwparams->Attribute("parent_hwnd", &hwnd)) { parent_window_handle = (long)hwnd; } -#endif -#ifdef HAVE_X11 + +#elif __APPLE__ + // On Mac, we don't parent windows directly to the browser; instead, + // we have to go through this subprocess-window nonsense. + + subprocess_window = xwparams->Attribute("subprocess_window"); + if (subprocess_window == NULL) { + subprocess_window = ""; + } + +#elif defined(HAVE_X11) // Bad! Casting to int loses precision. int xwindow; if (xwparams->Attribute("parent_xwindow", &xwindow)) { - parent_window_handle = (unsigned long)xwindow; + parent_window_handle = (long)xwindow; } #endif // TODO: direct this into the particular instance. This will // require a specialized ShowBase replacement. PyObject *result = PyObject_CallMethod - (_runner, (char *)"setupWindow", (char *)"siiiii", window_type.c_str(), + (_runner, (char *)"setupWindow", (char *)"siiiiis", window_type.c_str(), win_x, win_y, win_width, win_height, - parent_window_handle); + parent_window_handle, subprocess_window); if (result == NULL) { PyErr_Print(); } diff --git a/direct/src/plugin/p3dWindowParams.cxx b/direct/src/plugin/p3dWindowParams.cxx index 962cc71e79..51c1d18b69 100644 --- a/direct/src/plugin/p3dWindowParams.cxx +++ b/direct/src/plugin/p3dWindowParams.cxx @@ -79,8 +79,11 @@ make_xml() { xwparams->SetAttribute("win_height", _win_height); #ifdef _WIN32 xwparams->SetAttribute("parent_hwnd", (int)_parent_window._hwnd); -#endif -#ifdef HAVE_X11 + +#elif defined(__APPLE__) + // The subprocess_window setting is applied by the caller. + +#elif defined(HAVE_X11) xwparams->SetAttribute("parent_xwindow", (unsigned long)_parent_window._xwindow); #endif break; diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 2e4b01dc28..269a88b5f3 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -406,3 +406,11 @@ P3D_instance_feed_url_stream(P3D_instance *instance, int unique_id, RELEASE_LOCK(_api_lock); return result; } + +void +P3D_instance_handle_event(P3D_instance *instance, P3D_event_data event) { + assert(P3DInstanceManager::get_global_ptr()->is_initialized()); + ACQUIRE_LOCK(_api_lock); + ((P3DInstance *)instance)->handle_event(event); + RELEASE_LOCK(_api_lock); +} diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 398ac4eb41..906877364b 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -57,6 +57,10 @@ #endif /* _WIN32 */ +#ifdef __APPLE__ +#include +#endif /* __APPLE__ */ + #ifdef __cplusplus extern "C" { #endif @@ -130,14 +134,14 @@ typedef struct { typedef struct { #ifdef _WIN32 HWND _hwnd; -#endif -#ifdef HAVE_X11 + +#elif defined(__APPLE__) + GrafPtr _port; + +#elif defined(HAVE_X11) unsigned long _xwindow; void *_xdisplay; #endif -#ifdef __APPLE__ - void *_nswindow; -#endif } P3D_window_handle; /* This enum lists the different kinds of window types that may be @@ -781,6 +785,29 @@ P3D_instance_feed_url_stream_func(P3D_instance *instance, int unique_id, const void *this_data, size_t this_data_size); +/* This structure abstracts out the event pointer data types for the + different platforms, as passed to P3D_instance_handle_event(), + below. */ +typedef struct { +#ifdef _WIN32 + // Not used for Win32. + +#elif defined(__APPLE__) + EventRecord *_event; + +#elif defined(HAVE_X11) + // XEvent *_event; ? +#endif +} P3D_event_data; + +/* Use this function to supply a new os-specific window event to the + plugin. This is presently used only on OSX, where the window + events are needed for proper plugin handling; and possibly also on + X11. On Windows, window events are handled natively by the plugin. +*/ +typedef void +P3D_instance_handle_event_func(P3D_instance *instance, P3D_event_data event); + #ifdef P3D_FUNCTION_PROTOTYPES /* Define all of the actual prototypes for the above functions. */ @@ -820,6 +847,7 @@ EXPCL_P3D_PLUGIN P3D_instance_get_request_func P3D_instance_get_request; EXPCL_P3D_PLUGIN P3D_check_request_func P3D_check_request; EXPCL_P3D_PLUGIN P3D_request_finish_func P3D_request_finish; EXPCL_P3D_PLUGIN P3D_instance_feed_url_stream_func P3D_instance_feed_url_stream; +EXPCL_P3D_PLUGIN P3D_instance_handle_event_func P3D_instance_handle_event; #endif /* P3D_FUNCTION_PROTOTYPES */ diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 5cdfdd41b4..faa769e3ff 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -438,7 +438,7 @@ handle_request(P3D_request *request) { //////////////////////////////////////////////////////////////////// // Function: PPInstance::handle_request_loop -// Access: Private, Static +// Access: Public, Static // Description: Checks for any new requests from the plugin, and // dispatches them to the appropriate PPInstance. This // function is called only in the main thread. @@ -461,6 +461,47 @@ handle_request_loop() { } } +//////////////////////////////////////////////////////////////////// +// Function: PPInstance::handle_event +// Access: Public +// Description: Called by the browser as new window events are +// generated. +//////////////////////////////////////////////////////////////////// +void PPInstance:: +handle_event(void *event) { + // This is a good time to check for new requests. + handle_request_loop(); + + if (_p3d_inst == NULL) { + // Ignore events that come in before we've launched the instance. + return; + } + +#ifdef __APPLE__ + EventRecord *er = (EventRecord *)event; + + switch (er->what) { + case nullEvent: + // We appear to get this event pretty frequently when nothing else + // is going on. Great; we'll take advantage of it to invalidate + // the instance rectangle, which will cause updateEvt to be + // triggered (if the instance is still onscreen). + + if (_got_window) { + NPRect rect = { 0, 0, _window.height, _window.width }; + browser->invalidaterect(_npp_instance, &rect); + } + break; + } + + // All other events we feed down to the plugin for processing. + P3D_event_data edata; + edata._event = er; + P3D_instance_handle_event(_p3d_inst, edata); + +#endif // __APPLE__ +} + //////////////////////////////////////////////////////////////////// // Function: PPInstance::get_panda_script_object // Access: Public @@ -972,14 +1013,24 @@ send_window() { // right spot. #ifdef _WIN32 parent_window._hwnd = (HWND)(_window.window); -#endif -#ifdef HAVE_X11 + x = 0; + y = 0; + +#elif defined(__APPLE__) + logfile << "windowed plugin\n" << flush; + NP_Port *port = (NP_Port *)_window.window; + logfile << "portx, porty = " << port->portx << ", " << port->porty << "\n"; + logfile << "x, y = " << _window.x << ", " << _window.y << "\n"; + parent_window._port = port->port; + +#elif defined(HAVE_X11) // We make it an 'unsigned long' instead of 'Window' // to avoid nppanda3d.so getting a dependency on X11. parent_window._xwindow = (unsigned long)(_window.window); -#endif x = 0; y = 0; +#endif + } else { // We have a "windowless" plugin. Parent our window directly to // the browser window. @@ -990,8 +1041,15 @@ send_window() { &hwnd) == NPERR_NO_ERROR) { parent_window._hwnd = hwnd; } -#endif -#ifdef HAVE_X11 + +#elif defined(__APPLE__) + logfile << "windowless plugin\n" << flush; + NP_Port *port = (NP_Port *)_window.window; + logfile << "portx, porty = " << port->portx << ", " << port->porty << "\n"; + logfile << "x, y = " << _window.x << ", " << _window.y << "\n"; + parent_window._port = port->port; + +#elif defined(HAVE_X11) parent_window._xwindow = 0; unsigned long win; if (browser->getvalue(_npp_instance, NPNVnetscapeWindow, diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index c213f1c0bb..871e9086d1 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -53,6 +53,8 @@ public: void handle_request(P3D_request *request); static void handle_request_loop(); + void handle_event(void *event); + NPObject *get_panda_script_object(); void p3dobj_to_variant(NPVariant *result, P3D_object *object); diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index 47ad54566b..94ab3f7453 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -331,8 +331,10 @@ int16 NPP_HandleEvent(NPP instance, void *event) { // logfile << "HandleEvent\n" << flush; - // Here's a fine opportunity to check for new requests. - PPInstance::handle_request_loop(); + PPInstance *inst = (PPInstance *)(instance->pdata); + assert(inst != NULL); + + inst->handle_event(event); return 0; } diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index c3419c8bd4..729510c469 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -258,8 +258,36 @@ class AppRunner(DirectObject): self.startIfReady() - def setupWindow(self, windowType, x, y, width, height, parent): - print "setupWindow %s, %s, %s, %s, %s, %s" % (windowType, x, y, width, height, parent) + def clearWindowPrc(self): + """ Clears the windowPrc file that was created in a previous + call to setupWindow(), if any. """ + + if self.windowPrc: + unloadPrcFile(self.windowPrc) + self.windowPrc = None + + def setupWindow(self, windowType, x, y, width, height, + parent, subprocessWindow): + """ Applies the indicated window parameters to the prc + settings, for future windows; or applies them directly to the + main window if the window has already been opened. """ + + print "setupWindow %s, %s, %s, %s, %s, %s, %s" % (windowType, x, y, width, height, parent, subprocessWindow) + + if self.started and base.win: + # If we've already got a window, this must be a + # resize/reposition request. + wp = WindowProperties() + if x or y or windowType == 'embedded': + wp.setOrigin(x, y) + if width or height: + wp.setSize(width, height) + base.win.requestProperties(wp) + return + + # If we haven't got a window already, start 'er up. Apply the + # requested setting to the prc file. + if windowType == 'hidden': data = 'window-type none\n' else: @@ -271,33 +299,21 @@ class AppRunner(DirectObject): data += 'fullscreen 0\n' if windowType == 'embedded': - data += 'parent-window-handle %s\n' % (parent) + data += 'parent-window-handle %s\nsubprocess-window %s\n' % ( + parent, subprocessWindow) else: - data += 'parent-window-handle 0\n' + data += 'parent-window-handle 0\nsubprocess-window \n' if x or y or windowType == 'embedded': data += 'win-origin %s %s\n' % (x, y) if width or height: data += 'win-size %s %s\n' % (width, height) - if self.windowPrc: - unloadPrcFile(self.windowPrc) + self.clearWindowPrc() self.windowPrc = loadPrcFileData("setupWindow", data) - if self.started and base.win: - # If we've already got a window, this must be a - # resize/reposition request. - wp = WindowProperties() - if x or y or windowType == 'embedded': - wp.setOrigin(x, y) - if width or height: - wp.setSize(width, height) - base.win.requestProperties(wp) - - else: - # If we haven't got a window already, start 'er up. - self.gotWindow = True - self.startIfReady() + self.gotWindow = True + self.startIfReady() def setRequestFunc(self, func): """ This method is called by the plugin at startup to supply a @@ -319,9 +335,15 @@ class AppRunner(DirectObject): successfully opened. """ if not self.windowOpened: - self.notifyRequest('onwindowopen') self.windowOpened = True + # Now that the window is open, we don't need to keep those + # prc settings around any more. + self.clearWindowPrc() + + # Inform the plugin and browser. + self.notifyRequest('onwindowopen') + def notifyRequest(self, message): """ Delivers a notify request to the browser. This is a "this happened" type notification; it optionally triggers some @@ -340,10 +362,10 @@ class AppRunner(DirectObject): def evalScript(self, expression, needsResponse = False): """ Evaluates an arbitrary JavaScript expression in the global - DOM space. This may be deferred if necessary if self.dom has - not yet been assigned. If needsResponse is true, this waits - for the value and returns it, which means it may not be - deferred. """ + DOM space. This may be deferred if necessary if needsResponse + is False and self.dom has not yet been assigned. If + needsResponse is true, this waits for the value and returns + it, which means it cannot be deferred. """ if not self.dom: # Defer the expression.