Browse Source

More Linux work - the plugin now really works on Linux.

rdb 16 years ago
parent
commit
474b738f8b

+ 9 - 1
direct/src/plugin/Sources.pp

@@ -3,9 +3,15 @@
 #define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_TINYXML],$[HAVE_OPENSSL],$[HAVE_ZLIB]]
 #define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_TINYXML],$[HAVE_OPENSSL],$[HAVE_ZLIB]]
 
 
 #begin lib_target
 #begin lib_target
-  #define USE_PACKAGES tinyxml openssl zlib jpeg
+  #define USE_PACKAGES tinyxml openssl zlib jpeg x11
   #define TARGET p3d_plugin
   #define TARGET p3d_plugin
   #define LIB_PREFIX
   #define LIB_PREFIX
+  
+  // We need this because we don't
+  // include dtool_config.h.
+  #if $[HAVE_X11]
+    #define EXTRA_CDEFS HAVE_X11
+  #endif
 
 
   #define COMBINED_SOURCES \
   #define COMBINED_SOURCES \
     $[TARGET]_composite1.cxx
     $[TARGET]_composite1.cxx
@@ -39,6 +45,7 @@
     p3dStringObject.h \
     p3dStringObject.h \
     p3dUndefinedObject.h \
     p3dUndefinedObject.h \
     p3dWinSplashWindow.h p3dWinSplashWindow.I \
     p3dWinSplashWindow.h p3dWinSplashWindow.I \
+    p3dX11SplashWindow.h \
     p3dWindowParams.h p3dWindowParams.I
     p3dWindowParams.h p3dWindowParams.I
 
 
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
@@ -62,6 +69,7 @@
     p3dStringObject.cxx \
     p3dStringObject.cxx \
     p3dUndefinedObject.cxx \
     p3dUndefinedObject.cxx \
     p3dWinSplashWindow.cxx \
     p3dWinSplashWindow.cxx \
+    p3dX11SplashWindow.cxx \
     p3dWindowParams.cxx
     p3dWindowParams.cxx
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \

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

@@ -19,6 +19,7 @@
 #include "p3dPackage.h"
 #include "p3dPackage.h"
 #include "p3dSplashWindow.h"
 #include "p3dSplashWindow.h"
 #include "p3dWinSplashWindow.h"
 #include "p3dWinSplashWindow.h"
+#include "p3dX11SplashWindow.h"
 #include "p3dObject.h"
 #include "p3dObject.h"
 #include "p3dUndefinedObject.h"
 #include "p3dUndefinedObject.h"
 
 
@@ -28,8 +29,12 @@
 #ifdef _WIN32
 #ifdef _WIN32
 typedef P3DWinSplashWindow SplashWindowType;
 typedef P3DWinSplashWindow SplashWindowType;
 #else
 #else
+#ifdef HAVE_X11
+typedef P3DX11SplashWindow SplashWindowType;
+#else
 typedef P3DSplashWindow SplashWindowType;
 typedef P3DSplashWindow SplashWindowType;
 #endif
 #endif
+#endif
 
 
 int P3DInstance::_next_instance_id = 0;
 int P3DInstance::_next_instance_id = 0;
 
 

+ 2 - 1
direct/src/plugin/p3dInstanceManager.cxx

@@ -368,8 +368,9 @@ nt_thread_run() {
       for (ni = instances.begin(); ni != instances.end(); ++ni) {
       for (ni = instances.begin(); ni != instances.end(); ++ni) {
         // TODO: a race condition here when instances are deleted.
         // TODO: a race condition here when instances are deleted.
         P3DInstance *inst = (*ni);
         P3DInstance *inst = (*ni);
-        P3D_request_ready_func *func = inst->get_request_ready_func();
         assert(inst != NULL);
         assert(inst != NULL);
+        P3D_request_ready_func *func = inst->get_request_ready_func();
+        assert(func != NULL);
         (*func)(inst);
         (*func)(inst);
       }
       }
       _notify_ready.acquire();
       _notify_ready.acquire();

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

@@ -851,6 +851,13 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
     parent_window_handle = (long)hwnd;
     parent_window_handle = (long)hwnd;
   }
   }
 #endif
 #endif
+#ifdef HAVE_X11
+  // Bad! Casting to int loses precision.
+  int xwindow;
+  if (xwparams->Attribute("parent_xwindow", &xwindow)) {
+    parent_window_handle = (unsigned long)xwindow;
+  }
+#endif
 
 
   // TODO: direct this into the particular instance.  This will
   // TODO: direct this into the particular instance.  This will
   // require a specialized ShowBase replacement.
   // require a specialized ShowBase replacement.

+ 3 - 0
direct/src/plugin/p3dWindowParams.cxx

@@ -79,6 +79,9 @@ make_xml() {
     xwparams->SetAttribute("win_height", _win_height);
     xwparams->SetAttribute("win_height", _win_height);
 #ifdef _WIN32
 #ifdef _WIN32
     xwparams->SetAttribute("parent_hwnd", (int)_parent_window._hwnd);
     xwparams->SetAttribute("parent_hwnd", (int)_parent_window._hwnd);
+#endif
+#ifdef HAVE_X11
+    xwparams->SetAttribute("parent_xwindow", (unsigned long)_parent_window._xwindow);
 #endif
 #endif
     break;
     break;
 
 

+ 301 - 0
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -0,0 +1,301 @@
+// Filename: p3dX11SplashWindow.cxx
+// Created by:  pro-rsoft (08Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "p3dX11SplashWindow.h"
+
+#ifdef HAVE_X11
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DX11SplashWindow::
+P3DX11SplashWindow(P3DInstance *inst) : 
+  P3DSplashWindow(inst)
+{
+  INIT_THREAD(_thread);
+  _display = None;
+  _window = None;
+  _screen = 0;
+  _graphics_context = None;
+  _thread_running = false;
+  _got_install = false;
+  _image_filename_changed = false;
+  _image_filename_temp = false;
+  _install_label_changed = false;
+  _install_progress = 0.0;
+
+  INIT_LOCK(_install_lock);
+
+  start_thread();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DX11SplashWindow::
+~P3DX11SplashWindow() {
+  stop_thread();
+
+  DESTROY_LOCK(_install_lock);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::set_image_filename
+//       Access: Public, Virtual
+//               displayed in the center of the splash window.  If
+//               image_filename_temp is true, the file is immediately
+//               deleted after it has been read.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+set_image_filename(const string &image_filename,
+                   bool image_filename_temp) {
+  ACQUIRE_LOCK(_install_lock);
+  if (_image_filename != image_filename) {
+    _image_filename = image_filename;
+    _image_filename_temp = image_filename_temp;
+    _image_filename_changed = true;
+  }
+  RELEASE_LOCK(_install_lock);
+
+  // Post a silly message to spin the message loop.
+  //PostThreadMessage(_thread_id, WM_USER, 0, 0);
+
+  if (!_thread_running && _thread_continue) {
+    // The user must have closed the window.  Let's shut down the
+    // instance, too.
+    _inst->request_stop();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::set_install_label
+//       Access: Public, Virtual
+//  Description: Specifies the text that is displayed above the
+//               install progress bar.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+set_install_label(const string &install_label) {
+  ACQUIRE_LOCK(_install_lock);
+  if (_install_label != install_label) {
+    _install_label = install_label;
+    _install_label_changed = true;
+  }
+  RELEASE_LOCK(_install_lock);
+
+  // Post a silly message to spin the message loop.
+  //PostThreadMessage(_thread_id, WM_USER, 0, 0);
+
+  if (!_thread_running && _thread_continue) {
+    // The user must have closed the window.  Let's shut down the
+    // instance, too.
+    _inst->request_stop();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::set_install_progress
+//       Access: Public, Virtual
+//  Description: Moves the install progress bar from 0.0 to 1.0.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+set_install_progress(double install_progress) {
+  _got_install = true;
+
+  ACQUIRE_LOCK(_install_lock);
+  _install_progress = install_progress;
+  RELEASE_LOCK(_install_lock);
+
+  // Post a silly message to spin the message loop.
+  //PostThreadMessage(_thread_id, WM_USER, 0, 0);
+
+  if (!_thread_running && _thread_continue) {
+    // The user must have closed the window.  Let's shut down the
+    // instance, too.
+    _inst->request_stop();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::start_thread
+//       Access: Private
+//  Description: Spawns the sub-thread.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+start_thread() {
+  _thread_continue = true;
+  INIT_THREAD(_thread);
+  SPAWN_THREAD(_thread, thread_run, this);
+  if (_thread != 0) {
+    _thread_running = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::stop_thread
+//       Access: Private
+//  Description: Terminates and joins the sub-thread.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+stop_thread() {
+  _thread_continue = false;
+  // Post a silly message to spin the message loop.
+  //PostThreadMessage(_thread_id, WM_USER, 0, 0);
+
+  JOIN_THREAD(_thread);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::thread_run
+//       Access: Private
+//  Description: The sub-thread's main run method.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+thread_run() {
+  make_window();
+  setup_gc();
+
+  XEvent event;
+  XSelectInput(_display, _window, ExposureMask);
+  
+  bool override = true, have_event = false;
+  string prev_label;
+  
+  while (_thread_continue) {
+    have_event = XCheckTypedWindowEvent(_display, _window, Expose, &event);
+    
+    ACQUIRE_LOCK(_install_lock);
+    double install_progress = _install_progress;
+    
+    if (have_event || _install_label != prev_label) {
+      redraw(_install_label, install_progress);
+      override = false;
+    }
+    prev_label = _install_label;
+    
+    RELEASE_LOCK(_install_lock);
+  }
+
+  close_window();
+  _thread_running = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::redraw
+//       Access: Private
+//  Description: Redraws the window.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+redraw(string label, double progress) {
+  if (_graphics_context == NULL) return;
+  
+  XClearWindow(_display, _window);
+  XDrawString(_display, _window, _graphics_context, 10, 20, label.c_str(), label.size());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::make_window
+//       Access: Private
+//  Description: Creates the window for displaying progress.  Runs
+//               within the sub-thread.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+make_window() {
+  int x = 0;
+  int y = 0;
+  if (_wparams.get_win_x() != 0 && _wparams.get_win_y() != 0) {
+    x = _wparams.get_win_x();
+    y = _wparams.get_win_y();
+  }
+  
+  int width = 320;
+  int height = 240;
+  if (_wparams.get_win_width() != 0 && _wparams.get_win_height() != 0) {
+    width = _wparams.get_win_width();
+    height = _wparams.get_win_height();
+  }
+
+  Window parent = 0;
+  _display = (Display*) _wparams.get_parent_window()._xdisplay;
+  if (_display == 0) {
+    _display = XOpenDisplay(NULL);
+  }
+  _screen = DefaultScreen(_display);
+
+  if (_wparams.get_window_type() == P3D_WT_embedded) {
+    // Create an embedded window.
+    parent = _wparams.get_parent_window()._xwindow;
+  } else {
+    // Create a toplevel window.
+    parent = XRootWindow(_display, _screen);
+  }
+  
+  assert(_display != NULL);
+  assert(parent != None);
+  _window = XCreateSimpleWindow(_display, parent, x, y, width, height, 0, 0, -1);
+  XMapWindow(_display, _window);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::setup_gc
+//       Access: Private
+//  Description: Sets up the graphics context for drawing the text.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+setup_gc() {
+  if (_graphics_context != NULL) {
+    return;
+  }
+
+  ACQUIRE_LOCK(_install_lock);
+  string install_label = _install_label;
+  double install_progress = _install_progress;
+  _install_label_changed = false;
+  RELEASE_LOCK(_install_lock);
+
+  
+  XFontStruct* fs = XLoadQueryFont(_display, "6x13");
+  XGCValues gcval;
+  gcval.font = fs->fid; 
+  gcval.function = GXcopy;
+  gcval.plane_mask = AllPlanes;
+  gcval.foreground = BlackPixel(_display, _screen);
+  gcval.background = WhitePixel(_display, _screen);
+  _graphics_context = XCreateGC(_display, _window, 
+    GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval); 
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::close_window
+//       Access: Private
+//  Description: Closes the window created above.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+close_window() {
+  if (_window != None) {
+    XDestroyWindow(_display, _window);
+    _window = None;
+  }
+
+  if (_display != None) {
+    XCloseDisplay(_display);
+    _display = None;
+  }
+}
+
+#endif  // HAVE_X11

+ 82 - 0
direct/src/plugin/p3dX11SplashWindow.h

@@ -0,0 +1,82 @@
+// Filename: p3dX11SplashWindow.h
+// Created by:  pro-rsoft (08Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef P3DX11SPLASHWINDOW_H
+#define P3DX11SPLASHWINDOW_H
+
+#include "p3d_plugin_common.h"
+
+#ifdef HAVE_X11
+
+#include "p3dSplashWindow.h"
+#include "p3d_lock.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DX11SplashWindow
+// Description : This is the Windows implementation of the
+//               initial-download window.
+////////////////////////////////////////////////////////////////////
+class P3DX11SplashWindow : public P3DSplashWindow {
+public:
+  P3DX11SplashWindow(P3DInstance *inst);
+  virtual ~P3DX11SplashWindow();
+
+  virtual void set_image_filename(const string &image_filename,
+                                  bool image_filename_temp);
+  virtual void set_install_label(const string &install_label);
+  virtual void set_install_progress(double install_progress);
+
+private:
+  void start_thread();
+  void stop_thread();
+
+private:
+  // These methods run only within the window thread.
+  void thread_run();
+  THREAD_CALLBACK_DECLARATION(P3DX11SplashWindow, thread_run);
+
+  void redraw(string label, double progress);
+  void make_window();
+  void setup_gc();
+  void close_window();
+
+private:
+  bool _got_install;
+  bool _image_filename_changed;
+  string _image_filename;
+  bool _image_filename_temp;
+  bool _install_label_changed;
+  string _install_label;
+  double _install_progress;
+  LOCK _install_lock;
+  
+  string _label_text;
+
+  bool _thread_continue;
+  bool _thread_running;
+  Display *_display;
+  int _screen;
+  GC _graphics_context;
+  
+  THREAD _thread;
+  Window _window;
+  int _bitmap_width, _bitmap_height;
+};
+
+#endif  // HAVE_X11
+
+#endif

+ 4 - 0
direct/src/plugin/p3d_plugin.h

@@ -131,6 +131,10 @@ typedef struct {
 #ifdef _WIN32
 #ifdef _WIN32
   HWND _hwnd;
   HWND _hwnd;
 #endif
 #endif
+#ifdef HAVE_X11
+  unsigned long _xwindow;
+  void *_xdisplay;
+#endif
 #ifdef __APPLE__
 #ifdef __APPLE__
   void *_nswindow;
   void *_nswindow;
 #endif
 #endif

+ 1 - 0
direct/src/plugin/p3d_plugin_composite1.cxx

@@ -18,4 +18,5 @@
 #include "p3dStringObject.cxx"
 #include "p3dStringObject.cxx"
 #include "p3dUndefinedObject.cxx"
 #include "p3dUndefinedObject.cxx"
 #include "p3dWinSplashWindow.cxx"
 #include "p3dWinSplashWindow.cxx"
+#include "p3dX11SplashWindow.cxx"
 #include "p3dWindowParams.cxx"
 #include "p3dWindowParams.cxx"

+ 6 - 0
direct/src/plugin_npapi/Sources.pp

@@ -12,6 +12,12 @@
 
 
   #define LOCAL_LIBS plugin_common
   #define LOCAL_LIBS plugin_common
 
 
+  // We need this because we don't
+  // include dtool_config.h.
+  #if $[HAVE_X11]
+    #define EXTRA_CDEFS HAVE_X11
+  #endif
+
   #define COMBINED_SOURCES \
   #define COMBINED_SOURCES \
     $[TARGET]_composite1.cxx
     $[TARGET]_composite1.cxx
 
 

+ 26 - 1
direct/src/plugin_npapi/ppInstance.cxx

@@ -923,24 +923,49 @@ send_window() {
   int y = _window.y;
   int y = _window.y;
 
 
   P3D_window_handle parent_window;
   P3D_window_handle parent_window;
-#ifdef _WIN32
   if (_window.type == NPWindowTypeWindow) {
   if (_window.type == NPWindowTypeWindow) {
     // We have a "windowed" plugin.  Parent our window to the one we
     // We have a "windowed" plugin.  Parent our window to the one we
     // were given.  In this case, we should also reset the offset to
     // 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
     // (0, 0), since the window we were given is already placed in the
     // right spot.
     // right spot.
+#ifdef _WIN32
     parent_window._hwnd = (HWND)(_window.window);
     parent_window._hwnd = (HWND)(_window.window);
+#endif
+#ifdef 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;
     x = 0;
     y = 0;
     y = 0;
   } else {
   } else {
     // We have a "windowless" plugin.  Parent our window directly to
     // We have a "windowless" plugin.  Parent our window directly to
     // the browser window.
     // the browser window.
+#ifdef _WIN32
     parent_window._hwnd = 0;
     parent_window._hwnd = 0;
     HWND hwnd;
     HWND hwnd;
     if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
     if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
                           &hwnd) == NPERR_NO_ERROR) {
                           &hwnd) == NPERR_NO_ERROR) {
       parent_window._hwnd = hwnd;
       parent_window._hwnd = hwnd;
     }
     }
+#endif
+#ifdef HAVE_X11
+    parent_window._xwindow = 0;
+    unsigned long win;
+    if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
+                          &win) == NPERR_NO_ERROR) {
+      parent_window._xwindow = win;
+    }
+#endif
+  }
+
+#ifdef HAVE_X11
+  // In the case of X11, grab the display as well.
+  parent_window._xdisplay = 0;
+  void* disp;
+  if (browser->getvalue(_npp_instance, NPNVxDisplay,
+                        &disp) == NPERR_NO_ERROR) {
+    parent_window._xdisplay = disp;
   }
   }
 #endif
 #endif
 
 

+ 11 - 1
direct/src/plugin_npapi/startup.cxx

@@ -66,7 +66,13 @@ request_ready(P3D_instance *instance) {
   // it within HandleEvent().  TODO: enable a timer to ensure we get
   // it within HandleEvent().  TODO: enable a timer to ensure we get
   // HandleEvent callbacks in a timely manner?  Or maybe we should
   // HandleEvent callbacks in a timely manner?  Or maybe we should
   // enable a one-shot timer in response to this asynchronous event?
   // enable a one-shot timer in response to this asynchronous event?
-#endif
+  
+#ifndef __APPLE__
+  // On Unix, HandleEvent isn't called, so we will do what it does
+  // right here. Not sure if this is right.
+  PPInstance::handle_request_loop();
+#endif  // __APPLE__
+#endif  // _WIN32
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -98,7 +104,11 @@ NP_GetValue(void*, NPPVariable variable, void* value) {
     case NPPVpluginDescriptionString:
     case NPPVpluginDescriptionString:
       *(const char **)value = "Runs 3-D games and interactive applets";
       *(const char **)value = "Runs 3-D games and interactive applets";
       break;
       break;
+    case NPPVpluginNeedsXEmbed:
+      *((PRBool *)value) = PR_FALSE;
+      break;
     default:
     default:
+      logfile << "Ignoring GetValue request " << variable << "\n" << flush;
       return NPERR_INVALID_PARAM;
       return NPERR_INVALID_PARAM;
   }
   }