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

This commit is contained in:
rdb 2009-07-09 13:55:32 +00:00
parent d02b9bd34b
commit 474b738f8b
12 changed files with 457 additions and 4 deletions

View File

@ -3,10 +3,16 @@
#define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_TINYXML],$[HAVE_OPENSSL],$[HAVE_ZLIB]]
#begin lib_target
#define USE_PACKAGES tinyxml openssl zlib jpeg
#define USE_PACKAGES tinyxml openssl zlib jpeg x11
#define TARGET p3d_plugin
#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 \
$[TARGET]_composite1.cxx
@ -39,6 +45,7 @@
p3dStringObject.h \
p3dUndefinedObject.h \
p3dWinSplashWindow.h p3dWinSplashWindow.I \
p3dX11SplashWindow.h \
p3dWindowParams.h p3dWindowParams.I
#define INCLUDED_SOURCES \
@ -62,6 +69,7 @@
p3dStringObject.cxx \
p3dUndefinedObject.cxx \
p3dWinSplashWindow.cxx \
p3dX11SplashWindow.cxx \
p3dWindowParams.cxx
#define INSTALL_HEADERS \

View File

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

View File

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

View File

@ -851,6 +851,13 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
parent_window_handle = (long)hwnd;
}
#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
// require a specialized ShowBase replacement.

View File

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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -12,6 +12,12 @@
#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 \
$[TARGET]_composite1.cxx

View File

@ -923,24 +923,49 @@ send_window() {
int y = _window.y;
P3D_window_handle parent_window;
#ifdef _WIN32
if (_window.type == NPWindowTypeWindow) {
// We have a "windowed" plugin. Parent our window to the one we
// 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
// right spot.
#ifdef _WIN32
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;
y = 0;
} else {
// We have a "windowless" plugin. Parent our window directly to
// the browser window.
#ifdef _WIN32
parent_window._hwnd = 0;
HWND hwnd;
if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
&hwnd) == NPERR_NO_ERROR) {
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

View File

@ -66,7 +66,13 @@ request_ready(P3D_instance *instance) {
// it within HandleEvent(). TODO: enable a timer to ensure we get
// HandleEvent callbacks in a timely manner? Or maybe we should
// 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:
*(const char **)value = "Runs 3-D games and interactive applets";
break;
case NPPVpluginNeedsXEmbed:
*((PRBool *)value) = PR_FALSE;
break;
default:
logfile << "Ignoring GetValue request " << variable << "\n" << flush;
return NPERR_INVALID_PARAM;
}