fix windows crash; fix splash window drawing
This commit is contained in:
parent
54732da355
commit
bc0d953ab5
|
|
@ -17,6 +17,7 @@
|
|||
#include "p3dSession.h"
|
||||
#include "p3dPackage.h"
|
||||
#include "p3d_plugin_config.h"
|
||||
#include "p3dWinSplashWindow.h"
|
||||
#include "find_root_dir.h"
|
||||
#include "mkdir_complete.h"
|
||||
|
||||
|
|
@ -70,6 +71,10 @@ P3DInstanceManager::
|
|||
|
||||
assert(_instances.empty());
|
||||
assert(_sessions.empty());
|
||||
|
||||
#ifdef _WIN32
|
||||
P3DWinSplashWindow::unregister_window_class();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ run_python() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonRun::
|
||||
handle_command(TiXmlDocument *doc) {
|
||||
nout << "received: " << *doc << "\n" << flush;
|
||||
TiXmlElement *xcommand = doc->FirstChildElement("command");
|
||||
if (xcommand != NULL) {
|
||||
bool needs_response = false;
|
||||
|
|
@ -267,6 +268,7 @@ handle_command(TiXmlDocument *doc) {
|
|||
xresponse->SetAttribute("response_id", want_response_id);
|
||||
doc.LinkEndChild(decl);
|
||||
doc.LinkEndChild(xresponse);
|
||||
nout << "sent: " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
}
|
||||
}
|
||||
|
|
@ -413,6 +415,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||
}
|
||||
|
||||
if (needs_response) {
|
||||
nout << "sent: " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
}
|
||||
}
|
||||
|
|
@ -488,6 +491,7 @@ wait_script_response(int response_id) {
|
|||
// This is the response we were waiting for.
|
||||
_commands.erase(ci);
|
||||
RELEASE_LOCK(_commands_lock);
|
||||
nout << "received: " << *doc << "\n" << flush;
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
|
@ -585,6 +589,7 @@ py_request_func(PyObject *args) {
|
|||
}
|
||||
|
||||
xrequest->SetAttribute("message", message);
|
||||
nout << "sent: " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
} else if (strcmp(request_type, "script") == 0) {
|
||||
|
|
@ -609,6 +614,7 @@ py_request_func(PyObject *args) {
|
|||
TiXmlElement *xvalue = pyobj_to_xml(value);
|
||||
xrequest->LinkEndChild(xvalue);
|
||||
|
||||
nout << "sent: " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ P3DSession::
|
|||
xcommand->SetAttribute("cmd", "exit");
|
||||
doc.LinkEndChild(decl);
|
||||
doc.LinkEndChild(xcommand);
|
||||
nout << "sent: " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
// Also close the pipe, to help underscore the point.
|
||||
|
|
@ -214,6 +215,7 @@ void P3DSession::
|
|||
send_command(TiXmlDocument *command) {
|
||||
if (_p3dpython_running) {
|
||||
// Python is running. Send the command.
|
||||
nout << "sent: " << *command << "\n" << flush;
|
||||
_pipe_write << *command << flush;
|
||||
delete command;
|
||||
} else {
|
||||
|
|
@ -252,6 +254,7 @@ command_and_response(TiXmlDocument *command) {
|
|||
assert(xcommand != NULL);
|
||||
xcommand->SetAttribute("want_response_id", response_id);
|
||||
|
||||
nout << "sent: " << *command << "\n" << flush;
|
||||
_pipe_write << *command << flush;
|
||||
delete command;
|
||||
|
||||
|
|
@ -541,6 +544,7 @@ start_p3dpython() {
|
|||
// may have queued up.
|
||||
Commands::iterator ci;
|
||||
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
||||
nout << "sent: " << *(*ci) << "\n" << flush;
|
||||
_pipe_write << *(*ci);
|
||||
delete (*ci);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool P3DWinSplashWindow::_registered_window_class = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -132,7 +134,49 @@ set_install_progress(double install_progress) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::start_thraed
|
||||
// Function: P3DWinSplashWindow::register_window_class
|
||||
// Access: Public, Static
|
||||
// Description: Registers the window class for this window, if
|
||||
// needed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
register_window_class() {
|
||||
if (!_registered_window_class) {
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
|
||||
WNDCLASS wc;
|
||||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.lpfnWndProc = st_window_proc;
|
||||
wc.hInstance = application;
|
||||
wc.lpszClassName = "panda3d_splash";
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
nout << "Could not register window class panda3d_splash\n";
|
||||
}
|
||||
_registered_window_class = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::unregister_window_class
|
||||
// Access: Public, Static
|
||||
// Description: Unregisters the window class for this window. It is
|
||||
// necessary to do this before unloading the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
unregister_window_class() {
|
||||
if (_registered_window_class) {
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
|
||||
if (!UnregisterClass("panda3d_splash", application)) {
|
||||
nout << "Could not unregister window class panda3d_splash\n";
|
||||
}
|
||||
_registered_window_class = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::start_thread
|
||||
// Access: Private
|
||||
// Description: Spawns the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -146,7 +190,7 @@ start_thread() {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::stop_thraed
|
||||
// Function: P3DWinSplashWindow::stop_thread
|
||||
// Access: Private
|
||||
// Description: Terminates and joins the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -241,23 +285,8 @@ win_thread_run(LPVOID data) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
make_window() {
|
||||
WNDCLASS wc;
|
||||
|
||||
register_window_class();
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
|
||||
static bool registered_class = false;
|
||||
if (!registered_class) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.lpfnWndProc = st_window_proc;
|
||||
wc.hInstance = application;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszClassName = "panda3d_splash";
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
nout << "Could not register window class!\n";
|
||||
}
|
||||
registered_class = true;
|
||||
}
|
||||
|
||||
int x = CW_USEDEFAULT;
|
||||
int y = CW_USEDEFAULT;
|
||||
|
|
@ -482,6 +511,69 @@ close_window() {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::paint_window
|
||||
// Access: Private
|
||||
// Description: Paints the contents of the window into the indicated
|
||||
// DC.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
paint_window(HDC dc) {
|
||||
RECT rect;
|
||||
GetClientRect(_hwnd, &rect);
|
||||
int win_width = rect.right - rect.left;
|
||||
int win_height = rect.bottom - rect.top;
|
||||
|
||||
if (_bitmap != NULL) {
|
||||
// Paint the background splash image.
|
||||
HDC mem_dc = CreateCompatibleDC(dc);
|
||||
SelectObject(mem_dc, _bitmap);
|
||||
|
||||
// Determine the relative size of bitmap and window.
|
||||
int bm_width = _bitmap_width;
|
||||
int bm_height = _bitmap_height;
|
||||
|
||||
int win_cx = win_width / 2;
|
||||
int win_cy = win_height / 2;
|
||||
|
||||
if (bm_width <= win_width && bm_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 - bm_width / 2;
|
||||
int p_y = win_cy - bm_height / 2;
|
||||
|
||||
BitBlt(dc, p_x, p_y, bm_width, bm_height,
|
||||
mem_dc, 0, 0, SRCCOPY);
|
||||
|
||||
// Now don't paint over this in the below FillRect().
|
||||
ExcludeClipRect(dc, p_x, p_y, p_x + bm_width, p_y + bm_height);
|
||||
|
||||
} else {
|
||||
// The bitmap is larger than the window; scale it down.
|
||||
double x_scale = (double)win_width / (double)bm_width;
|
||||
double y_scale = (double)win_height / (double)bm_height;
|
||||
double scale = min(x_scale, y_scale);
|
||||
int sc_width = (int)(bm_width * scale);
|
||||
int sc_height = (int)(bm_height * scale);
|
||||
|
||||
int p_x = win_cx - sc_width / 2;
|
||||
int p_y = win_cy - sc_height / 2;
|
||||
StretchBlt(dc, p_x, p_y, sc_width, sc_height,
|
||||
mem_dc, 0, 0, bm_width, bm_height, SRCCOPY);
|
||||
|
||||
// Now don't paint over this in the below FillRect().
|
||||
ExcludeClipRect(dc, p_x, p_y, p_x + sc_width, p_y + sc_height);
|
||||
}
|
||||
|
||||
SelectObject(mem_dc, NULL);
|
||||
DeleteDC(mem_dc);
|
||||
}
|
||||
|
||||
// Paint everything else the background color.
|
||||
FillRect(dc, &rect, WHITE_BRUSH);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::window_proc
|
||||
// Access: Private
|
||||
|
|
@ -495,59 +587,20 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
return true;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC dc = BeginPaint(hwnd, &ps);
|
||||
if (_bitmap != NULL) {
|
||||
// Paint the background splash image.
|
||||
HDC mem_dc = CreateCompatibleDC(dc);
|
||||
SelectObject(mem_dc, _bitmap);
|
||||
|
||||
// Determine the relative size of bitmap and window.
|
||||
RECT rect;
|
||||
GetClientRect(hwnd, &rect);
|
||||
int win_width = rect.right - rect.left;
|
||||
int win_height = rect.bottom - rect.top;
|
||||
int bm_width = _bitmap_width;
|
||||
int bm_height = _bitmap_height;
|
||||
|
||||
int win_cx = win_width / 2;
|
||||
int win_cy = win_height / 2;
|
||||
|
||||
if (bm_width <= win_width && bm_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 - bm_width / 2;
|
||||
int p_y = win_cy - bm_height / 2;
|
||||
|
||||
BitBlt(dc, p_x, p_y, bm_width, bm_height,
|
||||
mem_dc, 0, 0, SRCCOPY);
|
||||
|
||||
} else {
|
||||
// The bitmap is larger than the window; scale it down.
|
||||
double x_scale = (double)win_width / (double)bm_width;
|
||||
double y_scale = (double)win_height / (double)bm_height;
|
||||
double scale = min(x_scale, y_scale);
|
||||
int sc_width = (int)(bm_width * scale);
|
||||
int sc_height = (int)(bm_height * scale);
|
||||
|
||||
int p_x = win_cx - sc_width / 2;
|
||||
int p_y = win_cy - sc_height / 2;
|
||||
StretchBlt(dc, p_x, p_y, sc_width, sc_height,
|
||||
mem_dc, 0, 0, bm_width, bm_height, SRCCOPY);
|
||||
}
|
||||
|
||||
SelectObject(mem_dc, NULL);
|
||||
DeleteDC(mem_dc);
|
||||
}
|
||||
paint_window(dc);
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
break;
|
||||
return true;
|
||||
|
||||
case WM_DRAWITEM:
|
||||
// Draw a text label placed within the window.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ public:
|
|||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress);
|
||||
|
||||
static void register_window_class();
|
||||
static void unregister_window_class();
|
||||
|
||||
private:
|
||||
void start_thread();
|
||||
void stop_thread();
|
||||
|
|
@ -55,6 +58,7 @@ private:
|
|||
bool image_filename_temp);
|
||||
void close_window();
|
||||
|
||||
void paint_window(HDC dc);
|
||||
LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static LONG WINAPI st_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
|
|
@ -79,6 +83,8 @@ private:
|
|||
int _bitmap_width, _bitmap_height;
|
||||
HWND _progress_bar;
|
||||
HWND _text_label;
|
||||
|
||||
static bool _registered_window_class;
|
||||
};
|
||||
|
||||
#include "p3dWinSplashWindow.I"
|
||||
|
|
|
|||
|
|
@ -419,6 +419,10 @@ handle_request(P3D_request *request) {
|
|||
}
|
||||
break;
|
||||
|
||||
case P3D_RT_script:
|
||||
// We're allowed to ignore this.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Some request types are not handled.
|
||||
logfile << "Unhandled request: " << request->_request_type << "\n";
|
||||
|
|
@ -762,24 +766,34 @@ void PPInstance::
|
|||
send_window() {
|
||||
assert(_p3d_inst != NULL);
|
||||
|
||||
int x = _window.x;
|
||||
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.
|
||||
parent_window._hwnd = (HWND)(_window.window);
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else {
|
||||
// Hmm, it's just a drawable; but we didn't ask for a windowless
|
||||
// plugin.
|
||||
// We have a "windowless" plugin. Parent our window directly to
|
||||
// the browser window.
|
||||
parent_window._hwnd = 0;
|
||||
HWND hwnd;
|
||||
if (browser->getvalue(_npp_instance, NPNVnetscapeWindow,
|
||||
&hwnd) == NPERR_NO_ERROR) {
|
||||
parent_window._hwnd = hwnd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actually, we set up the window starting at (0, 0), instead of
|
||||
// whatever Mozilla tells us, because the window handle we get is a
|
||||
// specially created window that is already aligned to where we want
|
||||
// our window to be.
|
||||
P3D_instance_setup_window
|
||||
(_p3d_inst, P3D_WT_embedded,
|
||||
0, 0, _window.width, _window.height,
|
||||
x, y, _window.width, _window.height,
|
||||
parent_window);
|
||||
}
|
||||
|
||||
|
|
@ -832,6 +846,13 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||
}
|
||||
--recursion_protect;
|
||||
|
||||
switch (msg) {
|
||||
case WM_ERASEBKGND:
|
||||
// Eat the WM_ERASEBKGND message, so the browser's intervening
|
||||
// window won't overdraw on top of our own window.
|
||||
return true;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ request_ready(P3D_instance *instance) {
|
|||
PPInstance *inst = (PPInstance *)(instance->_user_data);
|
||||
assert(inst != NULL);
|
||||
const NPWindow *win = inst->get_window();
|
||||
if (win != NULL) {
|
||||
if (win != NULL && win->type == NPWindowTypeWindow) {
|
||||
PostMessage((HWND)(win->window), WM_USER, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +161,12 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
|
|||
instance->pdata = new PPInstance(pluginType, instance, mode,
|
||||
argc, argn, argv, saved);
|
||||
|
||||
// To experiment with a "windowless" plugin, which really means we
|
||||
// create our own window without an intervening window, try this.
|
||||
// At the moment, there's a deadlock condition when we try it, but
|
||||
// surely it can be solved.
|
||||
// browser->setvalue(instance, NPPVpluginWindowBool, (void *)false);
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -307,7 +313,7 @@ NPP_Print(NPP instance, NPPrint *platformPrint) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int16
|
||||
NPP_HandleEvent(NPP instance, void *event) {
|
||||
// logfile << "HandleEvent\n";
|
||||
logfile << "HandleEvent\n" << flush;
|
||||
|
||||
// Here's a fine opportunity to check for new requests.
|
||||
PPInstance::handle_request_loop();
|
||||
|
|
|
|||
Loading…
Reference in New Issue