mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
finally committing that blooming snow leopard support
This commit is contained in:
parent
b2e2877d89
commit
dd007746b5
@ -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__
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user