Browse Source

osx splash window

David Rose 16 years ago
parent
commit
72da887fd5

+ 2 - 0
direct/src/plugin/Sources.pp

@@ -43,6 +43,7 @@
     p3dMultifileReader.h p3dMultifileReader.I \
     p3dMultifileReader.h p3dMultifileReader.I \
     p3dNoneObject.h \
     p3dNoneObject.h \
     p3dObject.h p3dObject.I \
     p3dObject.h p3dObject.I \
+    p3dOsxSplashWindow.h p3dOsxSplashWindow.I \
     p3dPackage.h p3dPackage.I \
     p3dPackage.h p3dPackage.I \
     p3dPythonObject.h \
     p3dPythonObject.h \
     p3dReferenceCount.h p3dReferenceCount.I \
     p3dReferenceCount.h p3dReferenceCount.I \
@@ -71,6 +72,7 @@
     p3dMultifileReader.cxx \
     p3dMultifileReader.cxx \
     p3dNoneObject.cxx \
     p3dNoneObject.cxx \
     p3dObject.cxx \
     p3dObject.cxx \
+    p3dOsxSplashWindow.cxx \
     p3dPackage.cxx \
     p3dPackage.cxx \
     p3dPythonObject.cxx \
     p3dPythonObject.cxx \
     p3dReferenceCount.cxx \
     p3dReferenceCount.cxx \

+ 24 - 4
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 "p3dOsxSplashWindow.h"
 #include "p3dX11SplashWindow.h"
 #include "p3dX11SplashWindow.h"
 #include "p3dObject.h"
 #include "p3dObject.h"
 #include "p3dToplevelObject.h"
 #include "p3dToplevelObject.h"
@@ -34,6 +35,8 @@
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 typedef P3DWinSplashWindow SplashWindowType;
 typedef P3DWinSplashWindow SplashWindowType;
+#elif defined(__APPLE__)
+typedef P3DOsxSplashWindow SplashWindowType;
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
 typedef P3DX11SplashWindow SplashWindowType;
 typedef P3DX11SplashWindow SplashWindowType;
 #else
 #else
@@ -153,8 +156,8 @@ set_fparams(const P3DFileParams &fparams) {
   // Generate a special notification: onpluginload, indicating the
   // Generate a special notification: onpluginload, indicating the
   // plugin has read its parameters and is ready to be queried (even
   // plugin has read its parameters and is ready to be queried (even
   // if Python has not yet started).  This notification is special
   // if Python has not yet started).  This notification is special
-  // because it is the only one generated at this level; the rest of
-  // them are generated by the Python code, once that is running.
+  // because it generated at the C++ level, here; most of them are
+  // generated by the Python code, once that is running.
   P3D_request *request = new P3D_request;
   P3D_request *request = new P3D_request;
   request->_request_type = P3D_RT_notify;
   request->_request_type = P3D_RT_notify;
   request->_request._notify._message = strdup("onpluginload");
   request->_request._notify._message = strdup("onpluginload");
@@ -475,6 +478,10 @@ feed_url_stream(int unique_id,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DInstance::
 void P3DInstance::
 handle_event(P3D_event_data event) {
 handle_event(P3D_event_data event) {
+  if (_splash_window != NULL) {
+    _splash_window->handle_event(event);
+  }
+
 #ifdef _WIN32
 #ifdef _WIN32
   // This function is not used in Win32 and does nothing.
   // This function is not used in Win32 and does nothing.
 
 
@@ -643,6 +650,20 @@ request_stop() {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::request_refresh
+//       Access: Public
+//  Description: Asks the host to refresh the plugin window.  This is
+//               only relevant for windowless plugins, for instance,
+//               the way OSX plugins always run.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+request_refresh() {
+  P3D_request *request = new P3D_request;
+  request->_request_type = P3D_RT_refresh;
+  add_baked_request(request);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::make_xml
 //     Function: P3DInstance::make_xml
 //       Access: Public
 //       Access: Public
@@ -971,8 +992,7 @@ install_progress(P3DPackage *package, double progress) {
 void P3DInstance::
 void P3DInstance::
 paint_window() {
 paint_window() {
 #ifdef __APPLE__
 #ifdef __APPLE__
-  if (_swbuffer == NULL) {
-    nout << "no _swbuffer\n";
+  if (_swbuffer == NULL || !_instance_window_opened) {
     return;
     return;
   }
   }
 
 

+ 1 - 0
direct/src/plugin/p3dInstance.h

@@ -82,6 +82,7 @@ public:
   void start_download(P3DDownload *download);
   void start_download(P3DDownload *download);
   inline bool is_started() const;
   inline bool is_started() const;
   void request_stop();
   void request_stop();
+  void request_refresh();
 
 
   TiXmlElement *make_xml();
   TiXmlElement *make_xml();
 
 

+ 14 - 0
direct/src/plugin/p3dOsxSplashWindow.I

@@ -0,0 +1,14 @@
+// Filename: p3dOsxSplashWindow.I
+// Created by:  drose (16Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+

+ 264 - 0
direct/src/plugin/p3dOsxSplashWindow.cxx

@@ -0,0 +1,264 @@
+// Filename: p3dOsxSplashWindow.cxx
+// Created by:  drose (16Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "p3dOsxSplashWindow.h"
+
+#ifdef __APPLE__
+
+#include <Carbon/Carbon.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DOsxSplashWindow::
+P3DOsxSplashWindow(P3DInstance *inst) : 
+  P3DSplashWindow(inst)
+{
+  _image = NULL;
+  _image_data = NULL;
+  _install_progress = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DOsxSplashWindow::
+~P3DOsxSplashWindow() {
+  if (_image != NULL) {
+    DisposeGWorld(_image);
+  }
+
+  if (_image_data != NULL) {
+    delete[] _image_data;
+    _image_data = NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::set_image_filename
+//       Access: Public, Virtual
+//  Description: Specifies the name of a JPEG image file that is
+//               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 P3DOsxSplashWindow::
+set_image_filename(const string &image_filename,
+                   bool image_filename_temp) {
+  int num_channels, row_stride;
+  string data;
+  if (!read_image(image_filename, image_filename_temp, 
+                  _image_height, _image_width, num_channels, row_stride,
+                  data)) {
+    return;
+  }
+
+  QDErr err;
+  Rect src_rect = { 0, 0, _image_height, _image_width };
+
+  if (_image != NULL) {
+    DisposeGWorld(_image);
+    _image = NULL;
+  }
+
+  if (_image_data != NULL) {
+    delete[] _image_data;
+    _image_data = NULL;
+  }
+
+  // Now we need to copy from the RGB source image into the BGRA target image.
+  int new_row_stride = _image_width * 4;
+  _image_data = new char[new_row_stride * _image_height];
+  for (int yi = 0; yi < _image_height; ++yi) {
+    char *dest = _image_data + yi * new_row_stride;
+    const char *source = data.data() + yi * row_stride;
+    for (int xi = 0; xi < _image_width; ++xi) {
+      char r = source[0];
+      char g = source[1];
+      char b = source[2];
+#ifndef __BIG_ENDIAN__
+      // Little-endian.
+      dest[0] = b;
+      dest[1] = g;
+      dest[2] = r;
+      dest[3] = 0xff;
+#else  // __BIG_ENDIAN__
+      // Big-endian.
+      dest[0] = 0xff;
+      dest[1] = r;
+      dest[2] = g;
+      dest[3] = b;
+#endif  // __BIG_ENDIAN__
+      source += 3;
+      dest += 4;
+    }
+  }
+
+  err = NewGWorldFromPtr(&_image, k32BGRAPixelFormat, &src_rect, 0, 0, 0, 
+                         _image_data, new_row_stride);
+  if (err != noErr) {
+    nout << " error in NewGWorldFromPtr, called from set_image_filename()\n";
+    return;
+  }
+
+  _inst->request_refresh();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::set_install_label
+//       Access: Public, Virtual
+//  Description: Specifies the text that is displayed above the
+//               install progress bar.
+////////////////////////////////////////////////////////////////////
+void P3DOsxSplashWindow::
+set_install_label(const string &install_label) {
+  _install_label = install_label;
+  _inst->request_refresh();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::set_install_progress
+//       Access: Public, Virtual
+//  Description: Moves the install progress bar from 0.0 to 1.0.
+////////////////////////////////////////////////////////////////////
+void P3DOsxSplashWindow::
+set_install_progress(double install_progress) {
+  if ((int)(install_progress * 500.0) != (int)(_install_progress * 500.0)) {
+    // Only request a refresh if we're changing substantially.
+    _inst->request_refresh();
+  }
+  _install_progress = install_progress;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::handle_event
+//       Access: Public, Virtual
+//  Description: Deals with the event callback from the OS window
+//               system.
+////////////////////////////////////////////////////////////////////
+void P3DOsxSplashWindow::
+handle_event(P3D_event_data event) {
+  EventRecord *er = event._event;
+  if (er->what == updateEvt) {
+    paint_window();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DOsxSplashWindow::paint_window
+//       Access: Private
+//  Description: Redraws the current splash window.
+////////////////////////////////////////////////////////////////////
+void P3DOsxSplashWindow::
+paint_window() {
+  cerr << "paint_window, _image = " << _image << ", label = " << _install_label << "\n";
+  GrafPtr out_port = _wparams.get_parent_window()._port;
+  GrafPtr portSave = NULL;
+  Boolean portChanged = QDSwapPort(out_port, &portSave);
+
+  int win_width = _wparams.get_win_width();
+  int win_height = _wparams.get_win_height();
+
+  Rect r = { 0, 0, win_height, win_width }; 
+  ClipRect(&r);
+
+  EraseRect(&r);
+
+  if (_image != NULL) {
+    Rect src_rect = { 0, 0, _image_height, _image_width };
+    Rect dest_rect;
+    
+    // Determine the relative size of image and window.
+    int win_cx = win_width / 2;
+    int win_cy = win_height / 2;
+    
+    if (_image_width <= win_width && _image_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 - _image_width / 2;
+      int p_y = win_cy - _image_height / 2;
+
+      dest_rect.left = p_x;
+      dest_rect.top = p_y;
+      dest_rect.right = p_x + _image_width;
+      dest_rect.bottom = p_y + _image_height;
+      
+    } else {
+      // The bitmap is larger than the window; scale it down.
+      double x_scale = (double)win_width / (double)_image_width;
+      double y_scale = (double)win_height / (double)_image_height;
+      double scale = min(x_scale, y_scale);
+      int sc_width = (int)(_image_width * scale);
+      int sc_height = (int)(_image_height * scale);
+      
+      int p_x = win_cx - sc_width / 2;
+      int p_y = win_cy - sc_height / 2;
+
+      dest_rect.left = p_x;
+      dest_rect.top = p_y;
+      dest_rect.right = p_x + sc_width;
+      dest_rect.bottom = p_y + sc_height;
+    }
+
+    CopyBits(GetPortBitMapForCopyBits(_image), 
+             GetPortBitMapForCopyBits(out_port), 
+             &src_rect, &dest_rect, srcCopy, 0);
+  }
+
+  int bar_width = min((int)(win_width * 0.6), 400);
+  int bar_height = min((int)(win_height * 0.1), 24);
+  int bar_x = (win_width - bar_width) / 2;
+  int bar_y = (win_height - bar_height * 2);
+
+  int progress = bar_x + 1 + (int)((bar_width - 2) * _install_progress);
+
+  Rect rbar = { bar_y, bar_x, bar_y + bar_height, bar_x + bar_width };
+  Rect rneed = { bar_y + 1, progress + 1, bar_y + bar_height - 1, bar_x + bar_width - 1 };
+  Rect rdone = { bar_y + 1, bar_x + 1, bar_y + bar_height - 1, progress };
+  FrameRect(&rbar);
+  PaintRect(&rdone);
+  EraseRect(&rneed);
+
+  TextFont(0);
+  TextFace(bold);
+  TextMode(srcOr);
+  TextSize(0);
+
+  Point numer, denom;
+  FontInfo font_info;
+  StdTxMeas(_install_label.size(), _install_label.data(), &numer, &denom, &font_info);
+
+  int text_width = TextWidth(_install_label.data(), 0, _install_label.size());
+  int text_x = (win_width - text_width) / 2;
+  int text_y = bar_y - font_info.descent - 8;
+
+  Rect rtext = { text_y - font_info.ascent - 2, text_x - 2, 
+                 text_y + font_info.descent + 2, text_x + text_width + 2 }; 
+  EraseRect(&rtext);
+
+  MoveTo(text_x, text_y);
+  DrawText(_install_label.data(), 0, _install_label.size());
+
+  if (portChanged) {
+    QDSwapPort(portSave, NULL);
+  }
+}
+
+
+#endif  // __APPLE__

+ 59 - 0
direct/src/plugin/p3dOsxSplashWindow.h

@@ -0,0 +1,59 @@
+// Filename: p3dOsxSplashWindow.h
+// Created by:  drose (16Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 P3DOSXSPLASHWINDOW_H
+#define P3DOSXSPLASHWINDOW_H
+
+#include "p3d_plugin_common.h"
+
+#ifdef __APPLE__
+
+#include "p3dSplashWindow.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DOsxSplashWindow
+// Description : This is the OSX implementation of the
+//               initial-download window.
+////////////////////////////////////////////////////////////////////
+class P3DOsxSplashWindow : public P3DSplashWindow {
+public:
+  P3DOsxSplashWindow(P3DInstance *inst);
+  virtual ~P3DOsxSplashWindow();
+
+  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);
+
+  virtual void handle_event(P3D_event_data event);
+
+private:
+  void paint_window();
+
+private:
+  GWorldPtr _image;
+  char *_image_data;
+  int _image_height, _image_width;
+
+  string _install_label;
+  double _install_progress;
+};
+
+#include "p3dOsxSplashWindow.I"
+
+#endif  // __APPLE__
+
+#endif

+ 10 - 0
direct/src/plugin/p3dSplashWindow.cxx

@@ -110,6 +110,16 @@ void P3DSplashWindow::
 set_install_progress(double install_progress) {
 set_install_progress(double install_progress) {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::handle_event
+//       Access: Public, Virtual
+//  Description: Deals with the event callback from the OS window
+//               system.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+handle_event(P3D_event_data event) {
+}
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::read_image
 //     Function: P3DSplashWindow::read_image

+ 2 - 0
direct/src/plugin/p3dSplashWindow.h

@@ -47,6 +47,8 @@ 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);
 
 
+  virtual void handle_event(P3D_event_data event);
+
   void setup_splash_image();
   void setup_splash_image();
 
 
 protected:
 protected:

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

@@ -630,6 +630,7 @@ typedef enum {
   P3D_RT_get_url,
   P3D_RT_get_url,
   P3D_RT_post_url,
   P3D_RT_post_url,
   P3D_RT_notify,
   P3D_RT_notify,
+  P3D_RT_refresh,
 } P3D_request_type;
 } P3D_request_type;
 
 
 /* Structures corresponding to the request types in the above enum. */
 /* Structures corresponding to the request types in the above enum. */
@@ -673,6 +674,12 @@ typedef struct {
   const char *_message;
   const char *_message;
 } P3D_request_notify;
 } P3D_request_notify;
 
 
+/* A refresh request.  The instance would like to get a repaint event
+   on its own window.  Only relevant for windowless plugins, e.g. on
+   OSX. */
+typedef struct {
+} P3D_request_refresh;
+
 /* This is the overall structure that represents a single request.  It
 /* This is the overall structure that represents a single request.  It
    is returned by P3D_instance_get_request(). */
    is returned by P3D_instance_get_request(). */
 typedef struct {
 typedef struct {
@@ -683,6 +690,7 @@ typedef struct {
     P3D_request_get_url _get_url;
     P3D_request_get_url _get_url;
     P3D_request_post_url _post_url;
     P3D_request_post_url _post_url;
     P3D_request_notify _notify;
     P3D_request_notify _notify;
+    P3D_request_refresh _refresh;
   } _request;
   } _request;
 } P3D_request;
 } P3D_request;
 
 

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

@@ -13,6 +13,7 @@
 #include "p3dMultifileReader.cxx"
 #include "p3dMultifileReader.cxx"
 #include "p3dNoneObject.cxx"
 #include "p3dNoneObject.cxx"
 #include "p3dObject.cxx"
 #include "p3dObject.cxx"
+#include "p3dOsxSplashWindow.cxx"
 #include "p3dPackage.cxx"
 #include "p3dPackage.cxx"
 #include "p3dPythonObject.cxx"
 #include "p3dPythonObject.cxx"
 #include "p3dReferenceCount.cxx"
 #include "p3dReferenceCount.cxx"

+ 19 - 9
direct/src/plugin_npapi/ppInstance.cxx

@@ -52,6 +52,7 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
   _started_instance_data = false;
   _started_instance_data = false;
   _got_instance_data = false;
   _got_instance_data = false;
   _got_window = false;
   _got_window = false;
+  _python_window_open = false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -430,8 +431,23 @@ handle_request(P3D_request *request) {
     break;
     break;
 
 
   case P3D_RT_notify:
   case P3D_RT_notify:
-    // We can ignore notifies, since these are handled by the core
-    // API.
+    // We mostly ignore notifies, since these are handled by the core
+    // API.  But we do check for the "onwindowopen" notify, at which
+    // point we start spamming the refresh requests.
+    if (strcmp(request->_request._notify._message, "onwindowopen") == 0) {
+      _python_window_open = true;
+      if (_got_window) {
+        NPRect rect = { 0, 0, _window.height, _window.width };
+        browser->invalidaterect(_npp_instance, &rect);
+      }
+    }
+    break;
+
+  case P3D_RT_refresh:
+    if (_got_window) {
+      NPRect rect = { 0, 0, _window.height, _window.width };
+      browser->invalidaterect(_npp_instance, &rect);
+    }
     break;
     break;
 
 
   default:
   default:
@@ -472,8 +488,7 @@ handle_event(void *event) {
     // is going on.  Great; we'll take advantage of it to invalidate
     // is going on.  Great; we'll take advantage of it to invalidate
     // the instance rectangle, which will cause updateEvt to be
     // the instance rectangle, which will cause updateEvt to be
     // triggered (if the instance is still onscreen).
     // triggered (if the instance is still onscreen).
-
-    if (_got_window) {
+    if (_got_window && _python_window_open) {
       NPRect rect = { 0, 0, _window.height, _window.width };
       NPRect rect = { 0, 0, _window.height, _window.width };
       browser->invalidaterect(_npp_instance, &rect);
       browser->invalidaterect(_npp_instance, &rect);
     }
     }
@@ -612,11 +627,6 @@ variant_to_p3dobj(const NPVariant *variant) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PPInstance::
 void PPInstance::
 request_ready(P3D_instance *instance) {
 request_ready(P3D_instance *instance) {
-  logfile
-    << "request_ready in " << instance
-    //    << " thread = " << GetCurrentThreadId()
-    << "\n" << flush;
-
   PPInstance *inst = (PPInstance *)(instance->_user_data);
   PPInstance *inst = (PPInstance *)(instance->_user_data);
   assert(inst != NULL);
   assert(inst != NULL);
 
 

+ 2 - 0
direct/src/plugin_npapi/ppInstance.h

@@ -104,6 +104,8 @@ private:
   LONG_PTR _orig_window_proc;
   LONG_PTR _orig_window_proc;
 #endif  // _WIN32
 #endif  // _WIN32
 
 
+  bool _python_window_open;
+
   PPPandaObject *_script_object;
   PPPandaObject *_script_object;
 
 
   P3D_instance *_p3d_inst;
   P3D_instance *_p3d_inst;

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

@@ -329,7 +329,7 @@ NPP_Print(NPP instance, NPPrint *platformPrint) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int16
 int16
 NPP_HandleEvent(NPP instance, void *event) {
 NPP_HandleEvent(NPP instance, void *event) {
-  logfile << "HandleEvent\n" << flush;
+  //  logfile << "HandleEvent\n" << flush;
 
 
   PPInstance *inst = (PPInstance *)(instance->pdata);
   PPInstance *inst = (PPInstance *)(instance->pdata);
   assert(inst != NULL);
   assert(inst != NULL);