Bug 547353 - [OOPP] Mouse pointer coordinates misaligned with winless Silverlight. r=bent.

This commit is contained in:
Jim Mathies 2010-02-24 16:13:48 -08:00
Родитель 27fa3622a3
Коммит 14da2adae7
3 изменённых файлов: 116 добавлений и 49 удалений

Просмотреть файл

@ -61,6 +61,7 @@ using namespace mozilla::plugins;
using mozilla::gfx::SharedDIB;
#include <windows.h>
#include <windowsx.h>
#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
@ -73,10 +74,12 @@ using mozilla::gfx::SharedDIB;
#endif // defined(OS_WIN)
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) :
mPluginIface(aPluginIface),
mCachedWindowActor(nsnull),
mCachedElementActor(nsnull)
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
const nsCString& aMimeType) :
mPluginIface(aPluginIface)
, mCachedWindowActor(nsnull)
, mCachedElementActor(nsnull)
, mQuirks(0)
#if defined(OS_WIN)
, mPluginWindowHWND(0)
, mPluginWndProc(0)
@ -104,6 +107,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) :
memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
mAlphaExtract.doublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
#endif // OS_WIN
InitQuirksModes(aMimeType);
}
PluginInstanceChild::~PluginInstanceChild()
@ -113,6 +117,19 @@ PluginInstanceChild::~PluginInstanceChild()
#endif
}
void
PluginInstanceChild::InitQuirksModes(const nsCString& aMimeType)
{
#ifdef OS_WIN
// application/x-silverlight
// application/x-silverlight-2
NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
if (FindInReadable(silverlight, aMimeType)) {
mQuirks |= QUIRK_SILVERLIGHT_WINLESS_INPUT_TRANSLATION;
}
#endif
}
NPError
PluginInstanceChild::InternalGetNPObjectForValue(NPNVariable aValue,
NPObject** aObject)
@ -791,23 +808,6 @@ PluginInstanceChild::PluginWindowProc(HWND hWnd,
/* winless modal ui loop logic */
static bool
IsUserInputEvent(UINT msg)
{
// Events we assume some sort of modal ui *might* be generated.
switch (msg) {
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_CONTEXTMENU:
return true;
}
return false;
}
VOID CALLBACK
PluginInstanceChild::PumpTimerProc(HWND hwnd,
UINT uMsg,
@ -923,42 +923,101 @@ PluginInstanceChild::InternalCallSetNestedEventState(bool aState)
}
}
/* windowless handle event helpers */
static bool
NeedsNestedEventCoverage(UINT msg)
{
// Events we assume some sort of modal ui *might* be generated.
switch (msg) {
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_CONTEXTMENU:
return true;
}
return false;
}
static bool
IsMouseInputEvent(UINT msg)
{
switch (msg) {
case WM_MOUSEMOVE:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
return true;
}
return false;
}
int16_t
PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
{
if (!IsUserInputEvent(event.event)) {
return mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
}
// Winless Silverlight quirk: winposchanged events are not used in
// determining the position of the plugin within the parent window,
// NPP_SetWindow values are used instead. Due to shared memory dib
// rendering, the origin of NPP_SetWindow is 0x0, so we trap
// winposchanged events here and do the translation internally for
// mouse input events.
if (mQuirks & QUIRK_SILVERLIGHT_WINLESS_INPUT_TRANSLATION) {
if (event.event == WM_WINDOWPOSCHANGED && event.lParam) {
WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(event.lParam);
mPluginOffset.x = pos->x;
mPluginOffset.y = pos->y;
}
else if (IsMouseInputEvent(event.event)) {
event.lParam =
MAKELPARAM((GET_X_LPARAM(event.lParam) - mPluginOffset.x),
(GET_Y_LPARAM(event.lParam) - mPluginOffset.y));
}
}
int16_t handled;
if (!NeedsNestedEventCoverage(event.event)) {
return mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
}
mNestedEventLevelDepth++;
PLUGIN_LOG_DEBUG(("WinlessHandleEvent start depth: %i", mNestedEventLevelDepth));
// Events that might generate nested event dispatch loops need
// special handling during delivery.
int16_t handled;
// On the first, non-reentrant call, setup our modal ui detection hook.
if (mNestedEventLevelDepth == 1) {
NS_ASSERTION(!gTempChildPointer, "valid gTempChildPointer here?");
gTempChildPointer = this;
SetNestedInputEventHook();
}
mNestedEventLevelDepth++;
PLUGIN_LOG_DEBUG(("WinlessHandleEvent start depth: %i", mNestedEventLevelDepth));
bool old_state = MessageLoop::current()->NestableTasksAllowed();
MessageLoop::current()->SetNestableTasksAllowed(true);
handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
MessageLoop::current()->SetNestableTasksAllowed(old_state);
// On the first, non-reentrant call, setup our modal ui detection hook.
if (mNestedEventLevelDepth == 1) {
NS_ASSERTION(!gTempChildPointer, "valid gTempChildPointer here?");
gTempChildPointer = this;
SetNestedInputEventHook();
}
gTempChildPointer = NULL;
bool old_state = MessageLoop::current()->NestableTasksAllowed();
MessageLoop::current()->SetNestableTasksAllowed(true);
handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
MessageLoop::current()->SetNestableTasksAllowed(old_state);
mNestedEventLevelDepth--;
PLUGIN_LOG_DEBUG(("WinlessHandleEvent end depth: %i", mNestedEventLevelDepth));
gTempChildPointer = NULL;
NS_ASSERTION(!(mNestedEventLevelDepth < 0), "mNestedEventLevelDepth < 0?");
if (mNestedEventLevelDepth <= 0) {
ResetNestedEventHook();
ResetPumpHooks();
InternalCallSetNestedEventState(false);
}
return handled;
mNestedEventLevelDepth--;
PLUGIN_LOG_DEBUG(("WinlessHandleEvent end depth: %i", mNestedEventLevelDepth));
NS_ASSERTION(!(mNestedEventLevelDepth < 0), "mNestedEventLevelDepth < 0?");
if (mNestedEventLevelDepth <= 0) {
ResetNestedEventHook();
ResetPumpHooks();
InternalCallSetNestedEventState(false);
}
return handled;
}
/* windowless drawing helpers */

Просмотреть файл

@ -149,7 +149,7 @@ protected:
AnswerUpdateWindow();
public:
PluginInstanceChild(const NPPluginFuncs* aPluginIface);
PluginInstanceChild(const NPPluginFuncs* aPluginIface, const nsCString& aMimeType);
virtual ~PluginInstanceChild();
@ -181,6 +181,12 @@ public:
void UnscheduleTimer(uint32_t id);
private:
// Quirks mode support for various plugin mime types
enum PluginQuirks {
QUIRK_SILVERLIGHT_WINLESS_INPUT_TRANSLATION = 1, // Win32
};
void InitQuirksModes(const nsCString& aMimeType);
NPError
InternalGetNPObjectForValue(NPNVariable aValue,
@ -221,6 +227,7 @@ private:
const NPPluginFuncs* mPluginIface;
NPP_t mData;
NPWindow mWindow;
int mQuirks;
// Cached scriptable actors to avoid IPC churn
PluginScriptableObjectChild* mCachedWindowActor;
@ -239,6 +246,7 @@ private:
HWND mCachedWinlessPluginHWND;
UINT_PTR mEventPumpTimer;
nsIntPoint mPluginSize;
nsIntPoint mPluginOffset;
#endif
friend class ChildAsyncCall;

Просмотреть файл

@ -1448,7 +1448,7 @@ PluginModuleChild::AllocPPluginInstance(const nsCString& aMimeType,
AssertPluginThread();
nsAutoPtr<PluginInstanceChild> childInstance(
new PluginInstanceChild(&mFunctions));
new PluginInstanceChild(&mFunctions, aMimeType));
if (!childInstance->Initialize()) {
*rv = NPERR_GENERIC_ERROR;
return 0;