فهرست منبع

fix windows crash; fix splash window drawing

David Rose 16 سال پیش
والد
کامیت
bc0d953ab5

+ 5 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -17,6 +17,7 @@
 #include "p3dSession.h"
 #include "p3dSession.h"
 #include "p3dPackage.h"
 #include "p3dPackage.h"
 #include "p3d_plugin_config.h"
 #include "p3d_plugin_config.h"
+#include "p3dWinSplashWindow.h"
 #include "find_root_dir.h"
 #include "find_root_dir.h"
 #include "mkdir_complete.h"
 #include "mkdir_complete.h"
 
 
@@ -70,6 +71,10 @@ P3DInstanceManager::
 
 
   assert(_instances.empty());
   assert(_instances.empty());
   assert(_sessions.empty());
   assert(_sessions.empty());
+
+#ifdef _WIN32
+  P3DWinSplashWindow::unregister_window_class();
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 6 - 0
direct/src/plugin/p3dPythonRun.cxx

@@ -209,6 +209,7 @@ run_python() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DPythonRun::
 void P3DPythonRun::
 handle_command(TiXmlDocument *doc) {
 handle_command(TiXmlDocument *doc) {
+  nout << "received: " << *doc << "\n" << flush;
   TiXmlElement *xcommand = doc->FirstChildElement("command");
   TiXmlElement *xcommand = doc->FirstChildElement("command");
   if (xcommand != NULL) {
   if (xcommand != NULL) {
     bool needs_response = false;
     bool needs_response = false;
@@ -267,6 +268,7 @@ handle_command(TiXmlDocument *doc) {
           xresponse->SetAttribute("response_id", want_response_id);
           xresponse->SetAttribute("response_id", want_response_id);
           doc.LinkEndChild(decl);
           doc.LinkEndChild(decl);
           doc.LinkEndChild(xresponse);
           doc.LinkEndChild(xresponse);
+          nout << "sent: " << doc << "\n" << flush;
           _pipe_write << doc << flush;
           _pipe_write << doc << flush;
         }
         }
       }
       }
@@ -413,6 +415,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
   }
   }
 
 
   if (needs_response) {
   if (needs_response) {
+    nout << "sent: " << doc << "\n" << flush;
     _pipe_write << doc << flush;
     _pipe_write << doc << flush;
   }
   }
 }
 }
@@ -488,6 +491,7 @@ wait_script_response(int response_id) {
               // This is the response we were waiting for.
               // This is the response we were waiting for.
               _commands.erase(ci);
               _commands.erase(ci);
               RELEASE_LOCK(_commands_lock);
               RELEASE_LOCK(_commands_lock);
+              nout << "received: " << *doc << "\n" << flush;
               return doc;
               return doc;
             }
             }
           }
           }
@@ -585,6 +589,7 @@ py_request_func(PyObject *args) {
     }
     }
 
 
     xrequest->SetAttribute("message", message);
     xrequest->SetAttribute("message", message);
+    nout << "sent: " << doc << "\n" << flush;
     _pipe_write << doc << flush;
     _pipe_write << doc << flush;
 
 
   } else if (strcmp(request_type, "script") == 0) {
   } else if (strcmp(request_type, "script") == 0) {
@@ -609,6 +614,7 @@ py_request_func(PyObject *args) {
     TiXmlElement *xvalue = pyobj_to_xml(value);
     TiXmlElement *xvalue = pyobj_to_xml(value);
     xrequest->LinkEndChild(xvalue);
     xrequest->LinkEndChild(xvalue);
 
 
+    nout << "sent: " << doc << "\n" << flush;
     _pipe_write << doc << flush;
     _pipe_write << doc << flush;
 
 
   } else {
   } else {

+ 4 - 0
direct/src/plugin/p3dSession.cxx

@@ -85,6 +85,7 @@ P3DSession::
     xcommand->SetAttribute("cmd", "exit");
     xcommand->SetAttribute("cmd", "exit");
     doc.LinkEndChild(decl);
     doc.LinkEndChild(decl);
     doc.LinkEndChild(xcommand);
     doc.LinkEndChild(xcommand);
+    nout << "sent: " << doc << "\n" << flush;
     _pipe_write << doc << flush;
     _pipe_write << doc << flush;
 
 
     // Also close the pipe, to help underscore the point.
     // Also close the pipe, to help underscore the point.
@@ -214,6 +215,7 @@ void P3DSession::
 send_command(TiXmlDocument *command) {
 send_command(TiXmlDocument *command) {
   if (_p3dpython_running) {
   if (_p3dpython_running) {
     // Python is running.  Send the command.
     // Python is running.  Send the command.
+    nout << "sent: " << *command << "\n" << flush;
     _pipe_write << *command << flush;
     _pipe_write << *command << flush;
     delete command;
     delete command;
   } else {
   } else {
@@ -252,6 +254,7 @@ command_and_response(TiXmlDocument *command) {
   assert(xcommand != NULL);
   assert(xcommand != NULL);
   xcommand->SetAttribute("want_response_id", response_id);
   xcommand->SetAttribute("want_response_id", response_id);
 
 
+  nout << "sent: " << *command << "\n" << flush;
   _pipe_write << *command << flush;
   _pipe_write << *command << flush;
   delete command;
   delete command;
 
 
@@ -541,6 +544,7 @@ start_p3dpython() {
   // may have queued up.
   // may have queued up.
   Commands::iterator ci;
   Commands::iterator ci;
   for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
   for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
+    nout << "sent: " << *(*ci) << "\n" << flush;
     _pipe_write << *(*ci);
     _pipe_write << *(*ci);
     delete (*ci);
     delete (*ci);
   }
   }

+ 116 - 63
direct/src/plugin/p3dWinSplashWindow.cxx

@@ -16,6 +16,8 @@
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 
 
+bool P3DWinSplashWindow::_registered_window_class = false;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::Constructor
 //     Function: P3DWinSplashWindow::Constructor
 //       Access: Public
 //       Access: Public
@@ -132,7 +134,49 @@ set_install_progress(double install_progress) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DWinSplashWindow::start_thraed
+//     Function: P3DWinSplashWindow::register_window_class
+//       Access: Public, Static
+//  Description: Registers the window class for this window, if
+//               needed.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+register_window_class() {
+  if (!_registered_window_class) {
+    HINSTANCE application = GetModuleHandle(NULL);
+
+    WNDCLASS wc;
+    ZeroMemory(&wc, sizeof(WNDCLASS));
+    wc.lpfnWndProc = st_window_proc;
+    wc.hInstance = application;
+    wc.lpszClassName = "panda3d_splash";
+    
+    if (!RegisterClass(&wc)) {
+      nout << "Could not register window class panda3d_splash\n";
+    }
+    _registered_window_class = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::unregister_window_class
+//       Access: Public, Static
+//  Description: Unregisters the window class for this window.  It is
+//               necessary to do this before unloading the DLL.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+unregister_window_class() {
+  if (_registered_window_class) {
+    HINSTANCE application = GetModuleHandle(NULL);
+
+    if (!UnregisterClass("panda3d_splash", application)) {
+      nout << "Could not unregister window class panda3d_splash\n";
+    }
+    _registered_window_class = false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::start_thread
 //       Access: Private
 //       Access: Private
 //  Description: Spawns the sub-thread.
 //  Description: Spawns the sub-thread.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -146,7 +190,7 @@ start_thread() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DWinSplashWindow::stop_thraed
+//     Function: P3DWinSplashWindow::stop_thread
 //       Access: Private
 //       Access: Private
 //  Description: Terminates and joins the sub-thread.
 //  Description: Terminates and joins the sub-thread.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -241,23 +285,8 @@ win_thread_run(LPVOID data) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DWinSplashWindow::
 void P3DWinSplashWindow::
 make_window() {
 make_window() {
-  WNDCLASS wc;
-
+  register_window_class();
   HINSTANCE application = GetModuleHandle(NULL);
   HINSTANCE application = GetModuleHandle(NULL);
-
-  static bool registered_class = false;
-  if (!registered_class) {
-    ZeroMemory(&wc, sizeof(WNDCLASS));
-    wc.lpfnWndProc = st_window_proc;
-    wc.hInstance = application;
-    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
-    wc.lpszClassName = "panda3d_splash";
-    
-    if (!RegisterClass(&wc)) {
-      nout << "Could not register window class!\n";
-    }
-    registered_class = true;
-  }
   
   
   int x = CW_USEDEFAULT;
   int x = CW_USEDEFAULT;
   int y = CW_USEDEFAULT;
   int y = CW_USEDEFAULT;
@@ -482,6 +511,69 @@ close_window() {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DWinSplashWindow::paint_window
+//       Access: Private
+//  Description: Paints the contents of the window into the indicated
+//               DC.
+////////////////////////////////////////////////////////////////////
+void P3DWinSplashWindow::
+paint_window(HDC dc) {
+  RECT rect;
+  GetClientRect(_hwnd, &rect);
+  int win_width = rect.right - rect.left;
+  int win_height = rect.bottom - rect.top;
+  
+  if (_bitmap != NULL) {
+    // Paint the background splash image.
+    HDC mem_dc = CreateCompatibleDC(dc);
+    SelectObject(mem_dc, _bitmap);
+    
+    // Determine the relative size of bitmap and window.
+    int bm_width = _bitmap_width;
+    int bm_height = _bitmap_height;
+    
+    int win_cx = win_width / 2;
+    int win_cy = win_height / 2;
+    
+    if (bm_width <= win_width && bm_height <= win_height) {
+      // The bitmap fits within the window; center it.
+      
+      // This is the top-left corner of the bitmap in window coordinates.
+      int p_x = win_cx - bm_width / 2;
+      int p_y = win_cy - bm_height / 2;
+      
+      BitBlt(dc, p_x, p_y, bm_width, bm_height,
+             mem_dc, 0, 0, SRCCOPY);
+
+      // Now don't paint over this in the below FillRect().
+      ExcludeClipRect(dc, p_x, p_y, p_x + bm_width, p_y + bm_height);
+      
+    } else {
+      // The bitmap is larger than the window; scale it down.
+      double x_scale = (double)win_width / (double)bm_width;
+      double y_scale = (double)win_height / (double)bm_height;
+      double scale = min(x_scale, y_scale);
+      int sc_width = (int)(bm_width * scale);
+      int sc_height = (int)(bm_height * scale);
+      
+      int p_x = win_cx - sc_width / 2;
+      int p_y = win_cy - sc_height / 2;
+      StretchBlt(dc, p_x, p_y, sc_width, sc_height,
+                 mem_dc, 0, 0, bm_width, bm_height, SRCCOPY);
+
+      // Now don't paint over this in the below FillRect().
+      ExcludeClipRect(dc, p_x, p_y, p_x + sc_width, p_y + sc_height);
+    }
+    
+    SelectObject(mem_dc, NULL);
+    DeleteDC(mem_dc);
+  }
+
+  // Paint everything else the background color.
+  FillRect(dc, &rect, WHITE_BRUSH);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::window_proc
 //     Function: P3DWinSplashWindow::window_proc
 //       Access: Private
 //       Access: Private
@@ -495,59 +587,20 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     break;
     break;
 
 
   case WM_SIZE:
   case WM_SIZE:
-    InvalidateRect(hwnd, NULL, TRUE);
+    InvalidateRect(hwnd, NULL, FALSE);
     break;
     break;
 
 
+  case WM_ERASEBKGND:
+    return true;
+
   case WM_PAINT:
   case WM_PAINT:
     {
     {
       PAINTSTRUCT ps;
       PAINTSTRUCT ps;
       HDC dc = BeginPaint(hwnd, &ps);
       HDC dc = BeginPaint(hwnd, &ps);
-      if (_bitmap != NULL) {
-        // Paint the background splash image.
-        HDC mem_dc = CreateCompatibleDC(dc);
-        SelectObject(mem_dc, _bitmap);
-        
-        // Determine the relative size of bitmap and window.
-        RECT rect;
-        GetClientRect(hwnd, &rect);
-        int win_width = rect.right - rect.left;
-        int win_height = rect.bottom - rect.top;
-        int bm_width = _bitmap_width;
-        int bm_height = _bitmap_height;
-        
-        int win_cx = win_width / 2;
-        int win_cy = win_height / 2;
-        
-        if (bm_width <= win_width && bm_height <= win_height) {
-          // The bitmap fits within the window; center it.
-          
-          // This is the top-left corner of the bitmap in window coordinates.
-          int p_x = win_cx - bm_width / 2;
-          int p_y = win_cy - bm_height / 2;
-          
-          BitBlt(dc, p_x, p_y, bm_width, bm_height,
-                 mem_dc, 0, 0, SRCCOPY);
-          
-        } else {
-          // The bitmap is larger than the window; scale it down.
-          double x_scale = (double)win_width / (double)bm_width;
-          double y_scale = (double)win_height / (double)bm_height;
-          double scale = min(x_scale, y_scale);
-          int sc_width = (int)(bm_width * scale);
-          int sc_height = (int)(bm_height * scale);
-          
-          int p_x = win_cx - sc_width / 2;
-          int p_y = win_cy - sc_height / 2;
-          StretchBlt(dc, p_x, p_y, sc_width, sc_height,
-                     mem_dc, 0, 0, bm_width, bm_height, SRCCOPY);
-        }
-        
-        SelectObject(mem_dc, NULL);
-        DeleteDC(mem_dc);
-      }
+      paint_window(dc);
       EndPaint(hwnd, &ps);
       EndPaint(hwnd, &ps);
     }
     }
-    break;
+    return true;
 
 
   case WM_DRAWITEM:
   case WM_DRAWITEM:
     // Draw a text label placed within the window.
     // Draw a text label placed within the window.

+ 6 - 0
direct/src/plugin/p3dWinSplashWindow.h

@@ -39,6 +39,9 @@ public:
   virtual void set_install_label(const string &install_label);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_progress(double install_progress);
   virtual void set_install_progress(double install_progress);
 
 
+  static void register_window_class();
+  static void unregister_window_class();
+
 private:
 private:
   void start_thread();
   void start_thread();
   void stop_thread();
   void stop_thread();
@@ -55,6 +58,7 @@ private:
                              bool image_filename_temp);
                              bool image_filename_temp);
   void close_window();
   void close_window();
 
 
+  void paint_window(HDC dc);
   LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   static LONG WINAPI st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   static LONG WINAPI st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
 
 
@@ -79,6 +83,8 @@ private:
   int _bitmap_width, _bitmap_height;
   int _bitmap_width, _bitmap_height;
   HWND _progress_bar;
   HWND _progress_bar;
   HWND _text_label;
   HWND _text_label;
+
+  static bool _registered_window_class;
 };
 };
 
 
 #include "p3dWinSplashWindow.I"
 #include "p3dWinSplashWindow.I"

+ 28 - 7
direct/src/plugin_npapi/ppInstance.cxx

@@ -419,6 +419,10 @@ handle_request(P3D_request *request) {
     }
     }
     break;
     break;
 
 
+  case P3D_RT_script:
+    // We're allowed to ignore this.
+    break;
+
   default:
   default:
     // Some request types are not handled.
     // Some request types are not handled.
     logfile << "Unhandled request: " << request->_request_type << "\n";
     logfile << "Unhandled request: " << request->_request_type << "\n";
@@ -762,24 +766,34 @@ void PPInstance::
 send_window() {
 send_window() {
   assert(_p3d_inst != NULL);
   assert(_p3d_inst != NULL);
 
 
+  int x = _window.x;
+  int y = _window.y;
+
   P3D_window_handle parent_window;
   P3D_window_handle parent_window;
 #ifdef _WIN32
 #ifdef _WIN32
   if (_window.type == NPWindowTypeWindow) {
   if (_window.type == NPWindowTypeWindow) {
+    // We have a "windowed" plugin.  Parent our window to the one we
+    // were given.  In this case, we should also reset the offset to
+    // (0, 0), since the window we were given is already placed in the
+    // right spot.
     parent_window._hwnd = (HWND)(_window.window);
     parent_window._hwnd = (HWND)(_window.window);
+    x = 0;
+    y = 0;
   } else {
   } else {
-    // Hmm, it's just a drawable; but we didn't ask for a windowless
-    // plugin.
+    // We have a "windowless" plugin.  Parent our window directly to
+    // the browser window.
     parent_window._hwnd = 0;
     parent_window._hwnd = 0;
+    HWND hwnd;
+    if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
+                          &hwnd) == NPERR_NO_ERROR) {
+      parent_window._hwnd = hwnd;
+    }
   }
   }
 #endif
 #endif
 
 
-  // Actually, we set up the window starting at (0, 0), instead of
-  // whatever Mozilla tells us, because the window handle we get is a
-  // specially created window that is already aligned to where we want
-  // our window to be.
   P3D_instance_setup_window
   P3D_instance_setup_window
     (_p3d_inst, P3D_WT_embedded,
     (_p3d_inst, P3D_WT_embedded,
-     0, 0, _window.width, _window.height,
+     x, y, _window.width, _window.height,
      parent_window);
      parent_window);
 }
 }
 
 
@@ -832,6 +846,13 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
   }
   }
   --recursion_protect;
   --recursion_protect;
 
 
+  switch (msg) {
+  case WM_ERASEBKGND:
+    // Eat the WM_ERASEBKGND message, so the browser's intervening
+    // window won't overdraw on top of our own window.
+    return true;
+  }
+
   return DefWindowProc(hwnd, msg, wparam, lparam);
   return DefWindowProc(hwnd, msg, wparam, lparam);
 }
 }
 #endif  // _WIN32
 #endif  // _WIN32

+ 8 - 2
direct/src/plugin_npapi/startup.cxx

@@ -57,7 +57,7 @@ request_ready(P3D_instance *instance) {
   PPInstance *inst = (PPInstance *)(instance->_user_data);
   PPInstance *inst = (PPInstance *)(instance->_user_data);
   assert(inst != NULL);
   assert(inst != NULL);
   const NPWindow *win = inst->get_window();
   const NPWindow *win = inst->get_window();
-  if (win != NULL) {
+  if (win != NULL && win->type == NPWindowTypeWindow) {
     PostMessage((HWND)(win->window), WM_USER, 0, 0);
     PostMessage((HWND)(win->window), WM_USER, 0, 0);
   }
   }
 
 
@@ -161,6 +161,12 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
   instance->pdata = new PPInstance(pluginType, instance, mode,
   instance->pdata = new PPInstance(pluginType, instance, mode,
                                    argc, argn, argv, saved);
                                    argc, argn, argv, saved);
 
 
+  // To experiment with a "windowless" plugin, which really means we
+  // create our own window without an intervening window, try this.
+  // At the moment, there's a deadlock condition when we try it, but
+  // surely it can be solved.
+  //  browser->setvalue(instance, NPPVpluginWindowBool, (void *)false);
+
   return NPERR_NO_ERROR;
   return NPERR_NO_ERROR;
 }
 }
 
 
@@ -307,7 +313,7 @@ NPP_Print(NPP instance, NPPrint *platformPrint) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int16
 int16
 NPP_HandleEvent(NPP instance, void *event) {
 NPP_HandleEvent(NPP instance, void *event) {
-  //  logfile << "HandleEvent\n";
+  logfile << "HandleEvent\n" << flush;
 
 
   // Here's a fine opportunity to check for new requests.
   // Here's a fine opportunity to check for new requests.
   PPInstance::handle_request_loop();
   PPInstance::handle_request_loop();