finally committing that blooming snow leopard support

This commit is contained in:
David Rose 2009-12-22 15:07:14 +00:00
parent b2e2877d89
commit dd007746b5
9 changed files with 959 additions and 261 deletions

View File

@ -33,6 +33,20 @@
#ifdef __APPLE__
#include <sys/mman.h>
#include <ApplicationServices/ApplicationServices.h>
// Lifted from NSEvent.h (which is Objective-C).
enum {
NSAlphaShiftKeyMask = 1 << 16,
NSShiftKeyMask = 1 << 17,
NSControlKeyMask = 1 << 18,
NSAlternateKeyMask = 1 << 19,
NSCommandKeyMask = 1 << 20,
NSNumericPadKeyMask = 1 << 21,
NSHelpKeyMask = 1 << 22,
NSFunctionKeyMask = 1 << 23,
NSDeviceIndependentModifierFlagsMask = 0xffff0000U
};
#endif // __APPLE__
#ifdef _WIN32
@ -63,6 +77,15 @@ const char *P3DInstance::_image_type_names[P3DInstance::IT_num_image_types] = {
"none", // Not really used.
};
static void
write_str(ostream &out, const wchar_t *str) {
const wchar_t *p = str;
while (*p != 0) {
out << (int)*p << ' ';
++p;
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::Constructor
// Access: Public
@ -137,6 +160,7 @@ P3DInstance(P3D_request_ready_func *func,
// We have to start with _mouse_active true; firefox doesn't send
// activate events.
_mouse_active = true;
_modifiers = 0;
_frame_timer = NULL;
#endif // __APPLE__
@ -833,88 +857,15 @@ handle_event(const P3D_event_data &event) {
}
#if defined(__APPLE__)
assert(event._event_type == P3D_ET_osx_event_record);
EventRecord *er = event._event._osx_event_record._event;
// Need to ensure we have the correct port set, in order to
// convert the mouse coordinates successfully via
// GlobalToLocal().
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_port);
GrafPtr out_port = handle._handle._osx_port._port;
GrafPtr port_save = NULL;
Boolean port_changed = QDSwapPort(out_port, &port_save);
Point pt = er->where;
GlobalToLocal(&pt);
if (port_changed) {
QDSwapPort(port_save, NULL);
if (event._event_type == P3D_ET_osx_event_record) {
retval = handle_event_osx_event_record(event);
} else if (event._event_type == P3D_ET_osx_cocoa) {
retval = handle_event_osx_cocoa(event);
} else {
assert(false);
}
#endif // __APPLE__
SubprocessWindowBuffer::Event swb_event;
swb_event._source = SubprocessWindowBuffer::ES_none;
swb_event._type = SubprocessWindowBuffer::ET_none;
swb_event._code = 0;
swb_event._flags = 0;
add_modifier_flags(swb_event._flags, er->modifiers);
switch (er->what) {
case mouseDown:
case mouseUp:
{
P3D_window_handle window = _wparams.get_parent_window();
swb_event._source = SubprocessWindowBuffer::ES_mouse;
if (er->what == mouseUp) {
swb_event._type = SubprocessWindowBuffer::ET_button_up;
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_down;
}
retval = true;
}
break;
case keyDown:
case keyUp:
case autoKey:
if (_swbuffer != NULL) {
swb_event._source = SubprocessWindowBuffer::ES_keyboard;
swb_event._code = er->message;
if (er->what == keyUp) {
swb_event._type = SubprocessWindowBuffer::ET_button_up;
} else if (er->what == keyDown) {
swb_event._type = SubprocessWindowBuffer::ET_button_down;
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_again;
}
retval = true;
}
break;
case updateEvt:
paint_window();
retval = true;
break;
case activateEvt:
_mouse_active = ((er->modifiers & 1) != 0);
break;
default:
break;
}
if (_mouse_active) {
swb_event._x = pt.h;
swb_event._y = pt.v;
swb_event._flags |= SubprocessWindowBuffer::EF_mouse_position | SubprocessWindowBuffer::EF_has_mouse;
}
if (_swbuffer != NULL) {
_swbuffer->add_event(swb_event);
}
#endif
return retval;
}
@ -3018,28 +2969,47 @@ set_install_label(const string &install_label) {
// 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.
// window. This is only needed for OSX, where the child
// process isn't allowed to do it directly.
////////////////////////////////////////////////////////////////////
void P3DInstance::
paint_window() {
const P3D_window_handle &handle = _wparams.get_parent_window();
if (handle._window_handle_type == P3D_WHT_osx_port) {
paint_window_osx_port();
} else if (handle._window_handle_type == P3D_WHT_osx_cgcontext) {
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_cgcontext);
CGContextRef context = handle._handle._osx_cgcontext._context;
paint_window_osx_cgcontext(context);
}
}
#ifdef __APPLE__
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::get_framebuffer
// Access: Private
// Description: Fills _reversed_buffer with the pixels from the
// current frame. Returns true on success, or false if
// there is no Panda3D window visible. Only needed on
// OSX.
////////////////////////////////////////////////////////////////////
bool P3DInstance::
get_framebuffer() {
if (_swbuffer == NULL || !_instance_window_opened) {
// We don't have a Panda3D window yet.
return;
return false;
}
if (_splash_window != NULL && _splash_window->get_visible()) {
// If the splash window is up, don't draw the Panda3D window.
return;
return false;
}
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());
size_t rowsize = _swbuffer->get_row_size();
if (_swbuffer->ready_for_read()) {
@ -3089,61 +3059,34 @@ paint_window() {
// time.
}
/*
// This is an attempt to paint the frame using the less-deprecated
// Quartz interfaces. Sure does seem like a lot of layers to go
// through just to paint a bitmap.
CFDataRef data =
CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)_reversed_buffer,
y_size * rowsize, kCFAllocatorNull);
return true;
}
#endif // __APPLE__
CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
CGColorSpaceRef color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGImageRef image =
CGImageCreate(x_size, y_size, 8, 32, rowsize, color_space,
kCGImageAlphaFirst | kCGBitmapByteOrder32Little, provider,
NULL, false, kCGRenderingIntentDefault);
CGrafPtr port = _wparams.get_parent_window()._port;
CGContextRef context;
err = QDBeginCGContext(port, &context);
if (err != noErr) {
nout << "Error: QDBeginCGContext\n";
#ifdef __APPLE__
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::paint_window_osx_port
// Access: Private
// Description: Actually paints the rendered image to the browser
// window, using the OSX deprecated QuickDraw
// interfaces.
////////////////////////////////////////////////////////////////////
void P3DInstance::
paint_window_osx_port() {
if (!get_framebuffer()) {
// No Panda3D window is showing.
return;
}
// CGContextTranslateCTM(context, 0.0, win_height);
// CGContextScaleCTM(context, 1.0, -1.0);
int x_size = min(_wparams.get_win_width(), _swbuffer->get_x_size());
int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
size_t rowsize = _swbuffer->get_row_size();
// We have to rely on the clipping rectangle having been set up
// correctly in order to get the proper location to draw the image.
// This isn't completely right, because if the image is slightly
// offscreen, the top left of the clipping rectangle will no longer
// correspond to the top left of the original image.
CGRect rect = CGContextGetClipBoundingBox(context);
nout << "rect: " << rect.origin.x << " " << rect.origin.y
<< " " << rect.size.width << " " << rect.size.height << "\n";
rect.size.width = x_size;
rect.size.height = y_size;
CGContextDrawImage(context, rect, image);
//CGContextSynchronize(context);
CGContextFlush(context);
QDEndCGContext(port, &context);
CGImageRelease(image);
CGColorSpaceRelease(color_space);
CGDataProviderRelease(provider);
CFRelease(data);
*/
// Painting the frame using the deprecated QuickDraw interfaces.
Rect src_rect = {0, 0, y_size, x_size};
Rect ddrc_rect = {0, 0, y_size, x_size};
QDErr err;
GWorldPtr pGWorld;
err = NewGWorldFromPtr(&pGWorld, k32BGRAPixelFormat, &src_rect, 0, 0, 0,
_reversed_buffer, rowsize);
@ -3172,18 +3115,269 @@ paint_window() {
}
DisposeGWorld(pGWorld);
}
#endif // __APPLE__
#ifdef __APPLE__
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::paint_window_osx_cgcontext
// Access: Private
// Description: Actually paints the rendered image to the browser
// window. This is the newer CoreGraphics
// implementation on OSX.
////////////////////////////////////////////////////////////////////
void P3DInstance::
paint_window_osx_cgcontext(CGContextRef context) {
if (!get_framebuffer()) {
// No Panda3D window is showing.
return;
}
int x_size = min(_wparams.get_win_width(), _swbuffer->get_x_size());
int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
size_t rowsize = _swbuffer->get_row_size();
CGContextTranslateCTM(context, 0, y_size);
CGContextScaleCTM(context, 1.0, -1.0);
CFDataRef data =
CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)_reversed_buffer,
y_size * rowsize, kCFAllocatorNull);
CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
//CGColorSpaceRef color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
CGImageRef image =
CGImageCreate(x_size, y_size, 8, 32, rowsize, color_space,
kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
provider, NULL, false, kCGRenderingIntentDefault);
CGRect region = { { 0, 0 }, { x_size, y_size } };
CGContextDrawImage(context, region, image);
CGImageRelease(image);
CGColorSpaceRelease(color_space);
CGDataProviderRelease(provider);
CFRelease(data);
}
#endif // __APPLE__
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::handle_event_osx_event_record
// Access: Private
// Description: Responds to the deprecated Carbon event types in Mac
// OSX.
////////////////////////////////////////////////////////////////////
bool P3DInstance::
handle_event_osx_event_record(const P3D_event_data &event) {
bool retval = false;
#ifdef __APPLE__
assert(event._event_type == P3D_ET_osx_event_record);
EventRecord *er = event._event._osx_event_record._event;
Point pt = er->where;
// Need to ensure we have the correct port set, in order to
// convert the mouse coordinates successfully via
// GlobalToLocal().
const P3D_window_handle &handle = _wparams.get_parent_window();
if (handle._window_handle_type == P3D_WHT_osx_port) {
GrafPtr out_port = handle._handle._osx_port._port;
GrafPtr port_save = NULL;
Boolean port_changed = QDSwapPort(out_port, &port_save);
GlobalToLocal(&pt);
if (port_changed) {
QDSwapPort(port_save, NULL);
}
} else {
// First, convert the coordinates from screen coordinates to
// browser window coordinates.
WindowRef window = handle._handle._osx_cgcontext._window;
CGPoint cgpt = { pt.h, pt.v };
HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
kHICoordSpaceWindow, window);
// Then convert to plugin coordinates.
pt.h = cgpt.x - _wparams.get_win_x();
pt.v = cgpt.y - _wparams.get_win_y();
}
SubprocessWindowBuffer::Event swb_event;
swb_event._source = SubprocessWindowBuffer::ES_none;
swb_event._type = SubprocessWindowBuffer::ET_none;
swb_event._code = 0;
swb_event._flags = 0;
add_carbon_modifier_flags(swb_event._flags, er->modifiers);
switch (er->what) {
case mouseDown:
swb_event._source = SubprocessWindowBuffer::ES_mouse;
swb_event._type = SubprocessWindowBuffer::ET_button_down;
retval = true;
break;
case mouseUp:
swb_event._source = SubprocessWindowBuffer::ES_mouse;
swb_event._type = SubprocessWindowBuffer::ET_button_up;
retval = true;
break;
case keyDown:
case keyUp:
case autoKey:
if (_swbuffer != NULL) {
swb_event._source = SubprocessWindowBuffer::ES_keyboard;
swb_event._code = er->message;
if (er->what == keyUp) {
swb_event._type = SubprocessWindowBuffer::ET_button_up;
} else if (er->what == keyDown) {
swb_event._type = SubprocessWindowBuffer::ET_button_down;
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_again;
}
retval = true;
}
break;
case updateEvt:
paint_window();
retval = true;
break;
case activateEvt:
_mouse_active = ((er->modifiers & 1) != 0);
break;
default:
break;
}
if (_mouse_active) {
swb_event._x = pt.h;
swb_event._y = pt.v;
swb_event._flags |= SubprocessWindowBuffer::EF_mouse_position | SubprocessWindowBuffer::EF_has_mouse;
}
if (_swbuffer != NULL) {
_swbuffer->add_event(swb_event);
}
#endif // __APPLE__
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::add_modifier_flags
// Function: P3DInstance::handle_event_osx_cocoa
// Access: Private
// Description: Responds to the new Cocoa event types in Mac
// OSX.
////////////////////////////////////////////////////////////////////
bool P3DInstance::
handle_event_osx_cocoa(const P3D_event_data &event) {
bool retval = false;
#ifdef __APPLE__
assert(event._event_type == P3D_ET_osx_cocoa);
const P3DCocoaEvent &ce = event._event._osx_cocoa._event;
SubprocessWindowBuffer::Event swb_event;
swb_event._source = SubprocessWindowBuffer::ES_none;
swb_event._type = SubprocessWindowBuffer::ET_none;
swb_event._code = 0;
swb_event._flags = 0;
switch (ce.type) {
case P3DCocoaEventDrawRect:
{
CGContextRef context = ce.data.draw.context;
paint_window_osx_cgcontext(context);
retval = true;
}
break;
case P3DCocoaEventMouseDown:
swb_event._source = SubprocessWindowBuffer::ES_mouse;
swb_event._type = SubprocessWindowBuffer::ET_button_down;
retval = true;
break;
case P3DCocoaEventMouseUp:
swb_event._source = SubprocessWindowBuffer::ES_mouse;
swb_event._type = SubprocessWindowBuffer::ET_button_up;
retval = true;
break;
case P3DCocoaEventKeyDown:
swb_event._source = SubprocessWindowBuffer::ES_keyboard;
swb_event._code = ce.data.key.keyCode << 8;
if (ce.data.key.isARepeat) {
swb_event._type = SubprocessWindowBuffer::ET_button_again;
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_down;
if (ce.data.key.characters[0] > 0 & ce.data.key.characters[0] < 0x100) {
swb_event._code |= ce.data.key.characters[0];
}
}
_modifiers = ce.data.key.modifierFlags;
retval = true;
break;
case P3DCocoaEventKeyUp:
swb_event._source = SubprocessWindowBuffer::ES_keyboard;
swb_event._type = SubprocessWindowBuffer::ET_button_up;
swb_event._code = ce.data.key.keyCode << 8;
_modifiers = ce.data.key.modifierFlags;
retval = true;
break;
case P3DCocoaEventFlagsChanged:
_modifiers = ce.data.key.modifierFlags;
retval = true;
break;
case P3DCocoaEventFocusChanged:
_mouse_active = (ce.data.focus.hasFocus != 0);
retval = true;
break;
}
add_cocoa_modifier_flags(swb_event._flags, _modifiers);
switch (ce.type) {
case P3DCocoaEventMouseDown:
case P3DCocoaEventMouseMoved:
case P3DCocoaEventMouseDragged:
swb_event._x = ce.data.mouse.pluginX;
swb_event._y = ce.data.mouse.pluginY;
swb_event._flags |= SubprocessWindowBuffer::EF_mouse_position;
}
if (_mouse_active) {
swb_event._flags |= SubprocessWindowBuffer::EF_has_mouse;
}
if (_swbuffer != NULL) {
_swbuffer->add_event(swb_event);
}
#endif // __APPLE__
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::add_carbon_modifier_flags
// Access: Private
// Description: OSX only: adds the appropriate bits to the Event flag
// bitmask to correspond to the modifier buttons held in
// the MacOS-style EventRecord::modifiers mask.
////////////////////////////////////////////////////////////////////
void P3DInstance::
add_modifier_flags(unsigned int &swb_flags, int modifiers) {
add_carbon_modifier_flags(unsigned int &swb_flags, int modifiers) {
#ifdef __APPLE__
if (modifiers & cmdKey) {
swb_flags |= SubprocessWindowBuffer::EF_meta_held;
@ -3200,6 +3394,31 @@ add_modifier_flags(unsigned int &swb_flags, int modifiers) {
#endif // __APPLE__
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::add_cocoa_modifier_flags
// Access: Private
// Description: OSX only: adds the appropriate bits to the Event flag
// bitmask to correspond to the modifier buttons held in
// the P3DCocoaEvent modifierFlags mask.
////////////////////////////////////////////////////////////////////
void P3DInstance::
add_cocoa_modifier_flags(unsigned int &swb_flags, int modifiers) {
#ifdef __APPLE__
if (modifiers & NSCommandKeyMask) {
swb_flags |= SubprocessWindowBuffer::EF_meta_held;
}
if (modifiers & NSShiftKeyMask) {
swb_flags |= SubprocessWindowBuffer::EF_shift_held;
}
if (modifiers & NSAlternateKeyMask) {
swb_flags |= SubprocessWindowBuffer::EF_alt_held;
}
if (modifiers & NSControlKeyMask) {
swb_flags |= SubprocessWindowBuffer::EF_control_held;
}
#endif // __APPLE__
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::send_notify
// Access: Private
@ -3284,7 +3503,7 @@ parse_hexdigit(int &result, char digit) {
#ifdef __APPLE__
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::timer_callback
// Access: Private
// Access: Private, Static
// Description: OSX only: this callback is associated with a
// CFRunLoopTimer, to be called periodically for
// updating the frame.
@ -3293,7 +3512,6 @@ void P3DInstance::
timer_callback(CFRunLoopTimerRef timer, void *info) {
P3DInstance *self = (P3DInstance *)info;
self->request_refresh();
//self->paint_window();
}
#endif // __APPLE__

View File

@ -200,7 +200,17 @@ private:
void set_install_label(const string &install_label);
void paint_window();
void add_modifier_flags(unsigned int &swb_flags, int modifiers);
#ifdef __APPLE__
bool get_framebuffer();
void paint_window_osx_port();
void paint_window_osx_cgcontext(CGContextRef context);
#endif // __APPLE__
bool handle_event_osx_event_record(const P3D_event_data &event);
bool handle_event_osx_cocoa(const P3D_event_data &event);
void add_carbon_modifier_flags(unsigned int &swb_flags, int modifiers);
void add_cocoa_modifier_flags(unsigned int &swb_flags, int modifiers);
void send_notify(const string &message);
@ -286,6 +296,7 @@ private:
SubprocessWindowBuffer *_swbuffer;
char *_reversed_buffer;
bool _mouse_active;
unsigned int _modifiers;
CFRunLoopTimerRef _frame_timer;
#endif // __APPLE__

View File

@ -220,51 +220,17 @@ set_install_progress(double install_progress,
////////////////////////////////////////////////////////////////////
bool P3DOsxSplashWindow::
handle_event(const P3D_event_data &event) {
assert(event._event_type == P3D_ET_osx_event_record);
EventRecord *er = event._event._osx_event_record._event;
bool retval = false;
// Need to ensure we have the correct port set, in order to
// convert the mouse coordinates successfully via
// GlobalToLocal().
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_port);
GrafPtr out_port = handle._handle._osx_port._port;
GrafPtr port_save = NULL;
Boolean port_changed = QDSwapPort(out_port, &port_save);
Point pt = er->where;
GlobalToLocal(&pt);
if (port_changed) {
QDSwapPort(port_save, NULL);
}
switch (er->what) {
case updateEvt:
paint_window();
break;
case mouseDown:
set_mouse_data(_mouse_x, _mouse_y, true);
break;
case mouseUp:
set_mouse_data(_mouse_x, _mouse_y, false);
break;
case activateEvt:
_mouse_active = ((er->modifiers & 1) != 0);
break;
default:
break;
if (event._event_type == P3D_ET_osx_event_record) {
retval = handle_event_osx_event_record(event);
} else if (event._event_type == P3D_ET_osx_cocoa) {
retval = handle_event_osx_cocoa(event);
} else {
assert(false);
}
if (_mouse_active) {
set_mouse_data(pt.h, pt.v, _mouse_down);
}
return false;
return retval;
}
////////////////////////////////////////////////////////////////////
@ -297,34 +263,65 @@ paint_window() {
return;
}
GrafPtr out_port = NULL;
if (_toplevel_window != NULL) {
GetPort(&out_port);
if (_toplevel_window != NULL ||
_wparams.get_parent_window()._window_handle_type == P3D_WHT_osx_port) {
// The old QuickDraw-style window handle. We use
// CreateCGContextForPort() to map this to the new
// CoreGraphics-style.
GrafPtr out_port = NULL;
if (_toplevel_window != NULL) {
GetPort(&out_port);
} else {
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_port);
out_port = handle._handle._osx_port._port;
}
CGContextRef context;
OSStatus err = CreateCGContextForPort(out_port, &context);
if (err != noErr) {
nout << "Couldn't create CG context\n";
return;
}
// Adjust for any SetOrigin calls on out_port
SyncCGContextOriginWithPort(context, out_port);
// Move the CG origin to the upper left of the port
Rect port_rect;
GetPortBounds(out_port, &port_rect);
CGContextTranslateCTM(context, 0, (float)(port_rect.bottom - port_rect.top));
// Flip the y axis so that positive Y points down
CGContextScaleCTM(context, 1.0, -1.0);
paint_window_osx_cgcontext(context);
// CGContextSynchronize(context);
CGContextRelease(context);
} else {
// The new CoreGraphics-style window handle. We can draw to this
// directly.
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_port);
out_port = handle._handle._osx_port._port;
assert(handle._window_handle_type == P3D_WHT_osx_cgcontext);
CGContextRef context = handle._handle._osx_cgcontext._context;
paint_window_osx_cgcontext(context);
}
}
CGContextRef context;
OSStatus err = CreateCGContextForPort(out_port, &context);
if (err != noErr) {
nout << "Couldn't create CG context\n";
return;
}
// Adjust for any SetOrigin calls on out_port
SyncCGContextOriginWithPort(context, out_port);
// Move the CG origin to the upper left of the port
Rect port_rect;
GetPortBounds(out_port, &port_rect);
CGContextTranslateCTM(context, 0, (float)(port_rect.bottom - port_rect.top));
// Flip the y axis so that positive Y points down
CGContextScaleCTM(context, 1.0, -1.0);
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::paint_window_osx_cgcontext
// Access: Private
// Description: Redraws the current splash window, using the new
// CoreGraphics interface.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
paint_window_osx_cgcontext(CGContextRef context) {
// Clear the whole region to the background color before beginning.
CGFloat bg_components[] = { _bgcolor_r / 255.0f, _bgcolor_g / 255.0f, _bgcolor_b / 255.0f, 1 };
CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
@ -364,9 +361,122 @@ paint_window() {
if (!_progress_known || _install_progress != 0.0) {
paint_progress_bar(context);
}
}
CGContextSynchronize(context);
CGContextRelease(context);
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::handle_event_osx_event_record
// Access: Private
// Description: Responds to the deprecated Carbon event types in Mac
// OSX.
////////////////////////////////////////////////////////////////////
bool P3DOsxSplashWindow::
handle_event_osx_event_record(const P3D_event_data &event) {
assert(event._event_type == P3D_ET_osx_event_record);
EventRecord *er = event._event._osx_event_record._event;
Point pt = er->where;
// Need to ensure we have the correct port set, in order to
// convert the mouse coordinates successfully via
// GlobalToLocal().
const P3D_window_handle &handle = _wparams.get_parent_window();
if (handle._window_handle_type == P3D_WHT_osx_port) {
GrafPtr out_port = handle._handle._osx_port._port;
GrafPtr port_save = NULL;
Boolean port_changed = QDSwapPort(out_port, &port_save);
GlobalToLocal(&pt);
if (port_changed) {
QDSwapPort(port_save, NULL);
}
} else if (handle._window_handle_type == P3D_WHT_osx_cgcontext) {
// First, convert the coordinates from screen coordinates to
// browser window coordinates.
WindowRef window = handle._handle._osx_cgcontext._window;
CGPoint cgpt = { pt.h, pt.v };
HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
kHICoordSpaceWindow, window);
// Then convert to plugin coordinates.
pt.h = cgpt.x - _wparams.get_win_x();
pt.v = cgpt.y - _wparams.get_win_y();
}
switch (er->what) {
case updateEvt:
paint_window();
break;
case mouseDown:
set_mouse_data(_mouse_x, _mouse_y, true);
break;
case mouseUp:
set_mouse_data(_mouse_x, _mouse_y, false);
break;
case activateEvt:
_mouse_active = ((er->modifiers & 1) != 0);
break;
default:
break;
}
if (_mouse_active) {
set_mouse_data(pt.h, pt.v, _mouse_down);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: P3DOsxSplashWindow::handle_event_osx_cocoa
// Access: Private
// Description: Responds to the new Cocoa event types in Mac
// OSX.
////////////////////////////////////////////////////////////////////
bool P3DOsxSplashWindow::
handle_event_osx_cocoa(const P3D_event_data &event) {
bool retval = false;
assert(event._event_type == P3D_ET_osx_cocoa);
const P3DCocoaEvent &ce = event._event._osx_cocoa._event;
switch (ce.type) {
case P3DCocoaEventDrawRect:
if (_visible) {
CGContextRef context = ce.data.draw.context;
paint_window_osx_cgcontext(context);
retval = true;
}
break;
case P3DCocoaEventMouseDown:
set_mouse_data(ce.data.mouse.pluginX, ce.data.mouse.pluginY, true);
retval = true;
break;
case P3DCocoaEventMouseUp:
set_mouse_data(ce.data.mouse.pluginX, ce.data.mouse.pluginY, false);
retval = true;
break;
case P3DCocoaEventMouseMoved:
case P3DCocoaEventMouseDragged:
set_mouse_data(ce.data.mouse.pluginX, ce.data.mouse.pluginY, _mouse_down);
retval = true;
break;
case P3DCocoaEventFocusChanged:
_mouse_active = (ce.data.focus.hasFocus != 0);
retval = true;
break;
}
return retval;
}
////////////////////////////////////////////////////////////////////
@ -681,13 +791,8 @@ event_callback(EventHandlerCallRef my_handler, EventRef event) {
sizeof(Point), NULL, (void *)&point);
GrafPtr port;
if (_toplevel_window != NULL) {
port = GetWindowPort(_toplevel_window);
} else {
const P3D_window_handle &handle = _wparams.get_parent_window();
assert(handle._window_handle_type == P3D_WHT_osx_port);
port = handle._handle._osx_port._port;
}
assert(_toplevel_window != NULL);
port = GetWindowPort(_toplevel_window);
GrafPtr port_save = NULL;
Boolean port_changed = QDSwapPort(port, &port_save);
GlobalToLocal(&point);

View File

@ -48,6 +48,9 @@ protected:
private:
void paint_window();
void paint_window_osx_cgcontext(CGContextRef context);
bool handle_event_osx_event_record(const P3D_event_data &event);
bool handle_event_osx_cocoa(const P3D_event_data &event);
class OsxImageData;
void load_image(OsxImageData &image, const string &image_filename);

View File

@ -204,6 +204,7 @@ typedef enum {
P3D_WHT_win_hwnd,
P3D_WHT_osx_port,
P3D_WHT_x11_window,
P3D_WHT_osx_cgcontext,
} P3D_window_handle_type;
typedef struct {
@ -220,6 +221,15 @@ typedef struct {
#endif
} P3D_window_handle_osx_port;
/* A CoreGraphics handle, as used by NPAPI with
NPDrawingModelCoreGraphics in effect. */
typedef struct {
#if defined(__APPLE__)
CGContextRef _context;
WindowRef _window;
#endif
} P3D_window_handle_osx_cgcontext;
typedef struct {
#if defined(HAVE_X11)
unsigned long _xwindow;
@ -233,6 +243,7 @@ typedef struct {
P3D_window_handle_win_hwnd _win_hwnd;
P3D_window_handle_osx_port _osx_port;
P3D_window_handle_x11_window _x11_window;
P3D_window_handle_osx_cgcontext _osx_cgcontext;
} _handle;
} P3D_window_handle;
@ -913,6 +924,7 @@ P3D_instance_feed_url_stream_func(P3D_instance *instance, int unique_id,
typedef enum {
P3D_ET_none = 0,
P3D_ET_osx_event_record,
P3D_ET_osx_cocoa,
} P3D_event_type;
typedef struct {
@ -921,10 +933,72 @@ typedef struct {
#endif
} P3D_event_osx_event_record;
// This enum reimplements NPCocoaEventTyped, used below.
typedef enum {
P3DCocoaEventDrawRect = 1,
P3DCocoaEventMouseDown,
P3DCocoaEventMouseUp,
P3DCocoaEventMouseMoved,
P3DCocoaEventMouseEntered,
P3DCocoaEventMouseExited,
P3DCocoaEventMouseDragged,
P3DCocoaEventKeyDown,
P3DCocoaEventKeyUp,
P3DCocoaEventFlagsChanged,
P3DCocoaEventFocusChanged,
P3DCocoaEventWindowFocusChanged,
P3DCocoaEventScrollWheel,
P3DCocoaEventTextInput
} P3DCocoaEventType;
// This structure reimplements NPCocoaEvent, to pass the complex
// cocoa event structures as generated by NPAPI.
typedef struct {
P3DCocoaEventType type;
unsigned int version;
union {
struct {
unsigned int modifierFlags;
double pluginX;
double pluginY;
int buttonNumber;
int clickCount;
double deltaX;
double deltaY;
double deltaZ;
} mouse;
struct {
unsigned int modifierFlags;
const wchar_t *characters;
const wchar_t *charactersIgnoringModifiers;
bool isARepeat;
unsigned short keyCode;
} key;
struct {
CGContextRef context;
double x;
double y;
double width;
double height;
} draw;
struct {
bool hasFocus;
} focus;
struct {
const wchar_t *text;
} text;
} data;
} P3DCocoaEvent;
typedef struct {
P3DCocoaEvent _event;
} P3D_event_osx_cocoa;
typedef struct {
P3D_event_type _event_type;
union {
P3D_event_osx_event_record _osx_event_record;
P3D_event_osx_cocoa _osx_cocoa;
} _event;
} P3D_event_data;

View File

@ -107,6 +107,18 @@ struct UC_NPString {
#define HAS_PLUGIN_THREAD_ASYNC_CALL 1
#endif
// We also need to know whether we have Apple's new Cocoa-based
// drawing and event callbacks.
#if defined(NPVERS_MACOSX_HAS_EVENT_MODELS) && NP_VERSION_MINOR >= NPVERS_MACOSX_HAS_EVENT_MODELS
#define MACOSX_HAS_EVENT_MODELS 1
#endif
// No one defined a symbol for the introduction of the Cocoa drawing,
// but it appears to have been version 19.
#if NP_VERSION_MINOR >= 19
#define MACOSX_HAS_COREGRAPHICS_DRAWING_MODEL 1
#endif
// Appears in startup.cxx.
extern NPNetscapeFuncs *browser;

View File

@ -48,11 +48,15 @@ PPInstance::FileDatas PPInstance::_file_datas;
////////////////////////////////////////////////////////////////////
PPInstance::
PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode,
int16_t argc, char *argn[], char *argv[], NPSavedData *saved) {
int16_t argc, char *argn[], char *argv[], NPSavedData *saved,
P3D_window_handle_type window_handle_type,
P3D_event_type event_type) {
_p3d_inst = NULL;
_npp_instance = instance;
_npp_mode = mode;
_window_handle_type = window_handle_type;
_event_type = event_type;
_script_object = NULL;
_failed = false;
_started = false;
@ -79,6 +83,10 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode,
_got_instance_url = false;
_got_window = false;
_python_window_open = false;
#ifdef __APPLE__
_request_timer = NULL;
#endif // __APPLE__
}
////////////////////////////////////////////////////////////////////
@ -90,6 +98,14 @@ PPInstance::
~PPInstance() {
cleanup_window();
#ifdef __APPLE__
if (_request_timer != NULL) {
CFRunLoopTimerInvalidate(_request_timer);
CFRelease(_request_timer);
_request_timer = NULL;
}
#endif // __APPLE__
if (_p3d_inst != NULL) {
P3D_instance_finish(_p3d_inst);
_p3d_inst = NULL;
@ -124,7 +140,8 @@ PPInstance::
void PPInstance::
begin() {
// On Windows and Linux, we must insist on having this call. OSX
// doesn't necessarily require it.
// doesn't necessarily require it (which is lucky, since it appears
// that Safari doesn't necessarily provide it!)
#ifndef __APPLE__
if (!has_plugin_thread_async_call) {
nout << "Browser version insufficient: we require at least NPAPI version 0.19.\n";
@ -677,17 +694,30 @@ handle_event(void *event) {
return retval;
}
#ifdef __APPLE__
P3D_event_data edata;
memset(&edata, 0, sizeof(edata));
edata._event_type = P3D_ET_osx_event_record;
edata._event._osx_event_record._event = (EventRecord *)event;
edata._event_type = _event_type;
EventAuxData aux_data;
if (_event_type == P3D_ET_osx_event_record) {
#ifdef __APPLE__
edata._event._osx_event_record._event = (EventRecord *)event;
#endif // __APPLE__
#ifdef MACOSX_HAS_EVENT_MODELS
} else if (_event_type == P3D_ET_osx_cocoa) {
// Copy the NPCocoaEvent structure componentwise into a
// P3DCocoaEvent structure.
NPCocoaEvent *np_event = (NPCocoaEvent *)event;
P3DCocoaEvent *p3d_event = &edata._event._osx_cocoa._event;
copy_cocoa_event(p3d_event, np_event, aux_data);
#endif // MACOSX_HAS_EVENT_MODELS
}
if (P3D_instance_handle_event(_p3d_inst, &edata)) {
retval = true;
}
#endif // __APPLE__
return retval;
}
@ -962,14 +992,18 @@ request_ready(P3D_instance *instance) {
PPInstance *inst = (PPInstance *)(instance->_user_data);
assert(inst != NULL);
{
static int n = 0;
nout << "request_ready " << ++n << "\n";
}
if (has_plugin_thread_async_call) {
#ifdef HAS_PLUGIN_THREAD_ASYNC_CALL
// Since we are running at least Gecko 1.9, and we have this very
// useful function, let's use it to ask the browser to call us back
// in the main thread.
if ((void *)browser->pluginthreadasynccall != (void *)NULL) {
browser->pluginthreadasynccall(inst->_npp_instance, browser_sync_callback, NULL);
}
assert((void *)browser->pluginthreadasynccall != (void *)NULL);
browser->pluginthreadasynccall(inst->_npp_instance, browser_sync_callback, NULL);
#endif // HAS_PLUGIN_THREAD_ASYNC_CALL
} else {
@ -986,8 +1020,28 @@ request_ready(P3D_instance *instance) {
PostMessage((HWND)(win->window), WM_USER, 0, 0);
}
#endif // _WIN32
// On Mac and Linux, we ignore this asynchronous event, and rely on
// detecting it within HandleEvent() and similar callbacks.
#ifdef __APPLE__
// Use an OSX timer to forward this event to the main thread.
// Stop any previously-started timer--we don't need more than one.
if (inst->_request_timer != NULL) {
CFRunLoopTimerInvalidate(inst->_request_timer);
CFRelease(inst->_request_timer);
inst->_request_timer = NULL;
}
// And start a new one.
CFRunLoopTimerContext timer_context;
memset(&timer_context, 0, sizeof(timer_context));
timer_context.info = inst;
inst->_request_timer = CFRunLoopTimerCreate
(NULL, 0, 0, 0, 0, timer_callback, &timer_context);
CFRunLoopRef run_loop = CFRunLoopGetMain();
CFRunLoopAddTimer(run_loop, inst->_request_timer, kCFRunLoopCommonModes);
#endif // __APPLE__
// Doesn't appear to be a reliable way to simulate this in Linux.
}
}
@ -1380,14 +1434,17 @@ send_window() {
y = 0;
#elif defined(__APPLE__)
NP_Port *port = (NP_Port *)_window.window;
parent_window._window_handle_type = P3D_WHT_osx_port;
parent_window._handle._osx_port._port = port->port;
/*
NP_CGContext *context = (NP_CGContext *)_window.window;
parent_window._context = context->context;
parent_window._window = (WindowRef)context->window;
*/
parent_window._window_handle_type = _window_handle_type;
if (_window_handle_type == P3D_WHT_osx_port) {
NP_Port *port = (NP_Port *)_window.window;
parent_window._handle._osx_port._port = port->port;
} else if (_window_handle_type == P3D_WHT_osx_cgcontext) {
NP_CGContext *context = (NP_CGContext *)_window.window;
if (context != NULL) {
parent_window._handle._osx_cgcontext._context = context->context;
parent_window._handle._osx_cgcontext._window = (WindowRef)context->window;
}
}
#elif defined(HAVE_X11)
// We make it an 'unsigned long' instead of 'Window'
@ -1410,14 +1467,17 @@ send_window() {
}
#elif defined(__APPLE__)
NP_Port *port = (NP_Port *)_window.window;
parent_window._window_handle_type = P3D_WHT_osx_port;
parent_window._handle._osx_port._port = port->port;
/*
NP_CGContext *context = (NP_CGContext *)_window.window;
parent_window._context = context->context;
parent_window._window = (WindowRef)context->window;
*/
parent_window._window_handle_type = _window_handle_type;
if (_window_handle_type == P3D_WHT_osx_port) {
NP_Port *port = (NP_Port *)_window.window;
parent_window._handle._osx_port._port = port->port;
} else if (_window_handle_type == P3D_WHT_osx_cgcontext) {
NP_CGContext *context = (NP_CGContext *)_window.window;
if (context != NULL) {
parent_window._handle._osx_cgcontext._context = context->context;
parent_window._handle._osx_cgcontext._window = (WindowRef)context->window;
}
}
#elif defined(HAVE_X11)
unsigned long win;
@ -1440,7 +1500,7 @@ send_window() {
#endif
P3D_window_type window_type = P3D_WT_embedded;
if (_window.window == NULL) {
if (_window.window == NULL && _event_type != P3D_ET_osx_cocoa) {
// No parent window: it must be a hidden window.
window_type = P3D_WT_hidden;
} else if (_window.width == 0 || _window.height == 0) {
@ -1654,6 +1714,156 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
}
#endif // _WIN32
#ifdef MACOSX_HAS_EVENT_MODELS
////////////////////////////////////////////////////////////////////
// Function: PPInstance::copy_cocoa_event
// Access: Private, Static
// Description: Copies the NPCocoaEvent structure componentwise into
// a P3DCocoaEvent structure, for passing into the core
// API.
//
// The aux_data object is used to manage temporary
// storage on the strings created for the event.
////////////////////////////////////////////////////////////////////
void PPInstance::
copy_cocoa_event(P3DCocoaEvent *p3d_event, NPCocoaEvent *np_event,
EventAuxData &aux_data) {
p3d_event->version = np_event->version;
switch (np_event->type) {
case NPCocoaEventDrawRect:
p3d_event->type = P3DCocoaEventDrawRect;
break;
case NPCocoaEventMouseDown:
p3d_event->type = P3DCocoaEventMouseDown;
break;
case NPCocoaEventMouseUp:
p3d_event->type = P3DCocoaEventMouseUp;
break;
case NPCocoaEventMouseMoved:
p3d_event->type = P3DCocoaEventMouseMoved;
break;
case NPCocoaEventMouseEntered:
p3d_event->type = P3DCocoaEventMouseEntered;
break;
case NPCocoaEventMouseExited:
p3d_event->type = P3DCocoaEventMouseExited;
break;
case NPCocoaEventMouseDragged:
p3d_event->type = P3DCocoaEventMouseDragged;
break;
case NPCocoaEventKeyDown:
p3d_event->type = P3DCocoaEventKeyDown;
break;
case NPCocoaEventKeyUp:
p3d_event->type = P3DCocoaEventKeyUp;
break;
case NPCocoaEventFlagsChanged:
p3d_event->type = P3DCocoaEventFlagsChanged;
break;
case NPCocoaEventFocusChanged:
p3d_event->type = P3DCocoaEventFocusChanged;
break;
case NPCocoaEventWindowFocusChanged:
p3d_event->type = P3DCocoaEventWindowFocusChanged;
break;
case NPCocoaEventScrollWheel:
p3d_event->type = P3DCocoaEventScrollWheel;
break;
case NPCocoaEventTextInput:
p3d_event->type = P3DCocoaEventTextInput;
break;
}
switch (np_event->type) {
case NPCocoaEventDrawRect:
p3d_event->data.draw.context = np_event->data.draw.context;
p3d_event->data.draw.x = np_event->data.draw.x;
p3d_event->data.draw.y = np_event->data.draw.y;
p3d_event->data.draw.width = np_event->data.draw.width;
p3d_event->data.draw.height = np_event->data.draw.height;
break;
case NPCocoaEventMouseDown:
case NPCocoaEventMouseUp:
case NPCocoaEventMouseMoved:
case NPCocoaEventMouseEntered:
case NPCocoaEventMouseExited:
case NPCocoaEventMouseDragged:
case NPCocoaEventScrollWheel:
p3d_event->data.mouse.modifierFlags = np_event->data.mouse.modifierFlags;
p3d_event->data.mouse.pluginX = np_event->data.mouse.pluginX;
p3d_event->data.mouse.pluginY = np_event->data.mouse.pluginY;
p3d_event->data.mouse.buttonNumber = np_event->data.mouse.buttonNumber;
p3d_event->data.mouse.clickCount = np_event->data.mouse.clickCount;
p3d_event->data.mouse.deltaX = np_event->data.mouse.deltaX;
p3d_event->data.mouse.deltaY = np_event->data.mouse.deltaY;
p3d_event->data.mouse.deltaZ = np_event->data.mouse.deltaZ;
break;
case NPCocoaEventKeyDown:
case NPCocoaEventKeyUp:
case NPCocoaEventFlagsChanged:
p3d_event->data.key.modifierFlags = np_event->data.key.modifierFlags;
p3d_event->data.key.characters =
make_ansi_string(aux_data._characters, np_event->data.key.characters);
p3d_event->data.key.charactersIgnoringModifiers =
make_ansi_string(aux_data._characters_im, np_event->data.key.charactersIgnoringModifiers);
p3d_event->data.key.isARepeat = np_event->data.key.isARepeat;
p3d_event->data.key.keyCode = np_event->data.key.keyCode;
break;
case NPCocoaEventFocusChanged:
case NPCocoaEventWindowFocusChanged:
p3d_event->data.focus.hasFocus = np_event->data.focus.hasFocus;
break;
case NPCocoaEventTextInput:
p3d_event->data.text.text =
make_ansi_string(aux_data._text, np_event->data.text.text);
break;
}
}
#endif // MACOSX_HAS_EVENT_MODELS
#ifdef MACOSX_HAS_EVENT_MODELS
////////////////////////////////////////////////////////////////////
// Function: PPInstance::make_ansi_string
// Access: Private, Static
// Description: OSX only: Fills result with the unicode characters in
// the NPNSString. Also returns result.c_str().
////////////////////////////////////////////////////////////////////
const wchar_t *PPInstance::
make_ansi_string(wstring &result, NPNSString *ns_string) {
// An NPNSString is really just an NSString, which is itself just a
// CFString.
CFStringRef cfstr = (CFStringRef)ns_string;
CFIndex length = CFStringGetLength(cfstr);
result.clear();
for (CFIndex i = 0; i < length; ++i) {
result += (wchar_t)CFStringGetCharacterAtIndex(cfstr, i);
}
return result.c_str();
}
#endif // MACOSX_HAS_EVENT_MODELS
#ifdef __APPLE__
////////////////////////////////////////////////////////////////////
// Function: PPInstance::timer_callback
// Access: Private, Static
// Description: OSX only: this callback is associated with a
// CFRunLoopTimer; it's used to forward request messages
// to the main thread.
////////////////////////////////////////////////////////////////////
void PPInstance::
timer_callback(CFRunLoopTimerRef timer, void *info) {
PPInstance *self = (PPInstance *)info;
self->handle_request_loop();
}
#endif // __APPLE__
////////////////////////////////////////////////////////////////////
// Function: PPInstance::StreamingFileData::Constructor
// Access: Public

View File

@ -35,7 +35,9 @@ class PPDownloadRequest;
class PPInstance {
public:
PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode,
int16_t argc, char *argn[], char *argv[], NPSavedData *saved);
int16_t argc, char *argn[], char *argv[], NPSavedData *saved,
P3D_window_handle_type window_handle_type,
P3D_event_type event_type);
~PPInstance();
void begin();
@ -99,9 +101,28 @@ private:
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
#endif // _WIN32
class EventAuxData {
public:
wstring _characters;
wstring _characters_im;
wstring _text;
};
#ifdef MACOSX_HAS_EVENT_MODELS
static void copy_cocoa_event(P3DCocoaEvent *p3d_event,
NPCocoaEvent *np_event,
EventAuxData &aux_data);
static const wchar_t *make_ansi_string(wstring &result, NPNSString *ns_string);
#endif // MACOSX_HAS_EVENT_MODELS
#ifdef __APPLE__
static void timer_callback(CFRunLoopTimerRef timer, void *info);
#endif // __APPLE__
private:
NPP _npp_instance;
unsigned int _npp_mode;
P3D_window_handle_type _window_handle_type;
P3D_event_type _event_type;
typedef vector<P3D_token> Tokens;
Tokens _tokens;
@ -165,6 +186,10 @@ private:
LONG_PTR _orig_window_proc;
#endif // _WIN32
#ifdef __APPLE__
CFRunLoopTimerRef _request_timer;
#endif // __APPLE__
bool _python_window_open;
PPToplevelObject *_script_object;

View File

@ -194,7 +194,12 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
#ifdef HAS_PLUGIN_THREAD_ASYNC_CALL
// Check if the browser offers this very useful call.
if (browser_major > 0 || browser_minor >= NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) {
has_plugin_thread_async_call = true;
if ((void *)browser->pluginthreadasynccall == (void *)NULL) {
nout << "Browser should have PLUGIN_THREAD_ASYNC_CALL, but the pointer is NULL.\n";
has_plugin_thread_async_call = false;
} else {
has_plugin_thread_async_call = true;
}
}
#endif
@ -287,30 +292,65 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode,
int16_t argc, char *argn[], char *argv[], NPSavedData *saved) {
nout << "new instance " << instance << "\n";
/*
P3D_window_handle_type window_handle_type = P3D_WHT_none;
P3D_event_type event_type = P3D_ET_none;
#ifdef __APPLE__
// We have to request the "core graphics" drawing model to be
// The default drawing model for Apple is via the deprecated
// QuickDraw GrafPtr, and the default event model is via the
// deprecated Carbon EventRecord.
window_handle_type = P3D_WHT_osx_port;
event_type = P3D_ET_osx_event_record;
// But we have to request the CoreGraphics drawing model to be
// compatible with Snow Leopard.
NPBool supportsCoreGraphics = false;
NPBool supports_core_graphics = false;
#ifdef MACOSX_HAS_COREGRAPHICS_DRAWING_MODEL
NPError err = browser->getvalue(instance,
NPNVsupportsCoreGraphicsBool,
&supportsCoreGraphics);
if (err != NPERR_NO_ERROR || !supportsCoreGraphics) {
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
// Set the drawing model
err = browser->setvalue(instance,
(NPPVariable)NPNVpluginDrawingModel,
(void *)NPDrawingModelCoreGraphics);
&supports_core_graphics);
if (err != NPERR_NO_ERROR) {
return NPERR_INCOMPATIBLE_VERSION_ERROR;
supports_core_graphics = false;
}
#endif
*/
if (supports_core_graphics) {
// Set the drawing model
err = browser->setvalue(instance,
(NPPVariable)NPNVpluginDrawingModel,
(void *)NPDrawingModelCoreGraphics);
if (err == NPERR_NO_ERROR) {
window_handle_type = P3D_WHT_osx_cgcontext;
}
}
#endif // MACOSX_HAS_COREGRAPHICS_DRAWING_MODEL
nout << "supports_core_graphics = " << (bool)supports_core_graphics
<< " window_handle_type = " << window_handle_type << "\n";
// And Snow Leopard also wants the new Cocoa event model.
NPBool supports_cocoa = false;
#ifdef MACOSX_HAS_EVENT_MODELS
err = browser->getvalue(instance, NPNVsupportsCocoaBool, &supports_cocoa);
if (err != NPERR_NO_ERROR) {
supports_cocoa = false;
}
if (supports_cocoa) {
// Set the event model
err = browser->setvalue(instance,
(NPPVariable)NPPVpluginEventModel,
(void *)NPEventModelCocoa);
if (err == NPERR_NO_ERROR) {
event_type = P3D_ET_osx_cocoa;
}
}
#endif // MACOSX_HAS_EVENT_MODELS
nout << "supports_cocoa = " << (bool)supports_cocoa
<< " event_type = " << event_type << "\n";
#endif // __APPLE__
PPInstance *inst = new PPInstance(pluginType, instance, mode,
argc, argn, argv, saved);
argc, argn, argv, saved,
window_handle_type, event_type);
instance->pdata = inst;
nout << "new instance->pdata = " << inst << "\n";