From b2906cda8bb0a3087d985065ca96c38d5fea6259 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 6 Jul 2009 22:34:46 +0000 Subject: [PATCH] windows crashy --- direct/src/plugin/load_plugin.cxx | 3 + direct/src/plugin_npapi/ppInstance.cxx | 84 +++++++++++++++++++++++++- direct/src/plugin_npapi/ppInstance.h | 9 +++ direct/src/plugin_npapi/startup.cxx | 59 +----------------- 4 files changed, 95 insertions(+), 60 deletions(-) diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 9bfa9b2baf..ab14b52ce9 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -275,6 +275,9 @@ unload_plugin() { cerr << "unload_plugin called\n"; P3D_finalize(); + + // TODO: unloading the DLL causes crashy problems on Windows. Must + // be an outstanding pointer or two still uncleaned-up. unload_dso(); } diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index e6c2c859c6..a713c134a8 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -73,7 +73,15 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode, PPInstance:: ~PPInstance() { logfile - << "destructing " << this << ", " << _p3d_inst << "\n" << flush; + << "destructing PPInstance " << this << "\n"; + +#ifdef _WIN32 + if (_got_window) { + // Restore the parent window to its own window handler. + HWND hwnd = (HWND)_window.window; + SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc); + } +#endif // _WIN32 if (_p3d_inst != NULL) { P3D_instance_finish(_p3d_inst); @@ -100,7 +108,8 @@ PPInstance:: //////////////////////////////////////////////////////////////////// void PPInstance:: set_window(NPWindow *window) { - if (window->x == _window.x && + if (_got_window && + window->x == _window.x && window->y == _window.y && window->width == _window.width && window->height == _window.height) { @@ -108,6 +117,25 @@ set_window(NPWindow *window) { return; } + if (_got_window) { + // We don't expect the browser to change the window's parent + // on-the-fly. + assert(_window.window == window->window); + } + +#ifdef _WIN32 + if (!_got_window) { + _orig_window_proc = NULL; + if (window->type == NPWindowTypeWindow) { + // Subclass the window to make it call our own window_proc instead + // of whatever window_proc it has already. This is just a dopey + // trick to allow us to poll events in the main thread. + HWND hwnd = (HWND)window->window; + _orig_window_proc = SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)window_proc); + } + } +#endif // _WIN32 + _window = *window; _got_window = true; @@ -416,6 +444,31 @@ handle_request(P3D_request *request) { P3D_request_finish(request, handled); } +//////////////////////////////////////////////////////////////////// +// Function: PPInstance::handle_request_loop +// 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. +//////////////////////////////////////////////////////////////////// +void PPInstance:: +handle_request_loop() { + if (!is_plugin_loaded()) { + return; + } + + P3D_instance *p3d_inst = P3D_check_request(false); + while (p3d_inst != (P3D_instance *)NULL) { + P3D_request *request = P3D_instance_get_request(p3d_inst); + if (request != (P3D_request *)NULL) { + PPInstance *inst = (PPInstance *)(p3d_inst->_user_data); + assert(inst != NULL); + inst->handle_request(request); + } + p3d_inst = P3D_check_request(false); + } +} + //////////////////////////////////////////////////////////////////// // Function: PPInstance::get_panda_script_object // Access: Public @@ -803,3 +856,30 @@ np_variant_to_object(const NPVariant &result) { // Huh, what is this? return NULL; } + + +#ifdef _WIN32 +//////////////////////////////////////////////////////////////////// +// Function: window_proc +// Access: Private, Static +// Description: We bind this function to the parent window we were +// given in set_window, so we can spin the request_loop +// when needed. This is only in the Windows case; other +// platforms rely on explicit windows events. +//////////////////////////////////////////////////////////////////// +LONG PPInstance:: +window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + // If this is a toplevel window event, but not something caused as a + // result of something done by handle_request_loop(), then call + // handle_request_loop() to see if there are any new requests to be + // forwarded to the main thread. + static int recursion_protect = 0; + ++recursion_protect; + if (recursion_protect == 1) { + handle_request_loop(); + } + --recursion_protect; + + return DefWindowProc(hwnd, msg, wparam, lparam); +} +#endif // _WIN32 diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index d7b0329a2f..ff88e9fb9e 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -48,6 +48,7 @@ public: void stream_as_file(NPStream *stream, const char *fname); void handle_request(P3D_request *request); + static void handle_request_loop(); NPObject *get_panda_script_object(); @@ -66,6 +67,11 @@ private: void show_np_variant(const NPVariant &result); P3D_object *np_variant_to_object(const NPVariant &result); +#ifdef _WIN32 + static LONG + window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); +#endif // _WIN32 + private: NPP _npp_instance; unsigned int _npp_mode; @@ -81,6 +87,9 @@ private: bool _got_window; NPWindow _window; +#ifdef _WIN32 + LONG_PTR _orig_window_proc; +#endif // _WIN32 PPPandaObject *_script_object; diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index f96409f3cf..109b24d2eb 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -34,53 +34,6 @@ open_logfile() { } -//////////////////////////////////////////////////////////////////// -// Function: handle_request_loop -// Description: Checks for any new requests from the plugin. This -// function is called only in the main thread. -//////////////////////////////////////////////////////////////////// -static void -handle_request_loop() { - if (!is_plugin_loaded()) { - return; - } - - P3D_instance *p3d_inst = P3D_check_request(false); - while (p3d_inst != (P3D_instance *)NULL) { - P3D_request *request = P3D_instance_get_request(p3d_inst); - if (request != (P3D_request *)NULL) { - PPInstance *inst = (PPInstance *)(p3d_inst->_user_data); - assert(inst != NULL); - inst->handle_request(request); - } - p3d_inst = P3D_check_request(false); - } -} - -#ifdef _WIN32 -//////////////////////////////////////////////////////////////////// -// Function: window_proc -// Description: We bind this function to the parent windows we are -// given in NPP_New(), so we can spin the request_loop -// when needed. -//////////////////////////////////////////////////////////////////// -static LONG -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - // If this is a toplevel window event, but not something caused as a - // result of something done by handle_request_loop(), then call - // handle_request_loop() to see if there are any new requests to be - // forwarded to the main thread. - static int recursion_protect = 0; - ++recursion_protect; - if (recursion_protect == 1) { - handle_request_loop(); - } - --recursion_protect; - - return DefWindowProc(hwnd, msg, wparam, lparam); -} -#endif // _WIN32 - //////////////////////////////////////////////////////////////////// // Function: request_ready // Description: This function is attached as an asynchronous callback @@ -241,16 +194,6 @@ NPP_SetWindow(NPP instance, NPWindow *window) { << ", " << window->width << ", " << window->height << "\n" << flush; -#ifdef _WIN32 - if (window->type == NPWindowTypeWindow) { - // Subclass the window to make it call our own window_proc instead - // of whatever window_proc it has already. This is just a dopey - // trick to allow us to poll events in the main thread. - HWND hwnd = (HWND)window->window; - LONG_PTR orig = SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)window_proc); - } -#endif // _WIN32 - PPInstance *inst = (PPInstance *)(instance->pdata); assert(inst != NULL); inst->set_window(window); @@ -367,7 +310,7 @@ NPP_HandleEvent(NPP instance, void *event) { // logfile << "HandleEvent\n"; // Here's a fine opportunity to check for new requests. - handle_request_loop(); + PPInstance::handle_request_loop(); return 0; }