Browse Source

windows crashy

David Rose 16 years ago
parent
commit
b2906cda8b

+ 3 - 0
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();
 }
 

+ 82 - 2
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

+ 9 - 0
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;
 

+ 1 - 58
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;
 }