Bug 672175 part.16 Implement nsIWidget::SynthesizeNativeMouseScrollEvent() on Windows r=jimm

This commit is contained in:
Masayuki Nakano 2012-03-22 09:59:12 +09:00
parent c670feb072
commit a60c46de7f
7 changed files with 468 additions and 14 deletions

View File

@ -377,6 +377,10 @@ interface nsIDOMWindowUtils : nsISupports {
* privileges.
*
* NOTE: The synthesized native event may be fired asynchronously.
*
* @param aNativeMessage
* On Windows: WM_MOUSEWHEEL (0x020A), WM_MOUSEHWHEEL(0x020E),
* WM_VSCROLL (0x0115) or WM_HSCROLL (0x114).
*/
void sendNativeMouseScrollEvent(in long aScreenX,
in long aScreenY,
@ -388,6 +392,28 @@ interface nsIDOMWindowUtils : nsISupports {
in unsigned long aAdditionalFlags,
in nsIDOMElement aElement);
/**
* The values of aAdditionalFlags.
*/
/**
* If MOUSESCROLL_PREFER_WIDGET_AT_POINT is set, widget will dispatch
* the event to a widget which is under the cursor. Otherwise, dispatch to
* a default target on the platform. E.g., on Windows, it's focused window.
*/
const unsigned long MOUSESCROLL_PREFER_WIDGET_AT_POINT = 0x00000001;
/**
* The platform specific values of aAdditionalFlags. Must be over 0x00010000.
*/
/**
* If MOUSESCROLL_WIN_SCROLL_LPARAM_NOT_NULL is set and aNativeMessage is
* WM_VSCROLL or WM_HSCROLL, widget will set the window handle to the lParam
* instead of NULL.
*/
const unsigned long MOUSESCROLL_WIN_SCROLL_LPARAM_NOT_NULL = 0x00010000;
/**
* See nsIWidget::ActivateNativeMenuItemAt
*

View File

@ -13,6 +13,7 @@
#include "nsWindow.h"
#include "WinUtils.h"
#include "nsGkAtoms.h"
#include "nsIDOMWindowUtils.h"
#include "mozilla/Preferences.h"
@ -79,6 +80,20 @@ bool MouseScrollHandler::Device::SetPoint::sMightBeUsing = false;
*
******************************************************************************/
/* static */
POINTS
MouseScrollHandler::GetCurrentMessagePos()
{
if (SynthesizingEvent::IsSynthesizing()) {
return sInstance->mSynthesizingEvent->GetCursorPoint();
}
DWORD pos = ::GetMessagePos();
return MAKEPOINTS(pos);
}
// Get rid of the GetMessagePos() API.
#define GetMessagePos()
/* static */
void
MouseScrollHandler::Initialize()
@ -109,7 +124,9 @@ MouseScrollHandler::GetInstance()
return sInstance;
}
MouseScrollHandler::MouseScrollHandler()
MouseScrollHandler::MouseScrollHandler() :
mIsWaitingInternalMessage(false),
mSynthesizingEvent(nsnull)
{
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScroll: Creating an instance, this=%p, sInstance=%p",
@ -121,6 +138,8 @@ MouseScrollHandler::~MouseScrollHandler()
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScroll: Destroying an instance, this=%p, sInstance=%p",
this, sInstance));
delete mSynthesizingEvent;
}
/* static */
@ -146,6 +165,7 @@ MouseScrollHandler::ProcessMessage(nsWindow* aWindow, UINT msg,
case WM_MOUSEHWHEEL:
GetInstance()->
ProcessNativeMouseWheelMessage(aWindow, msg, wParam, lParam);
sInstance->mSynthesizingEvent->NotifyNativeMessageHandlingFinished();
// We don't need to call next wndproc for WM_MOUSEWHEEL and
// WM_MOUSEHWHEEL. We should consume them always. If the messages
// would be handled by our window again, it caused making infinite
@ -158,12 +178,14 @@ MouseScrollHandler::ProcessMessage(nsWindow* aWindow, UINT msg,
case WM_VSCROLL:
aEatMessage =
GetInstance()->ProcessNativeScrollMessage(aWindow, msg, wParam, lParam);
sInstance->mSynthesizingEvent->NotifyNativeMessageHandlingFinished();
*aRetValue = 0;
return true;
case MOZ_WM_MOUSEVWHEEL:
case MOZ_WM_MOUSEHWHEEL:
GetInstance()->HandleMouseWheelMessage(aWindow, msg, wParam, lParam);
sInstance->mSynthesizingEvent->NotifyInternalMessageHandlingFinished();
// Doesn't need to call next wndproc for internal wheel message.
aEatMessage = true;
return true;
@ -172,6 +194,7 @@ MouseScrollHandler::ProcessMessage(nsWindow* aWindow, UINT msg,
case MOZ_WM_VSCROLL:
GetInstance()->
HandleScrollMessageAsMouseWheelMessage(aWindow, msg, wParam, lParam);
sInstance->mSynthesizingEvent->NotifyInternalMessageHandlingFinished();
// Doesn't need to call next wndproc for internal scroll message.
aEatMessage = true;
return true;
@ -197,6 +220,81 @@ MouseScrollHandler::ProcessMessage(nsWindow* aWindow, UINT msg,
}
}
/* static */
nsresult
MouseScrollHandler::SynthesizeNativeMouseScrollEvent(nsWindow* aWindow,
const nsIntPoint& aPoint,
PRUint32 aNativeMessage,
PRInt32 aDelta,
PRUint32 aModifierFlags,
PRUint32 aAdditionalFlags)
{
bool useFocusedWindow =
!(aAdditionalFlags & nsIDOMWindowUtils::MOUSESCROLL_PREFER_WIDGET_AT_POINT);
POINT pt;
pt.x = aPoint.x;
pt.y = aPoint.y;
HWND target = useFocusedWindow ? ::WindowFromPoint(pt) : ::GetFocus();
NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
WPARAM wParam = 0;
LPARAM lParam = 0;
switch (aNativeMessage) {
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL: {
lParam = MAKELPARAM(pt.x, pt.y);
WORD mod = 0;
if (aModifierFlags & (nsIWidget::CTRL_L | nsIWidget::CTRL_R)) {
mod |= MK_CONTROL;
}
if (aModifierFlags & (nsIWidget::SHIFT_L | nsIWidget::SHIFT_R)) {
mod |= MK_SHIFT;
}
wParam = MAKEWPARAM(mod, aDelta);
break;
}
case WM_VSCROLL:
case WM_HSCROLL:
lParam = (aAdditionalFlags &
nsIDOMWindowUtils::MOUSESCROLL_WIN_SCROLL_LPARAM_NOT_NULL) ?
reinterpret_cast<LPARAM>(target) : NULL;
wParam = aDelta;
break;
default:
return NS_ERROR_INVALID_ARG;
}
// Ensure to make the instance.
GetInstance();
BYTE kbdState[256];
memset(kbdState, 0, sizeof(kbdState));
nsAutoTArray<KeyPair,10> keySequence;
nsWindow::SetupKeyModifiersSequence(&keySequence, aModifierFlags);
for (PRUint32 i = 0; i < keySequence.Length(); ++i) {
PRUint8 key = keySequence[i].mGeneral;
PRUint8 keySpecific = keySequence[i].mSpecific;
kbdState[key] = 0x81; // key is down and toggled on if appropriate
if (keySpecific) {
kbdState[keySpecific] = 0x81;
}
}
if (!sInstance->mSynthesizingEvent) {
sInstance->mSynthesizingEvent = new SynthesizingEvent();
}
POINTS pts;
pts.x = static_cast<SHORT>(pt.x);
pts.y = static_cast<SHORT>(pt.y);
return sInstance->mSynthesizingEvent->
Synthesize(pts, target, aNativeMessage, wParam, lParam, kbdState);
}
/* static */
bool
MouseScrollHandler::DispatchEvent(nsWindow* aWindow, nsGUIEvent& aEvent)
@ -204,6 +302,28 @@ MouseScrollHandler::DispatchEvent(nsWindow* aWindow, nsGUIEvent& aEvent)
return aWindow->DispatchWindowEvent(&aEvent);
}
/* static */
void
MouseScrollHandler::InitEvent(nsWindow* aWindow,
nsGUIEvent& aEvent,
nsIntPoint* aPoint)
{
NS_ENSURE_TRUE(aWindow, );
nsIntPoint point;
if (aPoint) {
point = *aPoint;
} else {
POINTS pts = GetCurrentMessagePos();
POINT pt;
pt.x = pts.x;
pt.y = pts.y;
::ScreenToClient(aWindow->GetWindowHandle(), &pt);
point.x = pt.x;
point.y = pt.y;
}
aWindow->InitEvent(aEvent, &point);
}
/* static */
nsModifierKeyState
MouseScrollHandler::GetModifierKeyState(UINT aMessage)
@ -231,11 +351,10 @@ MouseScrollHandler::ComputeMessagePos(UINT aMessage,
("MouseScroll::ComputeMessagePos: Using ::GetCursorPos()"));
::GetCursorPos(&point);
} else {
DWORD dwPoints = ::GetMessagePos();
point.x = GET_X_LPARAM(dwPoints);
point.y = GET_Y_LPARAM(dwPoints);
POINTS pts = GetCurrentMessagePos();
point.x = pts.x;
point.y = pts.y;
}
return point;
}
@ -261,7 +380,7 @@ MouseScrollHandler::GetScrollTargetInfo(
}
nsMouseScrollEvent testEvent(true, NS_MOUSE_SCROLL, aWindow);
aWindow->InitEvent(testEvent);
InitEvent(aWindow, testEvent);
aModifierKeyState.InitInputEvent(testEvent);
testEvent.scrollFlags = aEventInfo.GetScrollFlags();
@ -272,7 +391,7 @@ MouseScrollHandler::GetScrollTargetInfo(
}
nsQueryContentEvent queryEvent(true, NS_QUERY_SCROLL_TARGET_INFO, aWindow);
aWindow->InitEvent(queryEvent);
InitEvent(aWindow, queryEvent);
queryEvent.InitForQueryScrollTargetInfo(&testEvent);
DispatchEvent(aWindow, queryEvent);
@ -330,6 +449,11 @@ MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindow* aWindow,
WPARAM aWParam,
LPARAM aLParam)
{
if (SynthesizingEvent::IsSynthesizing()) {
mSynthesizingEvent->NativeMessageReceived(aWindow, aMessage,
aWParam, aLParam);
}
POINT point = ComputeMessagePos(aMessage, aWParam, aLParam);
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
@ -408,6 +532,7 @@ MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindow* aWindow,
("MouseScroll::ProcessNativeMouseWheelMessage: Succeeded, "
"Posting internal message to an nsWindow (%p)...",
destWindow));
mIsWaitingInternalMessage = true;
UINT internalMessage = WinUtils::GetInternalMessage(aMessage);
::PostMessage(destWindow->GetWindowHandle(), internalMessage,
aWParam, aLParam);
@ -447,6 +572,7 @@ MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindow* aWindow,
"Posting internal message to an nsWindow (%p) which is parent of this "
"plugin window...",
destWindow));
mIsWaitingInternalMessage = true;
UINT internalMessage = WinUtils::GetInternalMessage(aMessage);
::PostMessage(destWindow->GetWindowHandle(), internalMessage,
aWParam, aLParam);
@ -475,6 +601,11 @@ MouseScrollHandler::ProcessNativeScrollMessage(nsWindow* aWindow,
return true;
}
if (SynthesizingEvent::IsSynthesizing()) {
mSynthesizingEvent->NativeMessageReceived(aWindow, aMessage,
aWParam, aLParam);
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScroll::ProcessNativeScrollMessage: aWindow=%p, "
"aMessage=%s, wParam=0x%08X, lParam=0x%08X",
@ -537,6 +668,8 @@ MouseScrollHandler::HandleMouseWheelMessage(nsWindow* aWindow,
aWindow, aMessage == MOZ_WM_MOUSEVWHEEL ? "V" : "H",
aWParam, aLParam));
mIsWaitingInternalMessage = false;
EventInfo eventInfo(aWindow, WinUtils::GetNativeMessage(aMessage),
aWParam, aLParam);
if (!eventInfo.CanDispatchMouseScrollEvent()) {
@ -623,6 +756,8 @@ MouseScrollHandler::HandleScrollMessageAsMouseWheelMessage(nsWindow* aWindow,
"HandleScrollMessageAsMouseWheelMessage must be called with "
"MOZ_WM_VSCROLL or MOZ_WM_HSCROLL");
mIsWaitingInternalMessage = false;
nsModifierKeyState modKeyState = GetModifierKeyState(aMessage);
nsMouseScrollEvent scrollEvent(true, NS_MOUSE_SCROLL, aWindow);
@ -647,7 +782,7 @@ MouseScrollHandler::HandleScrollMessageAsMouseWheelMessage(nsWindow* aWindow,
// XXX Current mouse position may not be same as when the original message
// is received. We need to know the actual mouse cursor position when
// the original message was received.
aWindow->InitEvent(scrollEvent);
InitEvent(aWindow, scrollEvent);
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScroll::HandleScrollMessageAsMouseWheelMessage: aWindow=%p, "
@ -784,7 +919,7 @@ MouseScrollHandler::LastEventInfo::InitMouseScrollEvent(
// XXX Why don't we use lParam value? We should use lParam value because
// our internal message is always posted by original message handler.
// So, GetMessagePos() may return different cursor position.
aWindow->InitEvent(aMouseScrollEvent);
InitEvent(aWindow, aMouseScrollEvent);
aModKeyState.InitInputEvent(aMouseScrollEvent);
@ -856,7 +991,7 @@ MouseScrollHandler::LastEventInfo::InitMousePixelScrollEvent(
// XXX Why don't we use lParam value? We should use lParam value because
// our internal message is always posted by original message handler.
// So, GetMessagePos() may return different cursor position.
aWindow->InitEvent(aPixelScrollEvent);
InitEvent(aWindow, aPixelScrollEvent);
aModKeyState.InitInputEvent(aPixelScrollEvent);
@ -1217,7 +1352,7 @@ MouseScrollHandler::Device::Elantech::HandleKeyMessage(nsWindow* aWindow,
nsCommandEvent commandEvent(true, nsGkAtoms::onAppCommand,
(aWParam == VK_NEXT) ? nsGkAtoms::Forward : nsGkAtoms::Back, aWindow);
aWindow->InitEvent(commandEvent);
InitEvent(aWindow, commandEvent);
MouseScrollHandler::DispatchEvent(aWindow, commandEvent);
}
#ifdef PR_LOGGING
@ -1406,7 +1541,8 @@ MouseScrollHandler::Device::SetPoint::IsGetMessagePosResponseValid(
return false;
}
DWORD messagePos = ::GetMessagePos();
POINTS pts = MouseScrollHandler::GetCurrentMessagePos();
LPARAM messagePos = MAKELPARAM(pts.x, pts.y);
// XXX We should check whether SetPoint is installed or not by registry.
@ -1418,7 +1554,7 @@ MouseScrollHandler::Device::SetPoint::IsGetMessagePosResponseValid(
// But ::GetMessagePos() API always returns (0, 0) for them, even if the
// actual mouse cursor isn't 0,0. Therefore, we cannot trust the result of
// ::GetMessagePos API if the sender is SetPoint.
if (!sMightBeUsing && !aLParam && (DWORD)aLParam != messagePos &&
if (!sMightBeUsing && !aLParam && aLParam != messagePos &&
::InSendMessage()) {
sMightBeUsing = true;
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
@ -1435,5 +1571,151 @@ MouseScrollHandler::Device::SetPoint::IsGetMessagePosResponseValid(
return (sMightBeUsing && !aLParam && !messagePos);
}
/******************************************************************************
*
* SynthesizingEvent
*
******************************************************************************/
/* static */
bool
MouseScrollHandler::SynthesizingEvent::IsSynthesizing()
{
return MouseScrollHandler::sInstance &&
MouseScrollHandler::sInstance->mSynthesizingEvent &&
MouseScrollHandler::sInstance->mSynthesizingEvent->mStatus !=
NOT_SYNTHESIZING;
}
nsresult
MouseScrollHandler::SynthesizingEvent::Synthesize(const POINTS& aCursorPoint,
HWND aWnd,
UINT aMessage,
WPARAM aWParam,
LPARAM aLParam,
const BYTE (&aKeyStates)[256])
{
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::SynthesizingEvent::Synthesize(): aCursorPoint: { "
"x: %d, y: %d }, aWnd=0x%X, aMessage=0x%04X, aWParam=0x%08X, "
"aLParam=0x%08X, IsSynthesized()=%s, mStatus=%s",
aCursorPoint.x, aCursorPoint.y, aWnd, aMessage, aWParam, aLParam,
GetBoolName(IsSynthesizing()), GetStatusName()));
if (IsSynthesizing()) {
return NS_ERROR_NOT_AVAILABLE;
}
::GetKeyboardState(mOriginalKeyState);
// Note that we cannot use ::SetCursorPos() because it works asynchronously.
// We should SEND the message for reducing the possibility of receiving
// unexpected message which were not sent from here.
mCursorPoint = aCursorPoint;
mWnd = aWnd;
mMessage = aMessage;
mWParam = aWParam;
mLParam = aLParam;
memcpy(mKeyState, aKeyStates, sizeof(mKeyState));
::SetKeyboardState(mKeyState);
mStatus = SENDING_MESSAGE;
// Don't assume that aWnd is always managed by nsWindow. It might be
// a plugin window.
::SendMessage(aWnd, aMessage, aWParam, aLParam);
return NS_OK;
}
void
MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(nsWindow* aWindow,
UINT aMessage,
WPARAM aWParam,
LPARAM aLParam)
{
if (mStatus == SENDING_MESSAGE && mMessage == aMessage &&
mWParam == aWParam && mLParam == aLParam) {
mStatus = NATIVE_MESSAGE_RECEIVED;
if (aWindow && aWindow->GetWindowHandle() == mWnd) {
return;
}
// If the target window is not ours and received window is our plugin
// window, it comes from child window of the plugin.
if (aWindow && aWindow->GetWindowType() == eWindowType_plugin &&
!WinUtils::GetNSWindowPtr(mWnd)) {
return;
}
// Otherwise, the message may not be sent by us.
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(): "
"aWindow=%p, aWindow->GetWindowHandle()=0x%X, mWnd=0x%X, "
"aMessage=0x%04X, aWParam=0x%08X, aLParam=0x%08X, mStatus=%s",
aWindow, aWindow ? aWindow->GetWindowHandle() : 0, mWnd,
aMessage, aWParam, aLParam, GetStatusName()));
// We failed to receive our sent message, we failed to do the job.
Finish();
return;
}
void
MouseScrollHandler::SynthesizingEvent::NotifyNativeMessageHandlingFinished()
{
if (!IsSynthesizing()) {
return;
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::SynthesizingEvent::"
"NotifyNativeMessageHandlingFinished(): IsWaitingInternalMessage=%s",
GetBoolName(MouseScrollHandler::IsWaitingInternalMessage())));
if (MouseScrollHandler::IsWaitingInternalMessage()) {
mStatus = INTERNAL_MESSAGE_POSTED;
return;
}
// If the native message handler didn't post our internal message,
// we our job is finished.
// TODO: When we post the message to plugin window, there is remaning job.
Finish();
}
void
MouseScrollHandler::SynthesizingEvent::NotifyInternalMessageHandlingFinished()
{
if (!IsSynthesizing()) {
return;
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::SynthesizingEvent::"
"NotifyInternalMessageHandlingFinished()"));
Finish();
}
void
MouseScrollHandler::SynthesizingEvent::Finish()
{
if (!IsSynthesizing()) {
return;
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::SynthesizingEvent::Finish()"));
// Restore the original key state.
::SetKeyboardState(mOriginalKeyState);
mStatus = NOT_SYNTHESIZING;
}
} // namespace widget
} // namespace mozilla

View File

@ -16,6 +16,7 @@
class nsWindow;
class nsGUIEvent;
class nsMouseScrollEvent;
struct nsIntPoint;
struct nsModifierKeyState;
namespace mozilla {
@ -35,10 +36,33 @@ public:
LRESULT *aRetValue,
bool &aEatMessage);
/**
* See nsIWidget::SynthesizeNativeMouseScrollEvent() for the detail about
* this method.
*/
static nsresult SynthesizeNativeMouseScrollEvent(nsWindow* aWindow,
const nsIntPoint& aPoint,
PRUint32 aNativeMessage,
PRInt32 aDelta,
PRUint32 aModifierFlags,
PRUint32 aAdditionalFlags);
/**
* IsWaitingInternalMessage() returns true if MouseScrollHandler posted
* an internal message for a native mouse wheel message and has not
* received it. Otherwise, false.
*/
static bool IsWaitingInternalMessage()
{
return sInstance && sInstance->mIsWaitingInternalMessage;
}
private:
MouseScrollHandler();
~MouseScrollHandler();
bool mIsWaitingInternalMessage;
static MouseScrollHandler* sInstance;
/**
@ -48,6 +72,14 @@ private:
*/
static bool DispatchEvent(nsWindow* aWindow, nsGUIEvent& aEvent);
/**
* InitEvent() initializes the aEvent. If aPoint is null, the result of
* GetCurrentMessagePos() will be used.
*/
static void InitEvent(nsWindow* aWindow,
nsGUIEvent& aEvent,
nsIntPoint* aPoint = nsnull);
/**
* GetModifierKeyState() returns current modifier key state.
* Note that some devices need some hack for the modifier key state.
@ -57,6 +89,14 @@ private:
*/
static nsModifierKeyState GetModifierKeyState(UINT aMessage);
/**
* MozGetMessagePos() returns the mouse cursor position when GetMessage()
* was called last time. However, if we're sending a native message,
* this returns the specified cursor position by
* SynthesizeNativeMouseScrollEvent().
*/
static POINTS GetCurrentMessagePos();
/**
* ProcessNativeMouseWheelMessage() processes WM_MOUSEWHEEL and
* WM_MOUSEHWHEEL. Additionally, processes WM_VSCROLL and WM_HSCROLL if they
@ -350,6 +390,70 @@ private:
UserPrefs mUserPrefs;
class SynthesizingEvent {
public:
SynthesizingEvent() :
mWnd(NULL), mMessage(0), mWParam(0), mLParam(0),
mStatus(NOT_SYNTHESIZING)
{
}
~SynthesizingEvent() {}
static bool IsSynthesizing();
nsresult Synthesize(const POINTS& aCursorPoint, HWND aWnd,
UINT aMessage, WPARAM aWParam, LPARAM aLParam,
const BYTE (&aKeyStates)[256]);
void NativeMessageReceived(nsWindow* aWindow, UINT aMessage,
WPARAM aWParam, LPARAM aLParam);
void NotifyNativeMessageHandlingFinished();
void NotifyInternalMessageHandlingFinished();
const POINTS& GetCursorPoint() const { return mCursorPoint; }
private:
POINTS mCursorPoint;
HWND mWnd;
UINT mMessage;
WPARAM mWParam;
LPARAM mLParam;
BYTE mKeyState[256];
BYTE mOriginalKeyState[256];
enum Status {
NOT_SYNTHESIZING,
SENDING_MESSAGE,
NATIVE_MESSAGE_RECEIVED,
INTERNAL_MESSAGE_POSTED,
};
Status mStatus;
#ifdef PR_LOGGING
const char* GetStatusName()
{
switch (mStatus) {
case NOT_SYNTHESIZING:
return "NOT_SYNTHESIZING";
case SENDING_MESSAGE:
return "SENDING_MESSAGE";
case NATIVE_MESSAGE_RECEIVED:
return "NATIVE_MESSAGE_RECEIVED";
case INTERNAL_MESSAGE_POSTED:
return "INTERNAL_MESSAGE_POSTED";
default:
return "Unknown";
}
}
#endif
void Finish();
}; // SynthesizingEvent
SynthesizingEvent* mSynthesizingEvent;
public:
class Device {

View File

@ -43,6 +43,8 @@
#include "nsToolkit.h"
#include "nsThreadUtils.h"
#include "WinTaskbar.h"
#include "WinMouseScrollHandler.h"
#include "nsWindowDefs.h"
#include "nsString.h"
#include "nsIMM32Handler.h"
#include "mozilla/widget/AudioSession.h"
@ -79,6 +81,19 @@ using mozilla::crashreporter::LSPAnnotate;
static bool PeekUIMessage(MSG* aMsg)
{
// For avoiding deadlock between our process and plugin process by
// mouse wheel messages, we're handling actually when we receive one of
// following internal messages which is posted by native mouse wheel message
// handler. Any other events, especially native modifier key events, should
// not be handled between native message and posted internal message because
// it may make different modifier key state or mouse cursor position between
// them.
if (mozilla::widget::MouseScrollHandler::IsWaitingInternalMessage() &&
::PeekMessageW(aMsg, NULL, MOZ_WM_MOUSEWHEEL_FIRST,
MOZ_WM_MOUSEWHEEL_LAST, PM_REMOVE)) {
return true;
}
MSG keyMsg, imeMsg, mouseMsg, *pMsg = 0;
bool haveKeyMsg, haveIMEMsg, haveMouseMsg;

View File

@ -5798,6 +5798,22 @@ nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
return NS_OK;
}
nsresult
nsWindow::SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint,
PRUint32 aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
PRUint32 aModifierFlags,
PRUint32 aAdditionalFlags)
{
return MouseScrollHandler::SynthesizeNativeMouseScrollEvent(
this, aPoint, aNativeMessage,
(aNativeMessage == WM_MOUSEWHEEL || aNativeMessage == WM_VSCROLL) ?
static_cast<PRInt32>(aDeltaY) : static_cast<PRInt32>(aDeltaX),
aModifierFlags, aAdditionalFlags);
}
/**************************************************************
*
* SECTION: OnXXX message handlers

View File

@ -177,6 +177,13 @@ public:
virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint,
PRUint32 aNativeMessage,
PRUint32 aModifierFlags);
virtual nsresult SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint,
PRUint32 aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
PRUint32 aModifierFlags,
PRUint32 aAdditionalFlags);
NS_IMETHOD ResetInputState();
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
@ -295,6 +302,8 @@ public:
void PickerClosed();
bool const DestroyCalled() { return mDestroyCalled; }
static void SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, PRUint32 aModifiers);
protected:
// A magic number to identify the FAKETRACKPOINTSCROLLABLE window created
@ -458,7 +467,6 @@ protected:
UINT MapFromNativeToDOM(UINT aNativeKeyCode);
void StopFlashing();
static bool IsTopLevelMouseExit(HWND aWnd);
static void SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, PRUint32 aModifiers);
nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting);
nsIntRegion GetRegionToPaint(bool aForceFullRepaint,

View File

@ -64,6 +64,9 @@
#define MOZ_WM_MOUSEHWHEEL (WM_APP+0x0311)
#define MOZ_WM_VSCROLL (WM_APP+0x0312)
#define MOZ_WM_HSCROLL (WM_APP+0x0313)
#define MOZ_WM_MOUSEWHEEL_FIRST MOZ_WM_MOUSEVWHEEL
#define MOZ_WM_MOUSEWHEEL_LAST MOZ_WM_HSCROLL
// Internal message for ensuring the file picker is visible on multi monitor
// systems, and when the screen resolution changes.
#define MOZ_WM_ENSUREVISIBLE (WM_APP + 14159)