Fix bug 176649 (Chimera plugin issues).
Plugins drawing over chrome (bug 172688) Plugins showing through tabs (bug 158018, bug 156583) Plugins not drawing initially on page load (bug 147728, bug 161378) Bugs _not_ fixed: Visual corruption when scrolling with QT movie (bug 160435) Crashes when loading plugins which are offscreen (bug 161378), tho it seems much less easy to reproduce now. Quick summary of changes: Added nsIPluginWidget to allow plugin code to get the widget clip rectangle and origin. Fixes drawing over chrome for plugins in iframes. Always use [mView qdPort], not the WindowRef port, for gecko rendering (making nsIRenderingContexts). Only use the WindowRef port for plugin drawing. Fixes drawing over chrome. Always call SetPortVisibleRegion() before plugin drawing, because we don't know what part of the BeginUpdate/EndUpdate cycle we're in. Keep track of whether views are in the frontmost tab (i.e. have a window), and hide/show views immediately on tab switching, rather than on the next timer fire. Fixes plugins stomping through tabs (mostly). Add smarts to FixUpPluginWindow() in nsObjectFrame so that it knows when it's Ok to display the plugin (after a ::Paint()). Fixes plugins drawing in the wrong place/not drawing on initial page load. git-svn-id: svn://10.0.0.236/branches/CHIMERA_M1_0_1_BRANCH@132538 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#include "nsPluginSafety.h"
|
||||
#include "nsIPref.h" // needed for NS_TRY_SAFE_CALL_*
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsIPluginWidget.h"
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
#include <gdk/gdk.h>
|
||||
@@ -363,6 +364,10 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
|
||||
// do not read more that supplier wants us to read
|
||||
bytesToRead = length;
|
||||
}
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
mInst->SetupForPluginDrawing();
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
@@ -463,6 +468,11 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
|
||||
} // end of for(;;)
|
||||
} while ((PRInt32)(length) > 0);
|
||||
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
mInst->DonePluginDrawing();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -618,6 +628,27 @@ ns4xPluginInstance :: IsStarted(void)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
nsresult
|
||||
ns4xPluginInstance::SetupForPluginDrawing()
|
||||
{
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
::SetPort(mWindow->window->port);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
nsresult
|
||||
ns4xPluginInstance::DonePluginDrawing()
|
||||
{
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP ns4xPluginInstance::Initialize(nsIPluginInstancePeer* peer)
|
||||
{
|
||||
@@ -1012,8 +1043,8 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window)
|
||||
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
|
||||
this, window->x, window->y, window->width, window->height,
|
||||
("NPP SetWindow called: this=%p, window=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
|
||||
this, *window->window, window->x, window->y, window->width, window->height,
|
||||
window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error));
|
||||
|
||||
// XXX In the old code, we'd just ignore any errors coming
|
||||
@@ -1122,25 +1153,12 @@ NS_IMETHODIMP ns4xPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* hand
|
||||
|
||||
if (fCallbacks->event) {
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
#if 0
|
||||
switch(event->event->what) {
|
||||
case updateEvt:
|
||||
if (mWindow) {
|
||||
GrafPtr port;
|
||||
GetPort(&port);
|
||||
if (port != mWindow->window->port) printf("[!!! port isn't set correctly !!!!]\n");
|
||||
RGBColor oldColor;
|
||||
RGBColor green = { 0, 0xFFFF, 0 };
|
||||
GetForeColor(&oldColor);
|
||||
RGBForeColor(&green);
|
||||
PaintRect((Rect*)&mWindow->clipRect);
|
||||
// ::QDFlushPortBuffer(port, NULL);
|
||||
RGBForeColor(&oldColor);
|
||||
// printf("[portx = %d, porty = %d]\n", mWindow->window->portx, mWindow->window->porty);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("CallNPP_HandleEventProc called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d]\n",
|
||||
this, mWindow->x, mWindow->y, mWindow->width, mWindow->height,
|
||||
mWindow->clipRect.top, mWindow->clipRect.bottom, mWindow->clipRect.left, mWindow->clipRect.right));
|
||||
|
||||
result = CallNPP_HandleEventProc(fCallbacks->event,
|
||||
&fNPP,
|
||||
(void*) event->event);
|
||||
|
||||
@@ -153,6 +153,11 @@ public:
|
||||
// cache this 4.x plugin like an XPCOM plugin
|
||||
nsresult SetCached(PRBool aCache) { mCached = aCache; return NS_OK; };
|
||||
|
||||
// only used on Mac; called to ensure that the plugin can draw whenever
|
||||
// we call into it
|
||||
nsresult SetupForPluginDrawing();
|
||||
nsresult DonePluginDrawing();
|
||||
|
||||
protected:
|
||||
|
||||
nsresult InitializePlugin(nsIPluginInstancePeer* peer);
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "nsIContentViewerEdit.h"
|
||||
#include "nsIWebBrowserPrint.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIPluginWidget.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
@@ -650,6 +651,7 @@ PluginViewerImpl::SetBounds(const nsRect& aBounds)
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
// On Mac we also need to add in the widget offset to the plugin window
|
||||
mOwner->FixUpPluginWindow();
|
||||
mWindow->Invalidate(PR_FALSE);
|
||||
#endif
|
||||
inst->SetWindow(win);
|
||||
}
|
||||
@@ -679,6 +681,7 @@ PluginViewerImpl::Move(PRInt32 aX, PRInt32 aY)
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
// On Mac we also need to add in the widget offset to the plugin window
|
||||
mOwner->FixUpPluginWindow();
|
||||
mWindow->Invalidate(PR_FALSE);
|
||||
#endif
|
||||
inst->SetWindow(win);
|
||||
}
|
||||
@@ -1038,7 +1041,30 @@ PluginListener::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#if defined (XP_MAC) || defined(XP_MACOSX)
|
||||
NS_ASSERTION(mViewer, "Need plugin viewer");
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mViewer->mWindow);
|
||||
PRBool startDrawCalled = PR_FALSE;
|
||||
|
||||
if (pluginWidget)
|
||||
{
|
||||
rv = pluginWidget->StartDrawPlugin();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "StartDrawPlugin failed in OnDataAvailable!");
|
||||
startDrawCalled = NS_SUCCEEDED(rv);
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
|
||||
|
||||
#if defined (XP_MAC) || defined(XP_MACOSX)
|
||||
if (pluginWidget && startDrawCalled)
|
||||
pluginWidget->EndDrawPlugin();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -1291,38 +1317,48 @@ nsEventStatus pluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
|
||||
return rv;
|
||||
|
||||
#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 ||
|
||||
anEvent.message == NS_CONTEXTMENU_MESSAGE_START) {
|
||||
EventRecord macEvent;
|
||||
GUItoMacEvent(anEvent, macEvent);
|
||||
event = &macEvent;
|
||||
if (event->what == updateEvt) {
|
||||
// Add in child windows absolute position to get make the dirty rect
|
||||
// relative to the top-level window.
|
||||
nsPluginPort* pluginPort = FixUpPluginWindow();
|
||||
if (pluginPort) {
|
||||
EventRecord updateEvent;
|
||||
InitializeEventRecord(&updateEvent);
|
||||
updateEvent.what = updateEvt;
|
||||
updateEvent.message = UInt32(pluginPort->port);
|
||||
|
||||
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(pluginPort->port) };
|
||||
PRBool eventHandled = PR_FALSE;
|
||||
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
||||
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWindow);
|
||||
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin()))
|
||||
{
|
||||
//if (mWidget != NULL) { // check for null mWidget
|
||||
EventRecord* event = (EventRecord*)anEvent.nativeMsg;
|
||||
if (event == NULL || event->what == nullEvent ||
|
||||
anEvent.message == NS_CONTEXTMENU_MESSAGE_START) {
|
||||
EventRecord macEvent;
|
||||
GUItoMacEvent(anEvent, macEvent);
|
||||
event = &macEvent;
|
||||
if (event->what == updateEvt) {
|
||||
// Add in child windows absolute position to get make the dirty rect
|
||||
// relative to the top-level window.
|
||||
nsPluginPort* pluginPort = FixUpPluginWindow();
|
||||
if (pluginPort) {
|
||||
EventRecord updateEvent;
|
||||
InitializeEventRecord(&updateEvent);
|
||||
updateEvent.what = updateEvt;
|
||||
updateEvent.message = UInt32(pluginPort->port);
|
||||
|
||||
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(pluginPort->port) };
|
||||
PRBool eventHandled = PR_FALSE;
|
||||
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
||||
}
|
||||
}
|
||||
rv = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
}
|
||||
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;
|
||||
// }
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
// }
|
||||
|
||||
pluginWidget->EndDrawPlugin();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//~~~
|
||||
@@ -1348,33 +1384,31 @@ NS_IMETHODIMP_(void) pluginInstanceOwner::Notify(nsITimer* /* timer */)
|
||||
// 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.
|
||||
if (mInstance != NULL) {
|
||||
nsPluginPort* pluginPort = FixUpPluginWindow();
|
||||
if (pluginPort) {
|
||||
EventRecord idleEvent;
|
||||
InitializeEventRecord(&idleEvent);
|
||||
idleEvent.what = nullEvent;
|
||||
|
||||
// give a bogus 'where' field of our null event when hidden, so Flash
|
||||
// won't respond to mouse moves in other tabs, see bug 120875
|
||||
if (!mWidgetVisible)
|
||||
idleEvent.where.h = idleEvent.where.v = 20000;
|
||||
|
||||
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(pluginPort->port) };
|
||||
|
||||
PRBool eventHandled = PR_FALSE;
|
||||
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
||||
if (mInstance != NULL)
|
||||
{
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWindow);
|
||||
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin()))
|
||||
{
|
||||
nsPluginPort* pluginPort = FixUpPluginWindow();
|
||||
if (pluginPort) {
|
||||
EventRecord idleEvent;
|
||||
InitializeEventRecord(&idleEvent);
|
||||
idleEvent.what = nullEvent;
|
||||
|
||||
// give a bogus 'where' field of our null event when hidden, so Flash
|
||||
// won't respond to mouse moves in other tabs, see bug 120875
|
||||
if (!mWidgetVisible)
|
||||
idleEvent.where.h = idleEvent.where.v = 20000;
|
||||
|
||||
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(pluginPort->port) };
|
||||
|
||||
PRBool eventHandled = PR_FALSE;
|
||||
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
||||
}
|
||||
|
||||
pluginWidget->EndDrawPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
#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, 1020 / 60);
|
||||
#endif // REPEATING_TIMERS
|
||||
#endif // XP_MAC
|
||||
}
|
||||
|
||||
@@ -1473,31 +1507,49 @@ nsPluginPort* pluginInstanceOwner::FixUpPluginWindow()
|
||||
{
|
||||
if (mWindow) {
|
||||
nsPluginPort* pluginPort = GetPluginPort();
|
||||
nscoord absWidgetX = 0;
|
||||
nscoord absWidgetY = 0;
|
||||
|
||||
nsRect widgetClip(0, 0, 0, 0);
|
||||
PRBool isVisible = PR_TRUE;
|
||||
|
||||
GetWidgetPosClipAndVis(mWindow, absWidgetX, absWidgetY, widgetClip, isVisible);
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
nsPoint pluginOrigin;
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWindow);
|
||||
pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin);
|
||||
|
||||
// check widget visibility (do we really have to do this here?)
|
||||
nsCOMPtr<nsIWidget> widget = mWindow;
|
||||
while (widget)
|
||||
{
|
||||
PRBool widgetVisible;
|
||||
widget->IsVisible(widgetVisible);
|
||||
isVisible &= widgetVisible;
|
||||
|
||||
widget = getter_AddRefs(widget->GetParent());
|
||||
}
|
||||
|
||||
if (!isVisible)
|
||||
widgetClip.Empty();
|
||||
|
||||
// set the port coordinates
|
||||
mPluginWindow.x = -pluginPort->portx;
|
||||
mPluginWindow.y = -pluginPort->porty;
|
||||
widgetClip.x += mPluginWindow.x - absWidgetX;
|
||||
widgetClip.y += mPluginWindow.y - absWidgetY;
|
||||
#else
|
||||
nscoord absWidgetX = 0;
|
||||
nscoord absWidgetY = 0;
|
||||
GetWidgetPosClipAndVis(mWindow, absWidgetX, absWidgetY, widgetClip, isVisible);
|
||||
// set the port coordinates
|
||||
mPluginWindow.x = absWidgetX;
|
||||
mPluginWindow.y = absWidgetY;
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
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;
|
||||
|
||||
if (mWidgetVisible != isVisible) {
|
||||
if (mWidgetVisible != isVisible)
|
||||
{
|
||||
mWidgetVisible = isVisible;
|
||||
// must do this to disable async Java Applet drawing
|
||||
if (isVisible) {
|
||||
|
||||
Reference in New Issue
Block a user