Bug 534027 - input event coords incorrect for oop windowless plugins. r=jmuizelaar.

This commit is contained in:
Jim Mathies 2009-12-14 18:28:51 -06:00
parent 8334063adb
commit 3c68e53543
3 changed files with 108 additions and 24 deletions

View File

@ -47,6 +47,10 @@
#include "npfunctions.h"
#include "nsAutoPtr.h"
#if defined(OS_WIN)
#include <windowsx.h>
#endif
using namespace mozilla::plugins;
PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
@ -452,12 +456,57 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
NPRemoteEvent npremoteevent;
npremoteevent.event = *npevent;
int16_t handled;
#if defined(OS_WIN)
RECT rect;
if (mWindowType == NPWindowTypeDrawable &&
npevent->event == WM_PAINT) {
SharedSurfaceBeforePaint(rect, npremoteevent);
if (mWindowType == NPWindowTypeDrawable) {
switch(npevent->event) {
case WM_PAINT:
{
RECT rect;
SharedSurfaceBeforePaint(rect, npremoteevent);
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0;
if (handled)
SharedSurfaceAfterPaint(npevent);
}
break;
case WM_WINDOWPOSCHANGED:
SharedSurfaceSetOrigin(npremoteevent);
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0;
break;
case WM_MOUSEMOVE:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
{
// Received mouse events have an origin at the position of the plugin rect
// in the page. However, when rendering to the shared dib, the rect origin
// changes to 0,0 via the WM_WINDOWPOSCHANGED event. In this case we need to
// translate these coords to the proper location.
nsPoint pt(GET_X_LPARAM(npremoteevent.event.lParam), GET_Y_LPARAM(npremoteevent.event.lParam));
pt.MoveBy(-mPluginPosOrigin.x, -mPluginPosOrigin.y);
npremoteevent.event.lParam = MAKELPARAM(pt.x, pt.y);
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0;
}
default:
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0;
break;
}
}
else {
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0;
}
#endif
@ -476,16 +525,9 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
XSync(GDK_DISPLAY(), False);
# endif
}
#endif
int16_t handled;
if (!CallNPP_HandleEvent(npremoteevent, &handled)) {
return 0; // no good way to handle errors here...
}
#if defined(OS_WIN)
if (handled && mWindowType == NPWindowTypeDrawable && npevent->event == WM_PAINT)
SharedSurfaceAfterPaint(npevent);
if (!CallNPP_HandleEvent(npremoteevent, &handled))
return 0; // no good way to handle errors here...
#endif
return handled;
@ -661,6 +703,41 @@ PluginInstanceParent::AnswerNPN_PopPopupsEnabledState(bool* aSuccess)
/* windowless drawing helpers */
/*
* Origin info:
*
* windowless, offscreen:
*
* WM_WINDOWPOSCHANGED: origin is relative to container
* setwindow: origin is 0,0
* WM_PAINT: origin is 0,0
*
* windowless, native:
*
* WM_WINDOWPOSCHANGED: origin is relative to container
* setwindow: origin is relative to container
* WM_PAINT: origin is relative to container
*
* PluginInstanceParent:
*
* painting: mPluginPort (nsIntRect, saved in SetWindow)
* event translation: mPluginPosOrigin (nsIntPoint, saved in SetOrigin)
*/
void
PluginInstanceParent::SharedSurfaceSetOrigin(NPRemoteEvent& npremoteevent)
{
WINDOWPOS* winpos = (WINDOWPOS*)npremoteevent.event.lParam;
// save the origin, we'll use this to translate input coordinates
mPluginPosOrigin.x = winpos->x;
mPluginPosOrigin.y = winpos->y;
// Reset to the offscreen dib origin
winpos->x = 0;
winpos->y = 0;
}
void
PluginInstanceParent::SharedSurfaceRelease()
{
@ -692,7 +769,7 @@ PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
aRemoteWindow.surfaceHandle = 0;
return true;
}
// allocate a new shared surface
SharedSurfaceRelease();
if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window),
@ -701,13 +778,13 @@ PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
// save the new shared surface size we just allocated
mSharedSize = newPort;
base::SharedMemoryHandle handle;
if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle)))
return false;
aRemoteWindow.surfaceHandle = handle;
return true;
}

View File

@ -219,12 +219,14 @@ private:
bool SharedSurfaceSetWindow(const NPWindow* aWindow, NPRemoteWindow& aRemoteWindow);
void SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent);
void SharedSurfaceAfterPaint(NPEvent* npevent);
void SharedSurfaceSetOrigin(NPRemoteEvent& npremoteevent);
void SharedSurfaceRelease();
private:
gfx::SharedDIBWin mSharedSurfaceDib;
nsIntRect mPluginPort;
nsIntRect mSharedSize;
nsIntPoint mPluginPosOrigin;
#endif // defined(XP_WIN)
};

View File

@ -1675,7 +1675,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
PRBool doupdatewindow = PR_FALSE;
// the offset of the DC
nsPoint origin;
gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
#ifdef MOZ_IPC
if (nativeDraw.IsDoublePass()) {
@ -1713,17 +1713,22 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
window->x = dest.left;
window->y = dest.top;
// Windowless plugins on windows need a special event to update their location, see bug 135737
// Windowless plugins on windows need a special event to update their location,
// see bug 135737.
//
// bug 271442: note, the rectangle we send is now purely the bounds of the plugin
// relative to the window it is contained in, which is useful for the plugin to correctly translate mouse coordinates
// relative to the window it is contained in, which is useful for the plugin to
// correctly translate mouse coordinates.
//
// this does not mesh with the comments for bug 135737 which imply that the rectangle
// must be clipped in some way to prevent the plugin attempting to paint over areas it shouldn't;
// must be clipped in some way to prevent the plugin attempting to paint over areas
// it shouldn't.
//
// since the two uses of the rectangle are mutually exclusive in some cases,
// and since I don't see any incorrect painting (at least with Flash and ViewPoint - the originator of 135737),
// it seems that windowless plugins are not relying on information here for clipping their drawing,
// and we can safely use this message to tell the plugin exactly where it is in all cases.
// since the two uses of the rectangle are mutually exclusive in some cases, and
// since I don't see any incorrect painting (at least with Flash and ViewPoint -
// the originator of bug 135737), it seems that windowless plugins are not relying
// on information here for clipping their drawing, and we can safely use this message
// to tell the plugin exactly where it is in all cases.
nsIntPoint origin = GetWindowOriginInPixels(PR_TRUE);
nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
@ -1752,7 +1757,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
inst->HandleEvent(&pluginEvent, &eventHandled);
}
inst->SetWindow(window);
inst->SetWindow(window);
}
mInstanceOwner->Paint(dirty, hdc);
nativeDraw.EndNativeDrawing();