Implement full-page plugins on Mac bug 35682 a=av sr=attinasi

git-svn-id: svn://10.0.0.236/trunk@91186 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
peterlubczynski%netscape.com 2001-04-03 22:18:59 +00:00
parent 120df2142a
commit a2ae9333a1
6 changed files with 596 additions and 18 deletions

View File

@ -120,7 +120,11 @@
#elif defined(XP_UNIX) || defined(XP_BEOS)
#define PLUGIN_DLL "libgkplugin" MOZ_DLL_SUFFIX
#elif defined(XP_MAC)
#define PLUGIN_DLL "PLUGIN_DLL"
#if defined(NS_DEBUG)
#define PLUGIN_DLL "pluginDebug.shlb"
#else
#define PLUGIN_DLL "plugin.shlb"
#endif // ifdef NS_DEBUG
#endif
#define REL_PLUGIN_DLL "rel:" PLUGIN_DLL

View File

@ -44,6 +44,11 @@
#include "nsIDOMDocument.h"
#include "nsPluginViewer.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
// Class IDs
static NS_DEFINE_IID(kChildWindowCID, NS_CHILD_CID);
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
@ -51,7 +56,6 @@ static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
// Interface IDs
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENTVIEWER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
@ -76,8 +80,10 @@ public:
PluginViewerImpl* mViewer;
nsIStreamListener* mNextStream;
};
class pluginInstanceOwner : public nsIPluginInstanceOwner
class pluginInstanceOwner : public nsIPluginInstanceOwner,
public nsITimerCallback
{
public:
pluginInstanceOwner();
@ -104,18 +110,35 @@ public:
NS_IMETHOD ShowStatus(const char *aStatusMsg);
NS_IMETHOD GetDocument(nsIDocument* *aDocument);
//nsIEventListener interface
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
//locals
NS_IMETHOD Init(PluginViewerImpl *aViewer, nsIWidget *aWindow);
// nsITimerCallback interface
NS_IMETHOD_(void) Notify(nsITimer *timer);
void CancelTimer();
#ifdef XP_MAC
void GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord& aMacEvent);
nsPluginPort* GetPluginPort();
void FixUpPluginWindow();
#endif
private:
nsPluginWindow mPluginWindow;
nsIPluginInstance *mInstance;
nsIWidget *mWindow; //we do not addref this...
PluginViewerImpl *mViewer; //we do not addref this...
nsCOMPtr<nsITimer> mPluginTimer;
};
static void GetWidgetPosAndClip(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY,
nsRect& aClipRect);
class PluginViewerImpl : public nsIContentViewer,
public nsIContentViewerEdit,
public nsIContentViewerFile
@ -178,6 +201,7 @@ public:
nsIChannel* mChannel;
pluginInstanceOwner *mOwner;
PRBool mEnableRendering;
};
//----------------------------------------------------------------------
@ -246,6 +270,10 @@ PluginViewerImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
PluginViewerImpl::~PluginViewerImpl()
{
#ifdef XP_MAC
if (mOwner) mOwner->CancelTimer();
#endif
NS_IF_RELEASE(mOwner);
if (nsnull != mWindow) {
mWindow->Destroy();
@ -417,14 +445,21 @@ PluginViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
return NS_ERROR_FAILURE;
}
static nsEventStatus PR_CALLBACK
nsEventStatus PR_CALLBACK
HandlePluginEvent(nsGUIEvent *aEvent)
{
if( (*aEvent).message == NS_PLUGIN_ACTIVATE) {
(nsIWidget*)((*aEvent).widget)->SetFocus();
}
#ifdef XP_MAC
PluginViewerImpl * pluginViewer;
(nsIWidget*)((*aEvent).widget)->GetClientData((PluginViewerImpl *)pluginViewer);
return pluginViewer->mOwner->ProcessEvent(*aEvent);
#endif
return nsEventStatus_eIgnore;
}
nsresult
PluginViewerImpl::MakeWindow(nsNativeWidget aParent,
nsIDeviceContext* aDeviceContext,
@ -436,7 +471,10 @@ PluginViewerImpl::MakeWindow(nsNativeWidget aParent,
if (NS_OK != rv) {
return rv;
}
mWindow->Create(aParent, aBounds, HandlePluginEvent, aDeviceContext);
mWindow->Create(aParent, aBounds,HandlePluginEvent, aDeviceContext);
mWindow->SetClientData(this);
return rv;
}
@ -752,6 +790,11 @@ pluginInstanceOwner :: pluginInstanceOwner()
pluginInstanceOwner :: ~pluginInstanceOwner()
{
// shut off the timer.
if (mPluginTimer != nsnull) {
mPluginTimer->Cancel();
}
if (nsnull != mInstance)
{
PRBool doCache = PR_TRUE;
@ -777,7 +820,7 @@ pluginInstanceOwner :: ~pluginInstanceOwner()
mViewer = nsnull;
}
NS_IMPL_ISUPPORTS(pluginInstanceOwner, kIPluginInstanceOwnerIID);
NS_IMPL_ISUPPORTS2(pluginInstanceOwner, nsIPluginInstanceOwner,nsITimerCallback);
NS_IMETHODIMP pluginInstanceOwner :: SetInstance(nsIPluginInstance *aInstance)
{
@ -811,9 +854,18 @@ NS_IMETHODIMP pluginInstanceOwner :: GetMode(nsPluginMode *aMode)
NS_IMETHODIMP pluginInstanceOwner :: CreateWidget(void)
{
PRBool windowless;
nsresult rv = NS_OK;
if (nsnull != mInstance)
{
#if defined(XP_MAC)
// 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->Init(this, 1000 / 60, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
#endif
mInstance->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
if (PR_TRUE == windowless)
@ -832,7 +884,7 @@ NS_IMETHODIMP pluginInstanceOwner :: CreateWidget(void)
else
return NS_ERROR_FAILURE;
return NS_OK;
return rv;
}
NS_IMETHODIMP pluginInstanceOwner :: GetURL(const char *aURL, const char *aTarget, void *aPostData, PRUint32 aPostDataLen, void *aHeadersData,
@ -926,3 +978,236 @@ NS_IMETHODIMP pluginInstanceOwner :: Init(PluginViewerImpl *aViewer, nsIWidget *
return NS_OK;
}
// Here's where we forward events to plugins.
#ifdef XP_MAC
#if TARGET_CARBON
inline Boolean OSEventAvail(EventMask mask, EventRecord* event) { return EventAvail(mask, event); }
#endif
void pluginInstanceOwner::GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord& aMacEvent)
{
::OSEventAvail(0, &aMacEvent);
switch (anEvent.message) {
case NS_GOTFOCUS:
case NS_FOCUS_EVENT_START:
aMacEvent.what = nsPluginEventType_GetFocusEvent;
break;
case NS_LOSTFOCUS:
case NS_MOUSE_EXIT:
aMacEvent.what = nsPluginEventType_LoseFocusEvent;
break;
case NS_MOUSE_MOVE:
case NS_MOUSE_ENTER:
mWindow->SetFocus();
aMacEvent.what = nsPluginEventType_AdjustCursorEvent;
break;
case NS_PAINT:
aMacEvent.what = updateEvt;
break;
case NS_KEY_DOWN:
case NS_KEY_PRESS:
break;
default:
aMacEvent.what = nullEvent;
break;
}
}
#endif
nsEventStatus pluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
{
nsEventStatus rv = nsEventStatus_eIgnore;
if (!mInstance) // if mInstance is null, we shouldn't be here
return rv;
#ifdef XP_MAC
//if (mWidget != NULL) { // check for null mWidget
EventRecord* event = (EventRecord*)anEvent.nativeMsg;
if (event == NULL || event->what == nullEvent) {
EventRecord macEvent;
GUItoMacEvent(anEvent, macEvent);
event = &macEvent;
if (event->what == updateEvt) {
nsPluginPort* pluginPort = GetPluginPort();
// Add in child windows absolute position to get make the dirty rect
// relative to the top-level window.
nscoord absWidgetX = 0;
nscoord absWidgetY = 0;
nsRect widgetClip(0,0,0,0);
GetWidgetPosAndClip(mWindow,absWidgetX,absWidgetY,widgetClip);
//mViewer->GetBounds(widgetClip);
//absWidgetX = widgetClip.x;
//absWidgetY = widgetClip.y;
// set the port
mPluginWindow.x = absWidgetX;
mPluginWindow.y = absWidgetY;
// fix up the clipping region
mPluginWindow.clipRect.top = widgetClip.y;
mPluginWindow.clipRect.left = widgetClip.x;
mPluginWindow.clipRect.bottom = mPluginWindow.clipRect.top + widgetClip.height;
mPluginWindow.clipRect.right = mPluginWindow.clipRect.left + widgetClip.width;
EventRecord updateEvent;
::OSEventAvail(0, &updateEvent);
updateEvent.what = updateEvt;
updateEvent.message = UInt32(pluginPort->port);
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
return nsEventStatus_eConsumeNoDefault;
}
//nsPluginPort* port = (nsPluginPort*)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
nsPluginPort* port = (nsPluginPort*)mWindow->GetNativeData(NS_NATIVE_PLUGIN_PORT);
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(port->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (eventHandled && anEvent.message != NS_MOUSE_LEFT_BUTTON_DOWN)
rv = nsEventStatus_eConsumeNoDefault;
// }
#endif
//~~~
#ifdef XP_WIN
nsPluginEvent * pPluginEvent = (nsPluginEvent *)anEvent.nativeMsg;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(pPluginEvent, &eventHandled);
if (eventHandled)
rv = nsEventStatus_eConsumeNoDefault;
#endif
return rv;
}
// Here's how we give idle time to plugins.
NS_IMETHODIMP_(void) pluginInstanceOwner::Notify(nsITimer* /* timer */)
{
#ifdef XP_MAC
// 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) {
EventRecord idleEvent;
::OSEventAvail(0, &idleEvent);
idleEvent.what = nullEvent;
nsPluginPort* pluginPort = GetPluginPort();
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
#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->Init(this, 1000 / 60);
#endif // REPEATING_TIMERS
#endif // XP_MAC
}
void pluginInstanceOwner::CancelTimer()
{
if (mPluginTimer) {
mPluginTimer->Cancel();
}
}
#ifdef XP_MAC
nsPluginPort* pluginInstanceOwner::GetPluginPort()
{
nsPluginPort* result = NULL;
if (mWindow != NULL)
result = (nsPluginPort*) mWindow->GetNativeData(NS_NATIVE_PLUGIN_PORT);
return result;
}
// calculate the absolute position and clip for a widget
// and use other windows in calculating the clip
static void GetWidgetPosAndClip(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY,
nsRect& aClipRect)
{
aWidget->GetBounds(aClipRect);
aAbsX = aClipRect.x;
aAbsY = aClipRect.y;
nscoord ancestorX = -aClipRect.x, ancestorY = -aClipRect.y;
// Calculate clipping relative to the widget passed in
aClipRect.x = 0;
aClipRect.y = 0;
// Gather up the absolute position of the widget
// + clip window
nsCOMPtr<nsIWidget> widget = getter_AddRefs(aWidget->GetParent());
while (widget != nsnull) {
nsRect wrect;
widget->GetClientBounds(wrect);
nscoord wx, wy;
wx = wrect.x;
wy = wrect.y;
wrect.x = ancestorX;
wrect.y = ancestorY;
aClipRect.IntersectRect(aClipRect, wrect);
aAbsX += wx;
aAbsY += wy;
widget = getter_AddRefs(widget->GetParent());
if (widget == nsnull) {
// Don't include the top-level windows offset
// printf("Top level window offset %d %d\n", wx, wy);
aAbsX -= wx;
aAbsY -= wy;
}
ancestorX -=wx;
ancestorY -=wy;
}
aClipRect.x += aAbsX;
aClipRect.y += aAbsY;
//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");
}
void pluginInstanceOwner::FixUpPluginWindow()
{
if (mWindow) {
nscoord absWidgetX = 0;
nscoord absWidgetY = 0;
nsRect widgetClip(0,0,0,0);
GetWidgetPosAndClip(mWindow,absWidgetX,absWidgetY,widgetClip);
// set the port coordinates
mPluginWindow.x = absWidgetX;
mPluginWindow.y = absWidgetY;
// fix up the clipping region
mPluginWindow.clipRect.top = widgetClip.y;
mPluginWindow.clipRect.left = widgetClip.x;
mPluginWindow.clipRect.bottom = mPluginWindow.clipRect.top + widgetClip.height;
mPluginWindow.clipRect.right = mPluginWindow.clipRect.left + widgetClip.width;
}
}
#endif

View File

@ -120,7 +120,11 @@
#elif defined(XP_UNIX) || defined(XP_BEOS)
#define PLUGIN_DLL "libgkplugin" MOZ_DLL_SUFFIX
#elif defined(XP_MAC)
#define PLUGIN_DLL "PLUGIN_DLL"
#if defined(NS_DEBUG)
#define PLUGIN_DLL "pluginDebug.shlb"
#else
#define PLUGIN_DLL "plugin.shlb"
#endif // ifdef NS_DEBUG
#endif
#define REL_PLUGIN_DLL "rel:" PLUGIN_DLL

View File

@ -44,6 +44,11 @@
#include "nsIDOMDocument.h"
#include "nsPluginViewer.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
// Class IDs
static NS_DEFINE_IID(kChildWindowCID, NS_CHILD_CID);
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
@ -51,7 +56,6 @@ static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
// Interface IDs
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENTVIEWER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
@ -76,8 +80,10 @@ public:
PluginViewerImpl* mViewer;
nsIStreamListener* mNextStream;
};
class pluginInstanceOwner : public nsIPluginInstanceOwner
class pluginInstanceOwner : public nsIPluginInstanceOwner,
public nsITimerCallback
{
public:
pluginInstanceOwner();
@ -104,18 +110,35 @@ public:
NS_IMETHOD ShowStatus(const char *aStatusMsg);
NS_IMETHOD GetDocument(nsIDocument* *aDocument);
//nsIEventListener interface
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
//locals
NS_IMETHOD Init(PluginViewerImpl *aViewer, nsIWidget *aWindow);
// nsITimerCallback interface
NS_IMETHOD_(void) Notify(nsITimer *timer);
void CancelTimer();
#ifdef XP_MAC
void GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord& aMacEvent);
nsPluginPort* GetPluginPort();
void FixUpPluginWindow();
#endif
private:
nsPluginWindow mPluginWindow;
nsIPluginInstance *mInstance;
nsIWidget *mWindow; //we do not addref this...
PluginViewerImpl *mViewer; //we do not addref this...
nsCOMPtr<nsITimer> mPluginTimer;
};
static void GetWidgetPosAndClip(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY,
nsRect& aClipRect);
class PluginViewerImpl : public nsIContentViewer,
public nsIContentViewerEdit,
public nsIContentViewerFile
@ -178,6 +201,7 @@ public:
nsIChannel* mChannel;
pluginInstanceOwner *mOwner;
PRBool mEnableRendering;
};
//----------------------------------------------------------------------
@ -246,6 +270,10 @@ PluginViewerImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
PluginViewerImpl::~PluginViewerImpl()
{
#ifdef XP_MAC
if (mOwner) mOwner->CancelTimer();
#endif
NS_IF_RELEASE(mOwner);
if (nsnull != mWindow) {
mWindow->Destroy();
@ -417,14 +445,21 @@ PluginViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
return NS_ERROR_FAILURE;
}
static nsEventStatus PR_CALLBACK
nsEventStatus PR_CALLBACK
HandlePluginEvent(nsGUIEvent *aEvent)
{
if( (*aEvent).message == NS_PLUGIN_ACTIVATE) {
(nsIWidget*)((*aEvent).widget)->SetFocus();
}
#ifdef XP_MAC
PluginViewerImpl * pluginViewer;
(nsIWidget*)((*aEvent).widget)->GetClientData((PluginViewerImpl *)pluginViewer);
return pluginViewer->mOwner->ProcessEvent(*aEvent);
#endif
return nsEventStatus_eIgnore;
}
nsresult
PluginViewerImpl::MakeWindow(nsNativeWidget aParent,
nsIDeviceContext* aDeviceContext,
@ -436,7 +471,10 @@ PluginViewerImpl::MakeWindow(nsNativeWidget aParent,
if (NS_OK != rv) {
return rv;
}
mWindow->Create(aParent, aBounds, HandlePluginEvent, aDeviceContext);
mWindow->Create(aParent, aBounds,HandlePluginEvent, aDeviceContext);
mWindow->SetClientData(this);
return rv;
}
@ -752,6 +790,11 @@ pluginInstanceOwner :: pluginInstanceOwner()
pluginInstanceOwner :: ~pluginInstanceOwner()
{
// shut off the timer.
if (mPluginTimer != nsnull) {
mPluginTimer->Cancel();
}
if (nsnull != mInstance)
{
PRBool doCache = PR_TRUE;
@ -777,7 +820,7 @@ pluginInstanceOwner :: ~pluginInstanceOwner()
mViewer = nsnull;
}
NS_IMPL_ISUPPORTS(pluginInstanceOwner, kIPluginInstanceOwnerIID);
NS_IMPL_ISUPPORTS2(pluginInstanceOwner, nsIPluginInstanceOwner,nsITimerCallback);
NS_IMETHODIMP pluginInstanceOwner :: SetInstance(nsIPluginInstance *aInstance)
{
@ -811,9 +854,18 @@ NS_IMETHODIMP pluginInstanceOwner :: GetMode(nsPluginMode *aMode)
NS_IMETHODIMP pluginInstanceOwner :: CreateWidget(void)
{
PRBool windowless;
nsresult rv = NS_OK;
if (nsnull != mInstance)
{
#if defined(XP_MAC)
// 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->Init(this, 1000 / 60, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
#endif
mInstance->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
if (PR_TRUE == windowless)
@ -832,7 +884,7 @@ NS_IMETHODIMP pluginInstanceOwner :: CreateWidget(void)
else
return NS_ERROR_FAILURE;
return NS_OK;
return rv;
}
NS_IMETHODIMP pluginInstanceOwner :: GetURL(const char *aURL, const char *aTarget, void *aPostData, PRUint32 aPostDataLen, void *aHeadersData,
@ -926,3 +978,236 @@ NS_IMETHODIMP pluginInstanceOwner :: Init(PluginViewerImpl *aViewer, nsIWidget *
return NS_OK;
}
// Here's where we forward events to plugins.
#ifdef XP_MAC
#if TARGET_CARBON
inline Boolean OSEventAvail(EventMask mask, EventRecord* event) { return EventAvail(mask, event); }
#endif
void pluginInstanceOwner::GUItoMacEvent(const nsGUIEvent& anEvent, EventRecord& aMacEvent)
{
::OSEventAvail(0, &aMacEvent);
switch (anEvent.message) {
case NS_GOTFOCUS:
case NS_FOCUS_EVENT_START:
aMacEvent.what = nsPluginEventType_GetFocusEvent;
break;
case NS_LOSTFOCUS:
case NS_MOUSE_EXIT:
aMacEvent.what = nsPluginEventType_LoseFocusEvent;
break;
case NS_MOUSE_MOVE:
case NS_MOUSE_ENTER:
mWindow->SetFocus();
aMacEvent.what = nsPluginEventType_AdjustCursorEvent;
break;
case NS_PAINT:
aMacEvent.what = updateEvt;
break;
case NS_KEY_DOWN:
case NS_KEY_PRESS:
break;
default:
aMacEvent.what = nullEvent;
break;
}
}
#endif
nsEventStatus pluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
{
nsEventStatus rv = nsEventStatus_eIgnore;
if (!mInstance) // if mInstance is null, we shouldn't be here
return rv;
#ifdef XP_MAC
//if (mWidget != NULL) { // check for null mWidget
EventRecord* event = (EventRecord*)anEvent.nativeMsg;
if (event == NULL || event->what == nullEvent) {
EventRecord macEvent;
GUItoMacEvent(anEvent, macEvent);
event = &macEvent;
if (event->what == updateEvt) {
nsPluginPort* pluginPort = GetPluginPort();
// Add in child windows absolute position to get make the dirty rect
// relative to the top-level window.
nscoord absWidgetX = 0;
nscoord absWidgetY = 0;
nsRect widgetClip(0,0,0,0);
GetWidgetPosAndClip(mWindow,absWidgetX,absWidgetY,widgetClip);
//mViewer->GetBounds(widgetClip);
//absWidgetX = widgetClip.x;
//absWidgetY = widgetClip.y;
// set the port
mPluginWindow.x = absWidgetX;
mPluginWindow.y = absWidgetY;
// fix up the clipping region
mPluginWindow.clipRect.top = widgetClip.y;
mPluginWindow.clipRect.left = widgetClip.x;
mPluginWindow.clipRect.bottom = mPluginWindow.clipRect.top + widgetClip.height;
mPluginWindow.clipRect.right = mPluginWindow.clipRect.left + widgetClip.width;
EventRecord updateEvent;
::OSEventAvail(0, &updateEvent);
updateEvent.what = updateEvt;
updateEvent.message = UInt32(pluginPort->port);
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
return nsEventStatus_eConsumeNoDefault;
}
//nsPluginPort* port = (nsPluginPort*)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
nsPluginPort* port = (nsPluginPort*)mWindow->GetNativeData(NS_NATIVE_PLUGIN_PORT);
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(port->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (eventHandled && anEvent.message != NS_MOUSE_LEFT_BUTTON_DOWN)
rv = nsEventStatus_eConsumeNoDefault;
// }
#endif
//~~~
#ifdef XP_WIN
nsPluginEvent * pPluginEvent = (nsPluginEvent *)anEvent.nativeMsg;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(pPluginEvent, &eventHandled);
if (eventHandled)
rv = nsEventStatus_eConsumeNoDefault;
#endif
return rv;
}
// Here's how we give idle time to plugins.
NS_IMETHODIMP_(void) pluginInstanceOwner::Notify(nsITimer* /* timer */)
{
#ifdef XP_MAC
// 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) {
EventRecord idleEvent;
::OSEventAvail(0, &idleEvent);
idleEvent.what = nullEvent;
nsPluginPort* pluginPort = GetPluginPort();
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(pluginPort->port) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
#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->Init(this, 1000 / 60);
#endif // REPEATING_TIMERS
#endif // XP_MAC
}
void pluginInstanceOwner::CancelTimer()
{
if (mPluginTimer) {
mPluginTimer->Cancel();
}
}
#ifdef XP_MAC
nsPluginPort* pluginInstanceOwner::GetPluginPort()
{
nsPluginPort* result = NULL;
if (mWindow != NULL)
result = (nsPluginPort*) mWindow->GetNativeData(NS_NATIVE_PLUGIN_PORT);
return result;
}
// calculate the absolute position and clip for a widget
// and use other windows in calculating the clip
static void GetWidgetPosAndClip(nsIWidget* aWidget,nscoord& aAbsX, nscoord& aAbsY,
nsRect& aClipRect)
{
aWidget->GetBounds(aClipRect);
aAbsX = aClipRect.x;
aAbsY = aClipRect.y;
nscoord ancestorX = -aClipRect.x, ancestorY = -aClipRect.y;
// Calculate clipping relative to the widget passed in
aClipRect.x = 0;
aClipRect.y = 0;
// Gather up the absolute position of the widget
// + clip window
nsCOMPtr<nsIWidget> widget = getter_AddRefs(aWidget->GetParent());
while (widget != nsnull) {
nsRect wrect;
widget->GetClientBounds(wrect);
nscoord wx, wy;
wx = wrect.x;
wy = wrect.y;
wrect.x = ancestorX;
wrect.y = ancestorY;
aClipRect.IntersectRect(aClipRect, wrect);
aAbsX += wx;
aAbsY += wy;
widget = getter_AddRefs(widget->GetParent());
if (widget == nsnull) {
// Don't include the top-level windows offset
// printf("Top level window offset %d %d\n", wx, wy);
aAbsX -= wx;
aAbsY -= wy;
}
ancestorX -=wx;
ancestorY -=wy;
}
aClipRect.x += aAbsX;
aClipRect.y += aAbsY;
//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");
}
void pluginInstanceOwner::FixUpPluginWindow()
{
if (mWindow) {
nscoord absWidgetX = 0;
nscoord absWidgetY = 0;
nsRect widgetClip(0,0,0,0);
GetWidgetPosAndClip(mWindow,absWidgetX,absWidgetY,widgetClip);
// set the port coordinates
mPluginWindow.x = absWidgetX;
mPluginWindow.y = absWidgetY;
// fix up the clipping region
mPluginWindow.clipRect.top = widgetClip.y;
mPluginWindow.clipRect.left = widgetClip.x;
mPluginWindow.clipRect.bottom = mPluginWindow.clipRect.top + widgetClip.height;
mPluginWindow.clipRect.right = mPluginWindow.clipRect.left + widgetClip.width;
}
}
#endif