mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
embed plugin windows within OSX browsers properly
This commit is contained in:
parent
37e76f402d
commit
9fa212a48a
@ -6,6 +6,8 @@
|
||||
#define USE_PACKAGES tinyxml openssl zlib jpeg x11
|
||||
#define TARGET p3d_plugin
|
||||
#define LIB_PREFIX
|
||||
|
||||
#define OTHER_LIBS subprocbuffer
|
||||
|
||||
// We need this because we don't
|
||||
// include dtool_config.h.
|
||||
|
@ -39,7 +39,7 @@ inline HandleStream::
|
||||
// output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void HandleStream::
|
||||
open_read(Handle handle) {
|
||||
open_read(FHandle handle) {
|
||||
clear((ios::iostate)0);
|
||||
_buf.open_read(handle);
|
||||
if (!_buf.is_open_read()) {
|
||||
@ -55,7 +55,7 @@ open_read(Handle handle) {
|
||||
// output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void HandleStream::
|
||||
open_write(Handle handle) {
|
||||
open_write(FHandle handle) {
|
||||
clear((ios::iostate)0);
|
||||
_buf.open_write(handle);
|
||||
if (!_buf.is_open_write()) {
|
||||
|
@ -29,8 +29,8 @@ public:
|
||||
inline HandleStream();
|
||||
inline ~HandleStream();
|
||||
|
||||
inline void open_read(Handle handle);
|
||||
inline void open_write(Handle handle);
|
||||
inline void open_read(FHandle handle);
|
||||
inline void open_write(FHandle handle);
|
||||
inline void close();
|
||||
|
||||
private:
|
||||
|
@ -69,7 +69,7 @@ HandleStreamBuf::
|
||||
// output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HandleStreamBuf::
|
||||
open_read(Handle handle) {
|
||||
open_read(FHandle handle) {
|
||||
close();
|
||||
|
||||
_handle = handle;
|
||||
@ -84,7 +84,7 @@ open_read(Handle handle) {
|
||||
// output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HandleStreamBuf::
|
||||
open_write(Handle handle) {
|
||||
open_write(FHandle handle) {
|
||||
close();
|
||||
|
||||
_handle = handle;
|
||||
|
@ -17,10 +17,10 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
typedef HANDLE Handle;
|
||||
typedef HANDLE FHandle;
|
||||
#else
|
||||
// On POSIX, we use a file descriptor as a "handle".
|
||||
typedef int Handle;
|
||||
typedef int FHandle;
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
@ -37,8 +37,8 @@ public:
|
||||
HandleStreamBuf();
|
||||
virtual ~HandleStreamBuf();
|
||||
|
||||
void open_read(Handle handle);
|
||||
void open_write(Handle handle);
|
||||
void open_read(FHandle handle);
|
||||
void open_write(FHandle handle);
|
||||
bool is_open_read() const;
|
||||
bool is_open_write() const;
|
||||
void close();
|
||||
@ -56,7 +56,7 @@ private:
|
||||
bool _is_open_read;
|
||||
bool _is_open_write;
|
||||
|
||||
Handle _handle;
|
||||
FHandle _handle;
|
||||
|
||||
char *_buffer;
|
||||
};
|
||||
|
@ -69,6 +69,7 @@ P3D_instance_get_request_func *P3D_instance_get_request;
|
||||
P3D_check_request_func *P3D_check_request;
|
||||
P3D_request_finish_func *P3D_request_finish;
|
||||
P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream;
|
||||
P3D_instance_handle_event_func *P3D_instance_handle_event;
|
||||
|
||||
#ifdef _WIN32
|
||||
static HMODULE module = NULL;
|
||||
@ -206,6 +207,7 @@ load_plugin(const string &p3d_plugin_filename) {
|
||||
P3D_check_request = (P3D_check_request_func *)get_func(module, "P3D_check_request");
|
||||
P3D_request_finish = (P3D_request_finish_func *)get_func(module, "P3D_request_finish");
|
||||
P3D_instance_feed_url_stream = (P3D_instance_feed_url_stream_func *)get_func(module, "P3D_instance_feed_url_stream");
|
||||
P3D_instance_handle_event = (P3D_instance_handle_event_func *)get_func(module, "P3D_instance_handle_event");
|
||||
|
||||
#undef get_func
|
||||
|
||||
@ -244,7 +246,8 @@ load_plugin(const string &p3d_plugin_filename) {
|
||||
P3D_instance_get_request == NULL ||
|
||||
P3D_check_request == NULL ||
|
||||
P3D_request_finish == NULL ||
|
||||
P3D_instance_feed_url_stream == NULL) {
|
||||
P3D_instance_feed_url_stream == NULL ||
|
||||
P3D_instance_handle_event == NULL) {
|
||||
|
||||
cerr
|
||||
<< "Some function pointers not found:"
|
||||
@ -283,6 +286,7 @@ load_plugin(const string &p3d_plugin_filename) {
|
||||
<< "\nP3D_check_request = " << P3D_check_request
|
||||
<< "\nP3D_request_finish = " << P3D_request_finish
|
||||
<< "\nP3D_instance_feed_url_stream = " << P3D_instance_feed_url_stream
|
||||
<< "\nP3D_instance_handle_event = " << P3D_instance_handle_event
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
@ -376,6 +380,7 @@ unload_dso() {
|
||||
P3D_check_request = NULL;
|
||||
P3D_request_finish = NULL;
|
||||
P3D_instance_feed_url_stream = NULL;
|
||||
P3D_instance_handle_event = NULL;
|
||||
|
||||
plugin_loaded = false;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ extern P3D_instance_get_request_func *P3D_instance_get_request;
|
||||
extern P3D_check_request_func *P3D_check_request;
|
||||
extern P3D_request_finish_func *P3D_request_finish;
|
||||
extern P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream;
|
||||
extern P3D_instance_handle_event_func *P3D_instance_handle_event;
|
||||
|
||||
string get_plugin_basename();
|
||||
bool load_plugin(const string &p3d_plugin_filename);
|
||||
|
@ -27,15 +27,17 @@
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/mman.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef P3DWinSplashWindow SplashWindowType;
|
||||
#else
|
||||
#ifdef HAVE_X11
|
||||
#elif defined(HAVE_X11)
|
||||
typedef P3DX11SplashWindow SplashWindowType;
|
||||
#else
|
||||
typedef P3DSplashWindow SplashWindowType;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::Constructor
|
||||
@ -63,6 +65,13 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) :
|
||||
_instance_window_opened = false;
|
||||
_requested_stop = false;
|
||||
|
||||
#ifdef __APPLE__
|
||||
_shared_fd = -1;
|
||||
_shared_mmap_size = 0;
|
||||
_swbuffer = NULL;
|
||||
_reversed_buffer = NULL;
|
||||
#endif // __APPLE__
|
||||
|
||||
// Set some initial properties.
|
||||
_panda_script_object->set_float_property("downloadProgress", 0.0);
|
||||
}
|
||||
@ -95,6 +104,19 @@ P3DInstance::
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
DESTROY_LOCK(_request_lock);
|
||||
|
||||
// TODO: empty _raw_requests and _baked_requests queues, and
|
||||
@ -184,6 +206,24 @@ set_wparams(const P3DWindowParams &wparams) {
|
||||
xcommand->SetAttribute("cmd", "setup_window");
|
||||
xcommand->SetAttribute("instance_id", get_instance_id());
|
||||
TiXmlElement *xwparams = _wparams.make_xml();
|
||||
|
||||
#ifdef __APPLE__
|
||||
// On Mac, we have to communicate the results of the rendering
|
||||
// back via shared memory, instead of directly parenting windows
|
||||
// to the browser. Set up this mechanism.
|
||||
int x_size = _wparams.get_win_width();
|
||||
int y_size = _wparams.get_win_height();
|
||||
nout << "size = " << x_size << " * " << y_size << "\n" << flush;
|
||||
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()];
|
||||
}
|
||||
|
||||
xwparams->SetAttribute("subprocess_window", _shared_filename);
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
@ -425,6 +465,85 @@ feed_url_stream(int unique_id,
|
||||
return download_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::handle_event
|
||||
// Access: Public
|
||||
// Description: Responds to the os-generated window event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
handle_event(P3D_event_data event) {
|
||||
#ifdef _WIN32
|
||||
// This function is not used in Win32 and does nothing.
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
EventRecord *er = event._event;
|
||||
|
||||
switch (er->what) {
|
||||
case nullEvent:
|
||||
break;
|
||||
|
||||
case mouseDown:
|
||||
case mouseUp:
|
||||
{
|
||||
Point pt = er->where;
|
||||
GlobalToLocal(&pt);
|
||||
P3D_window_handle window = _wparams.get_parent_window();
|
||||
cerr << "mouse " << pt.h << " " << pt.v << "\n";
|
||||
if (_swbuffer != NULL) {
|
||||
SubprocessWindowBuffer::Event swb_event;
|
||||
swb_event._up = (er->what == mouseUp);
|
||||
swb_event._x = pt.h;
|
||||
swb_event._y = pt.v;
|
||||
_swbuffer->add_event(swb_event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case keyDown:
|
||||
case keyUp:
|
||||
case autoKey:
|
||||
cerr << "keycode: " << (er->message & 0xffff) << "\n";
|
||||
break;
|
||||
|
||||
case updateEvt:
|
||||
paint_window();
|
||||
break;
|
||||
|
||||
case activateEvt:
|
||||
cerr << "activate window: " << er->message << "\n";
|
||||
break;
|
||||
|
||||
case diskEvt:
|
||||
break;
|
||||
|
||||
case osEvt:
|
||||
if ((er->message & 0xf0000000) == suspendResumeMessage) {
|
||||
if (er->message & 1) {
|
||||
cerr << "suspend\n";
|
||||
} else {
|
||||
cerr << "resume\n";
|
||||
}
|
||||
} else if ((er->message & 0xf0000000) == mouseMovedMessage) {
|
||||
cerr << "mouse moved\n";
|
||||
} else {
|
||||
cerr << "unhandled osEvt: " << hex << er->message << dec << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case kHighLevelEvent:
|
||||
cerr << "high level: " << er->message << "\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << "unhandled event: " << er->what << ", " << er->message << "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::add_package
|
||||
// Access: Public
|
||||
@ -811,6 +930,81 @@ install_progress(P3DPackage *package, double progress) {
|
||||
_panda_script_object->set_float_property("downloadProgress", progress);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::paint_window
|
||||
// Access: Private
|
||||
// Description: Actually paints the rendered image to the browser
|
||||
// window. This is only implemented (and needed) for
|
||||
// OSX, where the child process isn't allowed to do it
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
paint_window() {
|
||||
#ifdef __APPLE__
|
||||
if (_swbuffer == NULL) {
|
||||
nout << "no _swbuffer\n";
|
||||
return;
|
||||
}
|
||||
|
||||
QDErr err;
|
||||
|
||||
// blit rendered framebuffer into window backing store
|
||||
int x_size = min(_wparams.get_win_width(), _swbuffer->get_x_size());
|
||||
int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
|
||||
Rect src_rect = {0, 0, y_size, x_size};
|
||||
Rect ddrc_rect = {0, 0, y_size, x_size};
|
||||
|
||||
size_t rowsize = _swbuffer->get_row_size();
|
||||
|
||||
if (_swbuffer->ready_for_read()) {
|
||||
// Copy the new framebuffer image from the child process.
|
||||
const void *framebuffer = _swbuffer->open_read_framebuffer();
|
||||
|
||||
// We have to reverse the image vertically first (different
|
||||
// conventions between Panda and Mac).
|
||||
for (int yi = 0; yi < y_size; ++yi) {
|
||||
memcpy(_reversed_buffer + (y_size - 1 - yi) * rowsize,
|
||||
(char *)framebuffer + yi * rowsize,
|
||||
rowsize);
|
||||
}
|
||||
|
||||
_swbuffer->close_read_framebuffer();
|
||||
|
||||
} else {
|
||||
// No frame ready. Just re-paint the frame we had saved last
|
||||
// time.
|
||||
}
|
||||
|
||||
// create a GWorld containing our image
|
||||
GWorldPtr pGWorld;
|
||||
err = NewGWorldFromPtr(&pGWorld, k32BGRAPixelFormat, &src_rect, 0, 0, 0,
|
||||
_reversed_buffer, rowsize);
|
||||
if (err != noErr) {
|
||||
nout << " error in NewGWorldFromPtr, called from paint_window()\n";
|
||||
return;
|
||||
}
|
||||
|
||||
GrafPtr out_port = _wparams.get_parent_window()._port;
|
||||
GrafPtr portSave = NULL;
|
||||
Boolean portChanged = QDSwapPort(out_port, &portSave);
|
||||
|
||||
// Make sure the clipping rectangle isn't in the way. Is there a
|
||||
// better way to eliminate the cliprect from consideration?
|
||||
Rect r = { 0, 0, 0x7fff, 0x7fff };
|
||||
ClipRect(&r);
|
||||
|
||||
CopyBits(GetPortBitMapForCopyBits(pGWorld),
|
||||
GetPortBitMapForCopyBits(out_port),
|
||||
&src_rect, &ddrc_rect, srcCopy, 0);
|
||||
|
||||
if (portChanged) {
|
||||
QDSwapPort(portSave, NULL);
|
||||
}
|
||||
|
||||
DisposeGWorld(pGWorld);
|
||||
#endif // __APPLE__
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::SplashDownload::Constructor
|
||||
// Access: Public
|
||||
|
@ -22,6 +22,10 @@
|
||||
#include "p3dReferenceCount.h"
|
||||
#include "get_tinyxml.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "subprocessWindowBuffer.h"
|
||||
#endif
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
@ -65,6 +69,8 @@ public:
|
||||
const unsigned char *this_data,
|
||||
size_t this_data_size);
|
||||
|
||||
void handle_event(P3D_event_data event);
|
||||
|
||||
inline int get_instance_id() const;
|
||||
inline const string &get_session_key() const;
|
||||
inline const string &get_python_version() const;
|
||||
@ -101,6 +107,8 @@ private:
|
||||
void make_splash_window();
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
||||
void paint_window();
|
||||
|
||||
P3D_request_ready_func *_func;
|
||||
P3D_object *_browser_script_object;
|
||||
P3DToplevelObject *_panda_script_object;
|
||||
@ -118,6 +126,17 @@ private:
|
||||
// Not ref-counted: session is the parent.
|
||||
P3DSession *_session;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// On OSX, we have to get a copy of the framebuffer data back from
|
||||
// the child process, and draw it to the window, here in the parent
|
||||
// process. Crazy!
|
||||
int _shared_fd;
|
||||
size_t _shared_mmap_size;
|
||||
string _shared_filename;
|
||||
SubprocessWindowBuffer *_swbuffer;
|
||||
char *_reversed_buffer;
|
||||
#endif __APPLE__
|
||||
|
||||
P3DSplashWindow *_splash_window;
|
||||
bool _instance_window_opened;
|
||||
|
||||
|
@ -889,27 +889,37 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
|
||||
xwparams->Attribute("win_height", &win_height);
|
||||
|
||||
long parent_window_handle = 0;
|
||||
const char *subprocess_window = "";
|
||||
|
||||
#ifdef _WIN32
|
||||
int hwnd;
|
||||
if (xwparams->Attribute("parent_hwnd", &hwnd)) {
|
||||
parent_window_handle = (long)hwnd;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
|
||||
#elif __APPLE__
|
||||
// On Mac, we don't parent windows directly to the browser; instead,
|
||||
// we have to go through this subprocess-window nonsense.
|
||||
|
||||
subprocess_window = xwparams->Attribute("subprocess_window");
|
||||
if (subprocess_window == NULL) {
|
||||
subprocess_window = "";
|
||||
}
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
// Bad! Casting to int loses precision.
|
||||
int xwindow;
|
||||
if (xwparams->Attribute("parent_xwindow", &xwindow)) {
|
||||
parent_window_handle = (unsigned long)xwindow;
|
||||
parent_window_handle = (long)xwindow;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: direct this into the particular instance. This will
|
||||
// require a specialized ShowBase replacement.
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char *)"setupWindow", (char *)"siiiii", window_type.c_str(),
|
||||
(_runner, (char *)"setupWindow", (char *)"siiiiis", window_type.c_str(),
|
||||
win_x, win_y, win_width, win_height,
|
||||
parent_window_handle);
|
||||
parent_window_handle, subprocess_window);
|
||||
if (result == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
@ -79,8 +79,11 @@ make_xml() {
|
||||
xwparams->SetAttribute("win_height", _win_height);
|
||||
#ifdef _WIN32
|
||||
xwparams->SetAttribute("parent_hwnd", (int)_parent_window._hwnd);
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// The subprocess_window setting is applied by the caller.
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
xwparams->SetAttribute("parent_xwindow", (unsigned long)_parent_window._xwindow);
|
||||
#endif
|
||||
break;
|
||||
|
@ -406,3 +406,11 @@ P3D_instance_feed_url_stream(P3D_instance *instance, int unique_id,
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
P3D_instance_handle_event(P3D_instance *instance, P3D_event_data event) {
|
||||
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
((P3DInstance *)instance)->handle_event(event);
|
||||
RELEASE_LOCK(_api_lock);
|
||||
}
|
||||
|
@ -57,6 +57,10 @@
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -130,14 +134,14 @@ typedef struct {
|
||||
typedef struct {
|
||||
#ifdef _WIN32
|
||||
HWND _hwnd;
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
GrafPtr _port;
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
unsigned long _xwindow;
|
||||
void *_xdisplay;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
void *_nswindow;
|
||||
#endif
|
||||
} P3D_window_handle;
|
||||
|
||||
/* This enum lists the different kinds of window types that may be
|
||||
@ -781,6 +785,29 @@ P3D_instance_feed_url_stream_func(P3D_instance *instance, int unique_id,
|
||||
const void *this_data,
|
||||
size_t this_data_size);
|
||||
|
||||
/* This structure abstracts out the event pointer data types for the
|
||||
different platforms, as passed to P3D_instance_handle_event(),
|
||||
below. */
|
||||
typedef struct {
|
||||
#ifdef _WIN32
|
||||
// Not used for Win32.
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
EventRecord *_event;
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
// XEvent *_event; ?
|
||||
#endif
|
||||
} P3D_event_data;
|
||||
|
||||
/* Use this function to supply a new os-specific window event to the
|
||||
plugin. This is presently used only on OSX, where the window
|
||||
events are needed for proper plugin handling; and possibly also on
|
||||
X11. On Windows, window events are handled natively by the plugin.
|
||||
*/
|
||||
typedef void
|
||||
P3D_instance_handle_event_func(P3D_instance *instance, P3D_event_data event);
|
||||
|
||||
#ifdef P3D_FUNCTION_PROTOTYPES
|
||||
|
||||
/* Define all of the actual prototypes for the above functions. */
|
||||
@ -820,6 +847,7 @@ EXPCL_P3D_PLUGIN P3D_instance_get_request_func P3D_instance_get_request;
|
||||
EXPCL_P3D_PLUGIN P3D_check_request_func P3D_check_request;
|
||||
EXPCL_P3D_PLUGIN P3D_request_finish_func P3D_request_finish;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_feed_url_stream_func P3D_instance_feed_url_stream;
|
||||
EXPCL_P3D_PLUGIN P3D_instance_handle_event_func P3D_instance_handle_event;
|
||||
|
||||
#endif /* P3D_FUNCTION_PROTOTYPES */
|
||||
|
||||
|
@ -438,7 +438,7 @@ handle_request(P3D_request *request) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::handle_request_loop
|
||||
// Access: Private, Static
|
||||
// Access: Public, Static
|
||||
// Description: Checks for any new requests from the plugin, and
|
||||
// dispatches them to the appropriate PPInstance. This
|
||||
// function is called only in the main thread.
|
||||
@ -461,6 +461,47 @@ handle_request_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::handle_event
|
||||
// Access: Public
|
||||
// Description: Called by the browser as new window events are
|
||||
// generated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPInstance::
|
||||
handle_event(void *event) {
|
||||
// This is a good time to check for new requests.
|
||||
handle_request_loop();
|
||||
|
||||
if (_p3d_inst == NULL) {
|
||||
// Ignore events that come in before we've launched the instance.
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
EventRecord *er = (EventRecord *)event;
|
||||
|
||||
switch (er->what) {
|
||||
case nullEvent:
|
||||
// We appear to get this event pretty frequently when nothing else
|
||||
// is going on. Great; we'll take advantage of it to invalidate
|
||||
// the instance rectangle, which will cause updateEvt to be
|
||||
// triggered (if the instance is still onscreen).
|
||||
|
||||
if (_got_window) {
|
||||
NPRect rect = { 0, 0, _window.height, _window.width };
|
||||
browser->invalidaterect(_npp_instance, &rect);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// All other events we feed down to the plugin for processing.
|
||||
P3D_event_data edata;
|
||||
edata._event = er;
|
||||
P3D_instance_handle_event(_p3d_inst, edata);
|
||||
|
||||
#endif // __APPLE__
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::get_panda_script_object
|
||||
// Access: Public
|
||||
@ -972,14 +1013,24 @@ send_window() {
|
||||
// right spot.
|
||||
#ifdef _WIN32
|
||||
parent_window._hwnd = (HWND)(_window.window);
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
logfile << "windowed plugin\n" << flush;
|
||||
NP_Port *port = (NP_Port *)_window.window;
|
||||
logfile << "portx, porty = " << port->portx << ", " << port->porty << "\n";
|
||||
logfile << "x, y = " << _window.x << ", " << _window.y << "\n";
|
||||
parent_window._port = port->port;
|
||||
|
||||
#elif defined(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;
|
||||
y = 0;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// We have a "windowless" plugin. Parent our window directly to
|
||||
// the browser window.
|
||||
@ -990,8 +1041,15 @@ send_window() {
|
||||
&hwnd) == NPERR_NO_ERROR) {
|
||||
parent_window._hwnd = hwnd;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
logfile << "windowless plugin\n" << flush;
|
||||
NP_Port *port = (NP_Port *)_window.window;
|
||||
logfile << "portx, porty = " << port->portx << ", " << port->porty << "\n";
|
||||
logfile << "x, y = " << _window.x << ", " << _window.y << "\n";
|
||||
parent_window._port = port->port;
|
||||
|
||||
#elif defined(HAVE_X11)
|
||||
parent_window._xwindow = 0;
|
||||
unsigned long win;
|
||||
if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
void handle_request(P3D_request *request);
|
||||
static void handle_request_loop();
|
||||
|
||||
void handle_event(void *event);
|
||||
|
||||
NPObject *get_panda_script_object();
|
||||
|
||||
void p3dobj_to_variant(NPVariant *result, P3D_object *object);
|
||||
|
@ -331,8 +331,10 @@ int16
|
||||
NPP_HandleEvent(NPP instance, void *event) {
|
||||
// logfile << "HandleEvent\n" << flush;
|
||||
|
||||
// Here's a fine opportunity to check for new requests.
|
||||
PPInstance::handle_request_loop();
|
||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||
assert(inst != NULL);
|
||||
|
||||
inst->handle_event(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -258,8 +258,36 @@ class AppRunner(DirectObject):
|
||||
|
||||
self.startIfReady()
|
||||
|
||||
def setupWindow(self, windowType, x, y, width, height, parent):
|
||||
print "setupWindow %s, %s, %s, %s, %s, %s" % (windowType, x, y, width, height, parent)
|
||||
def clearWindowPrc(self):
|
||||
""" Clears the windowPrc file that was created in a previous
|
||||
call to setupWindow(), if any. """
|
||||
|
||||
if self.windowPrc:
|
||||
unloadPrcFile(self.windowPrc)
|
||||
self.windowPrc = None
|
||||
|
||||
def setupWindow(self, windowType, x, y, width, height,
|
||||
parent, subprocessWindow):
|
||||
""" Applies the indicated window parameters to the prc
|
||||
settings, for future windows; or applies them directly to the
|
||||
main window if the window has already been opened. """
|
||||
|
||||
print "setupWindow %s, %s, %s, %s, %s, %s, %s" % (windowType, x, y, width, height, parent, subprocessWindow)
|
||||
|
||||
if self.started and base.win:
|
||||
# If we've already got a window, this must be a
|
||||
# resize/reposition request.
|
||||
wp = WindowProperties()
|
||||
if x or y or windowType == 'embedded':
|
||||
wp.setOrigin(x, y)
|
||||
if width or height:
|
||||
wp.setSize(width, height)
|
||||
base.win.requestProperties(wp)
|
||||
return
|
||||
|
||||
# If we haven't got a window already, start 'er up. Apply the
|
||||
# requested setting to the prc file.
|
||||
|
||||
if windowType == 'hidden':
|
||||
data = 'window-type none\n'
|
||||
else:
|
||||
@ -271,33 +299,21 @@ class AppRunner(DirectObject):
|
||||
data += 'fullscreen 0\n'
|
||||
|
||||
if windowType == 'embedded':
|
||||
data += 'parent-window-handle %s\n' % (parent)
|
||||
data += 'parent-window-handle %s\nsubprocess-window %s\n' % (
|
||||
parent, subprocessWindow)
|
||||
else:
|
||||
data += 'parent-window-handle 0\n'
|
||||
data += 'parent-window-handle 0\nsubprocess-window \n'
|
||||
|
||||
if x or y or windowType == 'embedded':
|
||||
data += 'win-origin %s %s\n' % (x, y)
|
||||
if width or height:
|
||||
data += 'win-size %s %s\n' % (width, height)
|
||||
|
||||
if self.windowPrc:
|
||||
unloadPrcFile(self.windowPrc)
|
||||
self.clearWindowPrc()
|
||||
self.windowPrc = loadPrcFileData("setupWindow", data)
|
||||
|
||||
if self.started and base.win:
|
||||
# If we've already got a window, this must be a
|
||||
# resize/reposition request.
|
||||
wp = WindowProperties()
|
||||
if x or y or windowType == 'embedded':
|
||||
wp.setOrigin(x, y)
|
||||
if width or height:
|
||||
wp.setSize(width, height)
|
||||
base.win.requestProperties(wp)
|
||||
|
||||
else:
|
||||
# If we haven't got a window already, start 'er up.
|
||||
self.gotWindow = True
|
||||
self.startIfReady()
|
||||
self.gotWindow = True
|
||||
self.startIfReady()
|
||||
|
||||
def setRequestFunc(self, func):
|
||||
""" This method is called by the plugin at startup to supply a
|
||||
@ -319,9 +335,15 @@ class AppRunner(DirectObject):
|
||||
successfully opened. """
|
||||
|
||||
if not self.windowOpened:
|
||||
self.notifyRequest('onwindowopen')
|
||||
self.windowOpened = True
|
||||
|
||||
# Now that the window is open, we don't need to keep those
|
||||
# prc settings around any more.
|
||||
self.clearWindowPrc()
|
||||
|
||||
# Inform the plugin and browser.
|
||||
self.notifyRequest('onwindowopen')
|
||||
|
||||
def notifyRequest(self, message):
|
||||
""" Delivers a notify request to the browser. This is a "this
|
||||
happened" type notification; it optionally triggers some
|
||||
@ -340,10 +362,10 @@ class AppRunner(DirectObject):
|
||||
|
||||
def evalScript(self, expression, needsResponse = False):
|
||||
""" Evaluates an arbitrary JavaScript expression in the global
|
||||
DOM space. This may be deferred if necessary if self.dom has
|
||||
not yet been assigned. If needsResponse is true, this waits
|
||||
for the value and returns it, which means it may not be
|
||||
deferred. """
|
||||
DOM space. This may be deferred if necessary if needsResponse
|
||||
is False and self.dom has not yet been assigned. If
|
||||
needsResponse is true, this waits for the value and returns
|
||||
it, which means it cannot be deferred. """
|
||||
|
||||
if not self.dom:
|
||||
# Defer the expression.
|
||||
|
Loading…
x
Reference in New Issue
Block a user