Browse Source

allow resizing subprocess buffer

David Rose 16 years ago
parent
commit
6174ae7228

+ 24 - 14
direct/src/plugin/p3dInstance.cxx

@@ -221,14 +221,30 @@ set_wparams(const P3DWindowParams &wparams) {
     // to the browser.  Set up this mechanism.
     int x_size = _wparams.get_win_width();
     int y_size = _wparams.get_win_height();
-    if (_shared_fd == -1 && x_size != 0 && y_size != 0) {
-      _swbuffer = SubprocessWindowBuffer::new_buffer
-        (_shared_fd, _shared_mmap_size, _shared_filename, x_size, y_size);
-      if (_swbuffer != NULL) {
-        _reversed_buffer = new char[_swbuffer->get_framebuffer_size()];
+    if (x_size != 0 && y_size != 0) {
+      if (_swbuffer == NULL || _swbuffer->get_x_size() != x_size ||
+          _swbuffer->get_y_size() != y_size) {
+        // We need to open a new shared buffer.
+        if (_swbuffer != NULL) {
+          SubprocessWindowBuffer::destroy_buffer(_shared_fd, _shared_mmap_size,
+                                                 _shared_filename, _swbuffer);
+          _swbuffer = NULL;
+        }
+        if (_reversed_buffer != NULL) {
+          delete[] _reversed_buffer;
+          _reversed_buffer = NULL;
+        }
+
+        _swbuffer = SubprocessWindowBuffer::new_buffer
+          (_shared_fd, _shared_mmap_size, _shared_filename, x_size, y_size);
+        if (_swbuffer != NULL) {
+          _reversed_buffer = new char[_swbuffer->get_framebuffer_size()];
+        }
       }
 
-      xwparams->SetAttribute("subprocess_window", _shared_filename);
+      if (_swbuffer != NULL) {
+        xwparams->SetAttribute("subprocess_window", _shared_filename);
+      }
     }
 #endif   // __APPLE__
     
@@ -513,8 +529,6 @@ handle_event(P3D_event_data event) {
   swb_event._flags = 0;
   add_modifier_flags(swb_event._flags, er->modifiers);
 
-  bool keep_event = false;
-  
   switch (er->what) {
   case mouseDown:
   case mouseUp:
@@ -526,7 +540,6 @@ handle_event(P3D_event_data event) {
       } else {
         swb_event._type = SubprocessWindowBuffer::ET_button_down;
       }
-      keep_event = true;
       retval = true;
     }
     break;
@@ -544,7 +557,6 @@ handle_event(P3D_event_data event) {
       } else {
         swb_event._type = SubprocessWindowBuffer::ET_button_again;
       }
-      keep_event = true;
       retval = true;
     }
     break;
@@ -556,7 +568,6 @@ handle_event(P3D_event_data event) {
 
   case activateEvt:
     _mouse_active = ((er->modifiers & 1) != 0);
-    keep_event = true;
     break;
 
   default:
@@ -569,12 +580,10 @@ handle_event(P3D_event_data event) {
     swb_event._flags |= SubprocessWindowBuffer::EF_mouse_position | SubprocessWindowBuffer::EF_has_mouse;
   }
 
-  if (keep_event && _swbuffer != NULL) {
+  if (_swbuffer != NULL) {
     _swbuffer->add_event(swb_event);
   }
 
-#elif defined(HAVE_X11)
-
 #endif
   return retval;
 }
@@ -785,6 +794,7 @@ void P3DInstance::
 handle_notify_request(const string &message) {
   // We look for certain notify events that have particular meaning
   // to this instance.
+  nout << "Got notify: " << message << "\n" << flush;
   if (message == "onpythonload") {
     // Once Python is up and running, we can get the actual toplevel
     // object from the Python side, and merge it with our own.

+ 1 - 0
direct/src/plugin_npapi/make_osx_bundle.py

@@ -134,6 +134,7 @@ def buildDmg(startDir):
     fstartDir = Filename.fromOsSpecific(startDir)
     rootFilename = Filename(fstartDir, 'bundle')
     output = Filename(fstartDir, 'nppanda3d.dmg')
+    output.unlink()
     cmd = 'hdiutil create -fs HFS+ -srcfolder "%(dir)s" -volname "%(volname)s" "%(output)s"' % {
         'dir' : rootFilename.toOsSpecific(),
         'volname' : 'nppanda3d',

+ 2 - 0
direct/src/showutil/runp3d.py

@@ -304,6 +304,8 @@ class AppRunner(DirectObject):
                 wp.setOrigin(x, y)
             if width or height:
                 wp.setSize(width, height)
+            if subprocessWindow:
+                wp.setSubprocessWindow(subprocessWindow)
             base.win.requestProperties(wp)
             return
 

+ 128 - 42
panda/src/display/subprocessWindow.cxx

@@ -35,34 +35,24 @@ SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
                  const WindowProperties &win_prop,
                  int flags,
                  GraphicsStateGuardian *gsg,
-                 GraphicsOutput *host,
-                 const string &filename) :
+                 GraphicsOutput *host) :
   GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
 {
   GraphicsWindowInputDevice device =
     GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
   _input_devices.push_back(device);
 
-  // Create a buffer with the same properties as the window.
-  flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
-
-  GraphicsOutput *buffer = 
-    engine->make_output(pipe, name, 0, 
-                        fb_prop, win_prop, flags, gsg, host);
-  if (buffer != NULL) {
-    _buffer = DCAST(GraphicsBuffer, buffer);
-    // However, the buffer is not itself intended to be rendered.  We
-    // only render it indirectly, via callbacks in here.
-    _buffer->set_active(false);
-  }
+  // This will be an offscreen buffer that we use to render the actual
+  // contents.
+  _buffer = NULL;
 
-  // Now create a texture to receive the contents of the framebuffer
-  // from the buffer.
+  // Create a texture to receive the contents of the framebuffer from
+  // the offscreen buffer.
   _texture = new Texture(name);
 
   _fd = -1;
   _mmap_size = 0;
-  _filename = filename;
+  _filename = string();
   _swbuffer = NULL;
   _last_event_flags = 0;
 }
@@ -74,9 +64,7 @@ SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
 ////////////////////////////////////////////////////////////////////
 SubprocessWindow::
 ~SubprocessWindow() {
-  if (_buffer != NULL) {
-    _engine->remove_window(_buffer);
-  }
+  nassertv(_buffer == NULL);
   nassertv(_swbuffer == NULL);
 }
 
@@ -193,7 +181,9 @@ end_frame(FrameMode mode, Thread *current_thread) {
 void SubprocessWindow::
 begin_flip() {
   nassertv(_buffer != (GraphicsBuffer *)NULL);
-  nassertv(_swbuffer != NULL);
+  if (_swbuffer == NULL) {
+    return;
+  }
 
   RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(RTP_color));
   buffer = _gsg->get_render_buffer(_buffer->get_draw_buffer_type(),
@@ -233,6 +223,54 @@ begin_flip() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SubprocessWindow::set_properties_now
+//       Access: Public, Virtual
+//  Description: Applies the requested set of properties to the
+//               window, if possible, for instance to request a change
+//               in size or minimization status.
+//
+//               The window properties are applied immediately, rather
+//               than waiting until the next frame.  This implies that
+//               this method may *only* be called from within the
+//               window thread.
+//
+//               The properties that have been applied are cleared
+//               from the structure by this function; so on return,
+//               whatever remains in the properties structure are
+//               those that were unchanged for some reason (probably
+//               because the underlying interface does not support
+//               changing that property on an open window).
+////////////////////////////////////////////////////////////////////
+void SubprocessWindow::
+set_properties_now(WindowProperties &properties) {
+  if (properties.has_subprocess_window() && 
+      properties.get_subprocess_window() != _filename) {
+    // We're changing the subprocess buffer filename; that means we
+    // might as well completely close and re-open the window.
+    internal_close_window();
+
+    _properties.add_properties(properties);
+    properties.clear();
+
+    internal_open_window();
+    set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
+    throw_event(get_window_event(), this);
+    return;
+  }
+
+  GraphicsWindow::set_properties_now(properties);
+  if (!properties.is_any_specified()) {
+    // The base class has already handled this case.
+    return;
+  }
+
+  if (properties.has_subprocess_window()) {
+    // Redundant subprocess specification.
+    properties.clear_subprocess_window();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SubprocessWindow::close_window
 //       Access: Protected, Virtual
@@ -241,8 +279,46 @@ begin_flip() {
 ////////////////////////////////////////////////////////////////////
 void SubprocessWindow::
 close_window() {
+  internal_close_window();
+
+  WindowProperties properties;
+  properties.set_open(false);
+  properties.set_foreground(false);
+  system_changed_properties(properties);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubprocessWindow::open_window
+//       Access: Protected, Virtual
+//  Description: Opens the window right now.  Called from the window
+//               thread.  Returns true if the window is successfully
+//               opened, or false if there was a problem.
+////////////////////////////////////////////////////////////////////
+bool SubprocessWindow::
+open_window() {
+  if (!internal_open_window()) {
+    return false;
+  }
+
+  WindowProperties properties;
+  properties.set_open(true);
+  properties.set_foreground(true);
+  system_changed_properties(properties);
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubprocessWindow::internal_close_window
+//       Access: Private
+//  Description: Closes the "window" and resets the buffer, without
+//               changing the WindowProperties.
+////////////////////////////////////////////////////////////////////
+void SubprocessWindow::
+internal_close_window() {
   if (_swbuffer != NULL) {
-    SubprocessWindowBuffer::close_buffer(_fd, _mmap_size, _filename, _swbuffer);
+    SubprocessWindowBuffer::close_buffer
+      (_fd, _mmap_size, _filename.to_os_specific(), _swbuffer);
     _fd = -1;
     _filename = string();
 
@@ -252,28 +328,36 @@ close_window() {
   if (_buffer != NULL) {
     _buffer->request_close();
     _buffer->process_events();
+    _engine->remove_window(_buffer);
+    _buffer = NULL;
   }
 
   _is_valid = false;
-
-  WindowProperties properties;
-  properties.set_open(false);
-  properties.set_foreground(false);
-  system_changed_properties(properties);
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: SubprocessWindow::open_window
-//       Access: Protected, Virtual
-//  Description: Opens the window right now.  Called from the window
-//               thread.  Returns true if the window is successfully
-//               opened, or false if there was a problem.
+//     Function: SubprocessWindow::internal_open_window
+//       Access: Private
+//  Description: Opens the "window" and the associated offscreen
+//               buffer, without changing the WindowProperties.
 ////////////////////////////////////////////////////////////////////
 bool SubprocessWindow::
-open_window() {
-  nout << "open_window\n";
-  
-  if (_buffer != NULL) {
+internal_open_window() {
+  nassertr(_buffer == NULL, false);
+
+  // Create a buffer with the same properties as the window.
+  int flags = _creation_flags;
+  flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
+
+  GraphicsOutput *buffer = 
+    _engine->make_output(_pipe, _name, 0, _fb_properties, _properties, 
+                         flags, _gsg, _host);
+  if (buffer != NULL) {
+    _buffer = DCAST(GraphicsBuffer, buffer);
+    // However, the buffer is not itself intended to be rendered.  We
+    // only render it indirectly, via callbacks in here.
+    _buffer->set_active(false);
+
     _buffer->request_open();
     _buffer->process_events();
 
@@ -281,26 +365,28 @@ open_window() {
   }
 
   if (!_is_valid) {
+    display_cat.error()
+      << "Failed to open SubprocessWindowBuffer's internal offscreen buffer.\n";
     return false;
   }
 
   _gsg = _buffer->get_gsg();
+  _filename = _properties.get_subprocess_window();
 
-  _swbuffer = SubprocessWindowBuffer::open_buffer(_fd, _mmap_size, _filename);
+  _swbuffer = SubprocessWindowBuffer::open_buffer
+    (_fd, _mmap_size, _filename.to_os_specific());
 
   if (_swbuffer == NULL) {
     close(_fd);
     _fd = -1;
     _filename = string();
     _is_valid = false;
+    display_cat.error()
+      << "Failed to open SubprocessWindowBuffer's shared-memory buffer "
+      << _filename << "\n";
     return false;
   }
 
-  WindowProperties properties;
-  properties.set_open(true);
-  properties.set_foreground(true);
-  system_changed_properties(properties);
-
   return true;
 }
 

+ 8 - 3
panda/src/display/subprocessWindow.h

@@ -33,6 +33,7 @@
 #include "graphicsBuffer.h"
 #include "texture.h"
 #include "subprocessWindowBuffer.h"
+#include "filename.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : SubprocessWindow
@@ -55,8 +56,7 @@ public:
                    const WindowProperties &win_prop,
                    int flags,
                    GraphicsStateGuardian *gsg,
-                   GraphicsOutput *host,
-                   const string &filename);
+                   GraphicsOutput *host);
   virtual ~SubprocessWindow();
 
   virtual void process_events();
@@ -65,11 +65,16 @@ public:
   virtual void end_frame(FrameMode mode, Thread *current_thread);
   virtual void begin_flip();
 
+  virtual void set_properties_now(WindowProperties &properties);
+
 protected:
   virtual void close_window();
   virtual bool open_window();
 
 private:
+  void internal_close_window();
+  bool internal_open_window();
+
   ButtonHandle translate_key(int &keycode, int os_code, unsigned int flags) const;
   void transition_button(unsigned int flag, ButtonHandle button);
 
@@ -79,7 +84,7 @@ private:
 
   int _fd;
   size_t _mmap_size;
-  string _filename;
+  Filename _filename;
   SubprocessWindowBuffer *_swbuffer;
 
   unsigned int _last_event_flags;

+ 1 - 2
panda/src/osxdisplay/osxGraphicsPipe.cxx

@@ -237,8 +237,7 @@ make_output(const string &name,
 #ifdef SUPPORT_SUBPROCESS_WINDOW
     if (win_prop.has_subprocess_window()) {
       return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
-                                  flags, gsg, host,
-                                  win_prop.get_subprocess_window().to_os_specific());
+                                  flags, gsg, host);
     }
 #endif  // SUPPORT_SUBPROCESS_WINDOW
     return new osxGraphicsWindow(engine, this, name, fb_prop, win_prop,

+ 1 - 2
panda/src/tinydisplay/tinyOsxGraphicsPipe.cxx

@@ -238,8 +238,7 @@ make_output(const string &name,
 #ifdef SUPPORT_SUBPROCESS_WINDOW
     if (win_prop.has_subprocess_window()) {
       return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
-                                  flags, gsg, host,
-                                  win_prop.get_subprocess_window().to_os_specific());
+                                  flags, gsg, host);
     }
 #endif  // SUPPORT_SUBPROCESS_WINDOW
     return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,