osx splash window

This commit is contained in:
David Rose 2009-07-17 01:39:41 +00:00
parent bb3e1ef644
commit 72da887fd5
13 changed files with 407 additions and 14 deletions

View File

@ -43,6 +43,7 @@
p3dMultifileReader.h p3dMultifileReader.I \
p3dNoneObject.h \
p3dObject.h p3dObject.I \
p3dOsxSplashWindow.h p3dOsxSplashWindow.I \
p3dPackage.h p3dPackage.I \
p3dPythonObject.h \
p3dReferenceCount.h p3dReferenceCount.I \
@ -71,6 +72,7 @@
p3dMultifileReader.cxx \
p3dNoneObject.cxx \
p3dObject.cxx \
p3dOsxSplashWindow.cxx \
p3dPackage.cxx \
p3dPythonObject.cxx \
p3dReferenceCount.cxx \

View File

@ -19,6 +19,7 @@
#include "p3dPackage.h"
#include "p3dSplashWindow.h"
#include "p3dWinSplashWindow.h"
#include "p3dOsxSplashWindow.h"
#include "p3dX11SplashWindow.h"
#include "p3dObject.h"
#include "p3dToplevelObject.h"
@ -34,6 +35,8 @@
#ifdef _WIN32
typedef P3DWinSplashWindow SplashWindowType;
#elif defined(__APPLE__)
typedef P3DOsxSplashWindow SplashWindowType;
#elif defined(HAVE_X11)
typedef P3DX11SplashWindow SplashWindowType;
#else
@ -153,8 +156,8 @@ set_fparams(const P3DFileParams &fparams) {
// Generate a special notification: onpluginload, indicating the
// plugin has read its parameters and is ready to be queried (even
// if Python has not yet started). This notification is special
// because it is the only one generated at this level; the rest of
// them are generated by the Python code, once that is running.
// because it generated at the C++ level, here; most of them are
// generated by the Python code, once that is running.
P3D_request *request = new P3D_request;
request->_request_type = P3D_RT_notify;
request->_request._notify._message = strdup("onpluginload");
@ -475,6 +478,10 @@ feed_url_stream(int unique_id,
////////////////////////////////////////////////////////////////////
void P3DInstance::
handle_event(P3D_event_data event) {
if (_splash_window != NULL) {
_splash_window->handle_event(event);
}
#ifdef _WIN32
// This function is not used in Win32 and does nothing.
@ -643,6 +650,20 @@ request_stop() {
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::request_refresh
// Access: Public
// Description: Asks the host to refresh the plugin window. This is
// only relevant for windowless plugins, for instance,
// the way OSX plugins always run.
////////////////////////////////////////////////////////////////////
void P3DInstance::
request_refresh() {
P3D_request *request = new P3D_request;
request->_request_type = P3D_RT_refresh;
add_baked_request(request);
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::make_xml
// Access: Public
@ -971,8 +992,7 @@ install_progress(P3DPackage *package, double progress) {
void P3DInstance::
paint_window() {
#ifdef __APPLE__
if (_swbuffer == NULL) {
nout << "no _swbuffer\n";
if (_swbuffer == NULL || !_instance_window_opened) {
return;
}

View File

@ -82,6 +82,7 @@ public:
void start_download(P3DDownload *download);
inline bool is_started() const;
void request_stop();
void request_refresh();
TiXmlElement *make_xml();

View File

@ -0,0 +1,14 @@
// Filename: p3dOsxSplashWindow.I
// Created by: drose (16Jul09)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,264 @@
// Filename: p3dOsxSplashWindow.cxx
// Created by: drose (16Jul09)
//
////////////////////////////////////////////////////////////////////
//
// 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 "p3dOsxSplashWindow.h"
#ifdef __APPLE__
#include <Carbon/Carbon.h>
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DOsxSplashWindow::
P3DOsxSplashWindow(P3DInstance *inst) :
P3DSplashWindow(inst)
{
_image = NULL;
_image_data = NULL;
_install_progress = 0;
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DOsxSplashWindow::
~P3DOsxSplashWindow() {
if (_image != NULL) {
DisposeGWorld(_image);
}
if (_image_data != NULL) {
delete[] _image_data;
_image_data = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::set_image_filename
// Access: Public, Virtual
// Description: Specifies the name of a JPEG image file that is
// 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 P3DOsxSplashWindow::
set_image_filename(const string &image_filename,
bool image_filename_temp) {
int num_channels, row_stride;
string data;
if (!read_image(image_filename, image_filename_temp,
_image_height, _image_width, num_channels, row_stride,
data)) {
return;
}
QDErr err;
Rect src_rect = { 0, 0, _image_height, _image_width };
if (_image != NULL) {
DisposeGWorld(_image);
_image = NULL;
}
if (_image_data != NULL) {
delete[] _image_data;
_image_data = NULL;
}
// Now we need to copy from the RGB source image into the BGRA target image.
int new_row_stride = _image_width * 4;
_image_data = new char[new_row_stride * _image_height];
for (int yi = 0; yi < _image_height; ++yi) {
char *dest = _image_data + yi * new_row_stride;
const char *source = data.data() + yi * row_stride;
for (int xi = 0; xi < _image_width; ++xi) {
char r = source[0];
char g = source[1];
char b = source[2];
#ifndef __BIG_ENDIAN__
// Little-endian.
dest[0] = b;
dest[1] = g;
dest[2] = r;
dest[3] = 0xff;
#else // __BIG_ENDIAN__
// Big-endian.
dest[0] = 0xff;
dest[1] = r;
dest[2] = g;
dest[3] = b;
#endif // __BIG_ENDIAN__
source += 3;
dest += 4;
}
}
err = NewGWorldFromPtr(&_image, k32BGRAPixelFormat, &src_rect, 0, 0, 0,
_image_data, new_row_stride);
if (err != noErr) {
nout << " error in NewGWorldFromPtr, called from set_image_filename()\n";
return;
}
_inst->request_refresh();
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::set_install_label
// Access: Public, Virtual
// Description: Specifies the text that is displayed above the
// install progress bar.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
set_install_label(const string &install_label) {
_install_label = install_label;
_inst->request_refresh();
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::set_install_progress
// Access: Public, Virtual
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
set_install_progress(double install_progress) {
if ((int)(install_progress * 500.0) != (int)(_install_progress * 500.0)) {
// Only request a refresh if we're changing substantially.
_inst->request_refresh();
}
_install_progress = install_progress;
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::handle_event
// Access: Public, Virtual
// Description: Deals with the event callback from the OS window
// system.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
handle_event(P3D_event_data event) {
EventRecord *er = event._event;
if (er->what == updateEvt) {
paint_window();
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::paint_window
// Access: Private
// Description: Redraws the current splash window.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
paint_window() {
cerr << "paint_window, _image = " << _image << ", label = " << _install_label << "\n";
GrafPtr out_port = _wparams.get_parent_window()._port;
GrafPtr portSave = NULL;
Boolean portChanged = QDSwapPort(out_port, &portSave);
int win_width = _wparams.get_win_width();
int win_height = _wparams.get_win_height();
Rect r = { 0, 0, win_height, win_width };
ClipRect(&r);
EraseRect(&r);
if (_image != NULL) {
Rect src_rect = { 0, 0, _image_height, _image_width };
Rect dest_rect;
// Determine the relative size of image and window.
int win_cx = win_width / 2;
int win_cy = win_height / 2;
if (_image_width <= win_width && _image_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 - _image_width / 2;
int p_y = win_cy - _image_height / 2;
dest_rect.left = p_x;
dest_rect.top = p_y;
dest_rect.right = p_x + _image_width;
dest_rect.bottom = p_y + _image_height;
} else {
// The bitmap is larger than the window; scale it down.
double x_scale = (double)win_width / (double)_image_width;
double y_scale = (double)win_height / (double)_image_height;
double scale = min(x_scale, y_scale);
int sc_width = (int)(_image_width * scale);
int sc_height = (int)(_image_height * scale);
int p_x = win_cx - sc_width / 2;
int p_y = win_cy - sc_height / 2;
dest_rect.left = p_x;
dest_rect.top = p_y;
dest_rect.right = p_x + sc_width;
dest_rect.bottom = p_y + sc_height;
}
CopyBits(GetPortBitMapForCopyBits(_image),
GetPortBitMapForCopyBits(out_port),
&src_rect, &dest_rect, srcCopy, 0);
}
int bar_width = min((int)(win_width * 0.6), 400);
int bar_height = min((int)(win_height * 0.1), 24);
int bar_x = (win_width - bar_width) / 2;
int bar_y = (win_height - bar_height * 2);
int progress = bar_x + 1 + (int)((bar_width - 2) * _install_progress);
Rect rbar = { bar_y, bar_x, bar_y + bar_height, bar_x + bar_width };
Rect rneed = { bar_y + 1, progress + 1, bar_y + bar_height - 1, bar_x + bar_width - 1 };
Rect rdone = { bar_y + 1, bar_x + 1, bar_y + bar_height - 1, progress };
FrameRect(&rbar);
PaintRect(&rdone);
EraseRect(&rneed);
TextFont(0);
TextFace(bold);
TextMode(srcOr);
TextSize(0);
Point numer, denom;
FontInfo font_info;
StdTxMeas(_install_label.size(), _install_label.data(), &numer, &denom, &font_info);
int text_width = TextWidth(_install_label.data(), 0, _install_label.size());
int text_x = (win_width - text_width) / 2;
int text_y = bar_y - font_info.descent - 8;
Rect rtext = { text_y - font_info.ascent - 2, text_x - 2,
text_y + font_info.descent + 2, text_x + text_width + 2 };
EraseRect(&rtext);
MoveTo(text_x, text_y);
DrawText(_install_label.data(), 0, _install_label.size());
if (portChanged) {
QDSwapPort(portSave, NULL);
}
}
#endif // __APPLE__

View File

@ -0,0 +1,59 @@
// Filename: p3dOsxSplashWindow.h
// Created by: drose (16Jul09)
//
////////////////////////////////////////////////////////////////////
//
// 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 P3DOSXSPLASHWINDOW_H
#define P3DOSXSPLASHWINDOW_H
#include "p3d_plugin_common.h"
#ifdef __APPLE__
#include "p3dSplashWindow.h"
#include <ApplicationServices/ApplicationServices.h>
////////////////////////////////////////////////////////////////////
// Class : P3DOsxSplashWindow
// Description : This is the OSX implementation of the
// initial-download window.
////////////////////////////////////////////////////////////////////
class P3DOsxSplashWindow : public P3DSplashWindow {
public:
P3DOsxSplashWindow(P3DInstance *inst);
virtual ~P3DOsxSplashWindow();
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);
virtual void handle_event(P3D_event_data event);
private:
void paint_window();
private:
GWorldPtr _image;
char *_image_data;
int _image_height, _image_width;
string _install_label;
double _install_progress;
};
#include "p3dOsxSplashWindow.I"
#endif // __APPLE__
#endif

View File

@ -110,6 +110,16 @@ void P3DSplashWindow::
set_install_progress(double install_progress) {
}
////////////////////////////////////////////////////////////////////
// Function: P3DSplashWindow::handle_event
// Access: Public, Virtual
// Description: Deals with the event callback from the OS window
// system.
////////////////////////////////////////////////////////////////////
void P3DSplashWindow::
handle_event(P3D_event_data event) {
}
////////////////////////////////////////////////////////////////////
// Function: P3DSplashWindow::read_image

View File

@ -47,6 +47,8 @@ public:
virtual void set_install_label(const string &install_label);
virtual void set_install_progress(double install_progress);
virtual void handle_event(P3D_event_data event);
void setup_splash_image();
protected:

View File

@ -630,6 +630,7 @@ typedef enum {
P3D_RT_get_url,
P3D_RT_post_url,
P3D_RT_notify,
P3D_RT_refresh,
} P3D_request_type;
/* Structures corresponding to the request types in the above enum. */
@ -673,6 +674,12 @@ typedef struct {
const char *_message;
} P3D_request_notify;
/* A refresh request. The instance would like to get a repaint event
on its own window. Only relevant for windowless plugins, e.g. on
OSX. */
typedef struct {
} P3D_request_refresh;
/* This is the overall structure that represents a single request. It
is returned by P3D_instance_get_request(). */
typedef struct {
@ -683,6 +690,7 @@ typedef struct {
P3D_request_get_url _get_url;
P3D_request_post_url _post_url;
P3D_request_notify _notify;
P3D_request_refresh _refresh;
} _request;
} P3D_request;

View File

@ -13,6 +13,7 @@
#include "p3dMultifileReader.cxx"
#include "p3dNoneObject.cxx"
#include "p3dObject.cxx"
#include "p3dOsxSplashWindow.cxx"
#include "p3dPackage.cxx"
#include "p3dPythonObject.cxx"
#include "p3dReferenceCount.cxx"

View File

@ -52,6 +52,7 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
_started_instance_data = false;
_got_instance_data = false;
_got_window = false;
_python_window_open = false;
}
////////////////////////////////////////////////////////////////////
@ -430,8 +431,23 @@ handle_request(P3D_request *request) {
break;
case P3D_RT_notify:
// We can ignore notifies, since these are handled by the core
// API.
// We mostly ignore notifies, since these are handled by the core
// API. But we do check for the "onwindowopen" notify, at which
// point we start spamming the refresh requests.
if (strcmp(request->_request._notify._message, "onwindowopen") == 0) {
_python_window_open = true;
if (_got_window) {
NPRect rect = { 0, 0, _window.height, _window.width };
browser->invalidaterect(_npp_instance, &rect);
}
}
break;
case P3D_RT_refresh:
if (_got_window) {
NPRect rect = { 0, 0, _window.height, _window.width };
browser->invalidaterect(_npp_instance, &rect);
}
break;
default:
@ -472,8 +488,7 @@ handle_event(void *event) {
// 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) {
if (_got_window && _python_window_open) {
NPRect rect = { 0, 0, _window.height, _window.width };
browser->invalidaterect(_npp_instance, &rect);
}
@ -612,11 +627,6 @@ variant_to_p3dobj(const NPVariant *variant) {
////////////////////////////////////////////////////////////////////
void PPInstance::
request_ready(P3D_instance *instance) {
logfile
<< "request_ready in " << instance
// << " thread = " << GetCurrentThreadId()
<< "\n" << flush;
PPInstance *inst = (PPInstance *)(instance->_user_data);
assert(inst != NULL);

View File

@ -104,6 +104,8 @@ private:
LONG_PTR _orig_window_proc;
#endif // _WIN32
bool _python_window_open;
PPPandaObject *_script_object;
P3D_instance *_p3d_inst;

View File

@ -329,7 +329,7 @@ NPP_Print(NPP instance, NPPrint *platformPrint) {
////////////////////////////////////////////////////////////////////
int16
NPP_HandleEvent(NPP instance, void *event) {
logfile << "HandleEvent\n" << flush;
// logfile << "HandleEvent\n" << flush;
PPInstance *inst = (PPInstance *)(instance->pdata);
assert(inst != NULL);