Add support for loading cfm plugins in OSX mach-o builds.

Changes backported from the CHIMERA_M1_0_1_BRANCH branch.
Bug #155256 r=peterl sr=sfraser


git-svn-id: svn://10.0.0.236/trunk@133054 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
seawood%netscape.com
2002-11-06 01:24:57 +00:00
parent a4274ab9cb
commit 8ae058aa20
14 changed files with 718 additions and 417 deletions

View File

@@ -309,7 +309,8 @@ public:
NS_DECL_NSITIMERCALLBACK
void CancelTimer();
void StartTimer();
// nsIScrollPositionListener interface
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
@@ -323,9 +324,10 @@ public:
void SetPluginHost(nsIPluginHost* aHost);
#ifdef XP_MAC
void FixUpPluginWindow();
#if defined(XP_MAC) || defined(XP_MACOSX)
nsPluginPort* FixUpPluginWindow();
void GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord& aMacEvent);
void Composite();
#endif
private:
@@ -357,7 +359,7 @@ private:
static void ConvertTwipsToPixels(nsIPresContext& aPresContext, nsRect& aTwipsRect, nsRect& aPixelRect);
// Mac specific code to fix up port position and clip during paint
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
// get the absolute widget position and clip
static void GetWidgetPosClipAndVis(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY, nsRect& aClipRect, PRBool& aIsVisible);
// convert relative coordinates to absolute
@@ -366,9 +368,7 @@ static void ConvertTwipsToPixels(nsIPresContext& aPresContext, nsRect& aTwipsRec
nsObjectFrame::~nsObjectFrame()
{
// beard: stop the timer explicitly to reduce reference count.
if (nsnull != mInstanceOwner) {
mInstanceOwner->CancelTimer();
mInstanceOwner->Destroy();
}
@@ -796,7 +796,7 @@ nsObjectFrame::CreateWidget(nsIPresContext* aPresContext,
// Turn off double buffering on the Mac. This depends on bug 49743 and partially
// fixes 32327, 19931 amd 51787
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
nsCOMPtr<nsIPref> prefs(do_GetService(kPrefServiceCID));
PRBool doubleBuffer = PR_FALSE;
prefs ? prefs->GetBoolPref("plugin.enable_double_buffer", &doubleBuffer) : 0;
@@ -1273,7 +1273,7 @@ nsObjectFrame::InstantiatePlugin(nsIPresContext* aPresContext,
// happen until we have finished the reflow process.
window->clipRect.top = 0;
window->clipRect.left = 0;
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
window->clipRect.bottom = NSTwipsToIntPixels(aMetrics.height, t2p);
window->clipRect.right = NSTwipsToIntPixels(aMetrics.width, t2p);
#else
@@ -1349,7 +1349,7 @@ nsObjectFrame::ReinstantiatePlugin(nsIPresContext* aPresContext, nsHTMLReflowMet
// ignore this for now on the Mac because the widget is not properly positioned
// yet and won't be until we have finished the reflow process.
#ifndef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
window->clipRect.top = 0;
window->clipRect.left = 0;
window->clipRect.bottom = NSTwipsToIntPixels(aMetrics.height, t2p);
@@ -1559,9 +1559,9 @@ nsObjectFrame::DidReflow(nsIPresContext* aPresContext,
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
mInstanceOwner->FixUpPluginWindow();
#endif // XP_MAC
#endif // XP_MAC || XP_MACOSX
if (bHidden)
return rv;
@@ -1717,7 +1717,7 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext,
window.window = &port;
npprint.print.embedPrint.platformPrint = (void*)window.window;
#elif defined (XP_UNIX)
#elif defined (XP_UNIX) && !defined(XP_MACOSX)
// UNIX does things completely differently
PRUnichar *printfile = nsnull;
if (printSettings) {
@@ -1748,7 +1748,6 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext,
// send off print info to plugin
rv = pi->Print(&npprint);
#if defined(XP_MAC) && !TARGET_CARBON
// Clean-up on Mac
::SetOrigin(0,0);
@@ -1766,7 +1765,7 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext,
}
// Screen painting code
#if defined (XP_MAC)
#if defined (XP_MAC) || defined(XP_MACOSX)
// delegate all painting to the plugin instance.
if ((NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) && mInstanceOwner)
mInstanceOwner->Paint(aDirtyRect);
@@ -2182,7 +2181,7 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
NS_IF_RELEASE(mWidget);
mContext = nsnull;
#ifdef XP_UNIX
#if defined(XP_UNIX) && !defined(XP_MACOSX)
// the mem for this struct is allocated
// by PR_MALLOC in ns4xPluginInstance.cpp:ns4xPluginInstance::SetWindow()
if (mPluginWindow && mPluginWindow->ws_info) {
@@ -3132,15 +3131,15 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
// Here's where we forward events to plugins.
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
#if TARGET_CARBON
static void InitializeEventRecord(EventRecord* event)
{
memset(event, 0, sizeof(EventRecord));
GetGlobalMouse(&event->where);
event->when = TickCount();
event->modifiers = GetCurrentKeyModifiers();
::GetGlobalMouse(&event->where);
event->when = ::TickCount();
event->modifiers = ::GetCurrentKeyModifiers();
}
#else
inline void InitializeEventRecord(EventRecord* event) { ::OSEventAvail(0, event); }
@@ -3182,17 +3181,19 @@ void nsPluginInstanceOwner::GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord
nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
if (mInstance != NULL) {
EventRecord scrollEvent;
InitializeEventRecord(&scrollEvent);
scrollEvent.what = nsPluginEventType_ScrollingBeginsEvent;
nsPluginPort* pluginPort = GetPluginPort();
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(pluginPort->port) };
if (pluginPort) {
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(GetWindowFromPort(pluginPort->port)) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
}
#endif
return NS_OK;
@@ -3200,20 +3201,28 @@ nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScr
nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
if (mInstance != NULL) {
EventRecord scrollEvent;
InitializeEventRecord(&scrollEvent);
scrollEvent.what = nsPluginEventType_ScrollingEndsEvent;
nsPluginPort* pluginPort = GetPluginPort();
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (!eventHandled) {
nsPluginPort* pluginPort = FixUpPluginWindow();
if (pluginPort) {
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(GetWindowFromPort(pluginPort->port)) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
#if defined(XP_MACOSX)
// FIXME - Only invalidate the newly revealed amount.
// mWidget->Invalidate(PR_TRUE);
Composite();
#else
if (!eventHandled) {
nsRect bogus(0,0,0,0);
Paint(bogus, 0); // send an update event to the plugin
}
#endif
}
}
#endif
@@ -3235,10 +3244,10 @@ nsresult nsPluginInstanceOwner::Blur(nsIDOMEvent * aFocusEvent)
nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
{
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
return NS_ERROR_FAILURE; // means consume event
// continue only for cases without child window
// continue only for cases without child window
#endif
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aFocusEvent));
@@ -3370,7 +3379,7 @@ nsresult nsPluginInstanceOwner::KeyUp(nsIDOMEvent* aKeyEvent)
nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
{
#ifdef XP_MAC // send KeyPress events only on Mac
#if defined(XP_MAC) || defined(XP_MACOSX) // send KeyPress events only on Mac
return DispatchKeyToPlugin(aKeyEvent);
#else
if (mInstance) {
@@ -3389,7 +3398,7 @@ nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
{
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
return NS_ERROR_FAILURE; // means consume event
// continue only for cases without child window
@@ -3427,7 +3436,7 @@ nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
nsresult
nsPluginInstanceOwner::MouseMove(nsIDOMEvent* aMouseEvent)
{
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
return NS_ERROR_FAILURE; // means consume event
// continue only for cases without child window
@@ -3459,7 +3468,7 @@ nsPluginInstanceOwner::MouseMove(nsIDOMEvent* aMouseEvent)
nsresult
nsPluginInstanceOwner::MouseDown(nsIDOMEvent* aMouseEvent)
{
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
return NS_ERROR_FAILURE; // means consume event
// continue only for cases without child window
@@ -3523,7 +3532,7 @@ nsPluginInstanceOwner::MouseOut(nsIDOMEvent* aMouseEvent)
nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
{
#ifndef XP_MAC
#if !(defined(XP_MAC) || defined(XP_MACOSX))
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
return NS_ERROR_FAILURE; // means consume event
// continue only for cases without child window
@@ -3572,7 +3581,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
if (!mInstance) // if mInstance is null, we shouldn't be here
return rv;
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
if (mWidget != NULL) { // check for null mWidget
EventRecord* event = (EventRecord*)anEvent.nativeMsg;
if ((event == NULL) || (event->what == nullEvent) ||
@@ -3585,10 +3594,12 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
GUItoMacEvent(anEvent, macEvent);
event = &macEvent;
}
nsPluginPort* port = (nsPluginPort*)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(port->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
nsPluginPort* pluginPort = FixUpPluginWindow();
if (pluginPort) {
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(GetWindowFromPort(pluginPort->port)) };
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
if (eventHandled && !(anEvent.message == NS_MOUSE_LEFT_BUTTON_DOWN && !mContentFocused))
rv = nsEventStatus_eConsumeNoDefault;
}
@@ -3615,6 +3626,9 @@ nsPluginInstanceOwner::Destroy()
nsCOMPtr<nsIContent> content;
mOwner->GetContent(getter_AddRefs(content));
// stop the timer explicitly to reduce reference count.
CancelTimer();
// unregister context menu listener
if (mCXMenuListener) {
mCXMenuListener->Destroy(mOwner);
@@ -3724,9 +3738,7 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, PRUint32 ndc)
if(!mInstance)
return;
#ifdef XP_MAC
nsPluginPort* pluginPort = GetPluginPort();
#if defined(XP_MAC) || defined(XP_MACOSX)
#ifdef DO_DIRTY_INTERSECT // aDirtyRect isn't always correct, see bug 56128
nsPoint rel(aDirtyRect.x, aDirtyRect.y);
nsPoint abs(0,0);
@@ -3741,16 +3753,24 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, PRUint32 ndc)
nsRect absDirtyRectInPixels;
ConvertTwipsToPixels(*mContext, absDirtyRect, absDirtyRectInPixels);
#endif
FixUpPluginWindow();
EventRecord updateEvent;
InitializeEventRecord(&updateEvent);
updateEvent.what = updateEvt;
updateEvent.message = UInt32(pluginPort->port);
nsPluginPort* pluginPort = FixUpPluginWindow();
if (pluginPort) {
EventRecord updateEvent;
InitializeEventRecord(&updateEvent);
updateEvent.what = updateEvt;
updateEvent.message = UInt32(GetWindowFromPort(pluginPort->port));
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
GrafPtr oldPort;
::GetPort(&oldPort);
::SetPort((GrafPtr)pluginPort->port);
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(GetWindowFromPort(pluginPort->port)) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
::SetPort(oldPort);
}
#endif
#ifdef XP_WIN
@@ -3781,12 +3801,13 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, PRUint32 ndc)
NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* /* timer */)
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
// validate the plugin clipping information by syncing the plugin window info to
// reflect the current widget location. This makes sure that everything is updated
// correctly in the event of scrolling in the window.
FixUpPluginWindow();
if (mInstance != NULL) {
nsPluginPort* pluginPort = FixUpPluginWindow();
if (pluginPort) {
EventRecord idleEvent;
InitializeEventRecord(&idleEvent);
idleEvent.what = nullEvent;
@@ -3796,23 +3817,28 @@ NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* /* timer */)
if (!mWidgetVisible)
idleEvent.where.h = idleEvent.where.v = 20000;
nsPluginPort* pluginPort = GetPluginPort();
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(pluginPort->port) };
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(GetWindowFromPort(pluginPort->port)) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
}
#endif
return NS_OK;
}
#ifndef REPEATING_TIMERS
// reprime the timer? currently have to create a new timer for each call, which is
// kind of wasteful. need to get periodic timers working on all platforms.
nsresult rv;
mPluginTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (NS_SUCCEEDED(rv))
mPluginTimer->InitWithCallback(this, 1020 / 60, nsITimer::TYPE_ONE_SHOT);
void nsPluginInstanceOwner::StartTimer()
{
#if defined(XP_MAC) || defined(XP_MACOSX)
nsresult rv;
// start a periodic timer to provide null events to the plugin instance.
if (!mPluginTimer) {
mPluginTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (rv == NS_OK)
rv = mPluginTimer->InitWithCallback(this, 1020 / 60, nsITimer::TYPE_REPEATING_SLACK);
}
#endif
return NS_OK;
}
void nsPluginInstanceOwner::CancelTimer()
@@ -4024,13 +4050,8 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
mPluginWindow->type = nsPluginWindowType_Window;
mPluginWindow->window = GetPluginPort();
#if defined(XP_MAC)
// Is this needed in the windowless case ???
// start a periodic timer to provide null events to the plugin instance.
mPluginTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (rv == NS_OK)
rv = mPluginTimer->InitWithCallback(this, 1020 / 60, nsITimer::TYPE_REPEATING_SLACK);
#endif
// start the idle timer.
StartTimer();
}
}
}
@@ -4059,7 +4080,7 @@ static void ConvertTwipsToPixels(nsIPresContext& aPresContext, nsRect& aTwipsRec
}
// Mac specific code to fix up the port location and clipping region
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
// calculate the absolute position and clip for a widget
// and use other windows in calculating the clip
static void GetWidgetPosClipAndVis(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY,
@@ -4110,10 +4131,6 @@ static void GetWidgetPosClipAndVis(nsIWidget* aWidget,nscoord& aAbsX, nscoord& a
// if we are not visible, clear out the plugin's clip so it won't paint
if (!aIsVisible)
aClipRect.Empty();
//printf("--------------\n");
//printf("Widget clip X %d Y %d rect %d %d %d %d\n", aAbsX, aAbsY, aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height );
//printf("--------------\n");
}
#ifdef DO_DIRTY_INTERSECT
@@ -4177,15 +4194,21 @@ inline PRUint16 COLOR8TOCOLOR16(PRUint8 color8)
return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */
}
void nsPluginInstanceOwner::FixUpPluginWindow()
nsPluginPort* nsPluginInstanceOwner::FixUpPluginWindow()
{
if (!mWidget || !mPluginWindow)
return;
return nsnull;
nsPluginPort* pluginPort = GetPluginPort();
nscoord absWidgetX = 0;
nscoord absWidgetY = 0;
nsRect widgetClip(0,0,0,0);
#if defined(MOZ_WIDGET_COCOA)
if (!pluginPort)
return nsnull;
#endif
// first, check our view for CSS visibility style
nsIView *view;
mOwner->GetView(mContext, &view);
@@ -4195,12 +4218,17 @@ void nsPluginInstanceOwner::FixUpPluginWindow()
GetWidgetPosClipAndVis(mWidget,absWidgetX,absWidgetY,widgetClip,isVisible);
if (mWidgetVisible != isVisible)
mWidgetVisible = isVisible;
#if defined(MOZ_WIDGET_COCOA)
// set the port coordinates
mPluginWindow->x = -pluginPort->portx;
mPluginWindow->y = -pluginPort->porty;
widgetClip.x += mPluginWindow->x - absWidgetX;
widgetClip.y += mPluginWindow->y - absWidgetY;
#else
// set the port coordinates
mPluginWindow->x = absWidgetX;
mPluginWindow->y = absWidgetY;
#endif
// fix up the clipping region
mPluginWindow->clipRect.top = widgetClip.y;
@@ -4212,7 +4240,6 @@ void nsPluginInstanceOwner::FixUpPluginWindow()
// the background color needs to be set here on the plugin port
GrafPtr savePort;
::GetPort(&savePort); // save our current port
nsPluginPort* pluginPort = GetPluginPort();
::SetPort((GrafPtr)pluginPort->port);
nscolor color = mWidget->GetBackgroundColor();
@@ -4222,7 +4249,46 @@ void nsPluginInstanceOwner::FixUpPluginWindow()
macColor.blue = COLOR8TOCOLOR16(NS_GET_B(color));
::RGBBackColor(&macColor);
::SetPort(savePort); // restore port
if (mWidgetVisible != isVisible) {
mWidgetVisible = isVisible;
// must do this to disable async Java Applet drawing
if (isVisible) {
mInstance->SetWindow(mPluginWindow);
} else {
mInstance->SetWindow(nsnull);
// switching states, do not draw
pluginPort = nsnull;
}
}
#if defined(MOZ_WIDGET_COCOA)
if (!mWidgetVisible) {
mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
}
#endif
return pluginPort;
}
#endif // XP_MAC
void nsPluginInstanceOwner::Composite()
{
//no reference count on view
nsIView* view;
nsresult rv = mOwner->GetView(mContext, &view);
if (NS_SUCCEEDED(rv) && view) {
nsIViewManager* manager;
rv = view->GetViewManager(manager);
//set flags to not do a synchronous update, force update does the redraw
if (NS_SUCCEEDED(rv) && manager) {
rv = manager->UpdateView(view, NS_VMREFRESH_IMMEDIATE);
NS_RELEASE(manager);
}
}
}
#endif // XP_MAC || XP_MACOSX