diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 48b94080b0..f1c8ccc166 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/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. diff --git a/direct/src/plugin_npapi/make_osx_bundle.py b/direct/src/plugin_npapi/make_osx_bundle.py index ccc15e03f4..44e504b066 100755 --- a/direct/src/plugin_npapi/make_osx_bundle.py +++ b/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', diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index f1ae2bff98..a439cfafac 100755 --- a/direct/src/showutil/runp3d.py +++ b/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 diff --git a/panda/src/display/subprocessWindow.cxx b/panda/src/display/subprocessWindow.cxx index 5ef077eba0..cd47d6b8ee 100644 --- a/panda/src/display/subprocessWindow.cxx +++ b/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); + // This will be an offscreen buffer that we use to render the actual + // contents. + _buffer = NULL; - 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); - } - - // 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,20 +279,7 @@ begin_flip() { //////////////////////////////////////////////////////////////////// void SubprocessWindow:: close_window() { - if (_swbuffer != NULL) { - SubprocessWindowBuffer::close_buffer(_fd, _mmap_size, _filename, _swbuffer); - _fd = -1; - _filename = string(); - - _swbuffer = NULL; - } - - if (_buffer != NULL) { - _buffer->request_close(); - _buffer->process_events(); - } - - _is_valid = false; + internal_close_window(); WindowProperties properties; properties.set_open(false); @@ -271,28 +296,7 @@ close_window() { //////////////////////////////////////////////////////////////////// bool SubprocessWindow:: open_window() { - nout << "open_window\n"; - - if (_buffer != NULL) { - _buffer->request_open(); - _buffer->process_events(); - - _is_valid = _buffer->is_valid(); - } - - if (!_is_valid) { - return false; - } - - _gsg = _buffer->get_gsg(); - - _swbuffer = SubprocessWindowBuffer::open_buffer(_fd, _mmap_size, _filename); - - if (_swbuffer == NULL) { - close(_fd); - _fd = -1; - _filename = string(); - _is_valid = false; + if (!internal_open_window()) { return false; } @@ -304,6 +308,88 @@ open_window() { 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.to_os_specific(), _swbuffer); + _fd = -1; + _filename = string(); + + _swbuffer = NULL; + } + + if (_buffer != NULL) { + _buffer->request_close(); + _buffer->process_events(); + _engine->remove_window(_buffer); + _buffer = NULL; + } + + _is_valid = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: SubprocessWindow::internal_open_window +// Access: Private +// Description: Opens the "window" and the associated offscreen +// buffer, without changing the WindowProperties. +//////////////////////////////////////////////////////////////////// +bool SubprocessWindow:: +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(); + + _is_valid = _buffer->is_valid(); + } + + 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.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; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: SubprocessWindow::translate_key // Access: Private diff --git a/panda/src/display/subprocessWindow.h b/panda/src/display/subprocessWindow.h index c6445fcdc3..b1975f9241 100644 --- a/panda/src/display/subprocessWindow.h +++ b/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; diff --git a/panda/src/osxdisplay/osxGraphicsPipe.cxx b/panda/src/osxdisplay/osxGraphicsPipe.cxx index f08d430de7..cf70a19101 100644 --- a/panda/src/osxdisplay/osxGraphicsPipe.cxx +++ b/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, diff --git a/panda/src/tinydisplay/tinyOsxGraphicsPipe.cxx b/panda/src/tinydisplay/tinyOsxGraphicsPipe.cxx index 7c3076e2c1..eeb5cc135c 100644 --- a/panda/src/tinydisplay/tinyOsxGraphicsPipe.cxx +++ b/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,