Bug 672175 part.7 Manage last wheel scroll message information by MouseScrollHandler::LastEventInfo r=jimm

This commit is contained in:
Masayuki Nakano 2012-03-06 12:20:28 +09:00
Родитель f441247ea3
Коммит c420e187b8
4 изменённых файлов: 134 добавлений и 77 удалений

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

@ -65,6 +65,11 @@ bool MouseScrollHandler::Device::Elantech::sUseSwipeHack = false;
bool MouseScrollHandler::Device::Elantech::sUsePinchHack = false;
DWORD MouseScrollHandler::Device::Elantech::sZoomUntil = 0;
// The duration until timeout of events transaction. The value is 1.5 sec,
// it's just a magic number, it was suggested by Logitech's engineer, see
// bug 605648 comment 90.
#define DEFAULT_TIMEOUT_DURATION 1500
/******************************************************************************
*
* MouseScrollHandler
@ -168,7 +173,8 @@ MouseScrollHandler::DispatchEvent(nsWindow* aWindow, nsGUIEvent& aEvent)
*
******************************************************************************/
MouseScrollHandler::EventInfo::EventInfo(UINT aMessage,
MouseScrollHandler::EventInfo::EventInfo(nsWindow* aWindow,
UINT aMessage,
WPARAM aWParam, LPARAM aLParam)
{
NS_ABORT_IF_FALSE(aMessage == WM_MOUSEWHEEL || aMessage == WM_MOUSEHWHEEL,
@ -180,6 +186,8 @@ MouseScrollHandler::EventInfo::EventInfo(UINT aMessage,
mIsPage = MouseScrollHandler::sInstance->
mSystemSettings.IsPageScroll(mIsVertical);
mDelta = (short)HIWORD(aWParam);
mWnd = aWindow->GetWindowHandle();
mTimeStamp = TimeStamp::Now();
}
bool
@ -214,6 +222,50 @@ MouseScrollHandler::EventInfo::GetScrollFlags() const
return result;
}
/******************************************************************************
*
* LastEventInfo
*
******************************************************************************/
bool
MouseScrollHandler::LastEventInfo::CanContinueTransaction(
const EventInfo& aNewEvent)
{
return !mWnd ||
(mWnd == aNewEvent.GetWindowHandle() &&
IsPositive() == aNewEvent.IsPositive() &&
mIsVertical == aNewEvent.IsVertical() &&
mIsPage == aNewEvent.IsPage() &&
TimeStamp::Now() - mTimeStamp <=
TimeDuration::FromMilliseconds(DEFAULT_TIMEOUT_DURATION));
}
void
MouseScrollHandler::LastEventInfo::ResetTransaction()
{
if (!mWnd) {
return;
}
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScroll::LastEventInfo::ResetTransaction()"));
mWnd = nsnull;
mRemainingDeltaForScroll = 0;
mRemainingDeltaForPixel = 0;
}
void
MouseScrollHandler::LastEventInfo::RecordEvent(const EventInfo& aEvent)
{
mWnd = aEvent.GetWindowHandle();
mDelta = aEvent.GetNativeDelta();
mIsVertical = aEvent.IsVertical();
mIsPage = aEvent.IsPage();
mTimeStamp = TimeStamp::Now();
}
/******************************************************************************
*
* SystemSettings
@ -278,6 +330,10 @@ MouseScrollHandler::SystemSettings::MarkDirty()
("MouseScrollHandler::SystemSettings::MarkDirty(): "
"Marking SystemSettings dirty"));
mInitialized = false;
// When system settings are changed, we should reset current transaction.
MOZ_ASSERT(sInstance,
"Must not be called at initializing MouseScrollHandler");
MouseScrollHandler::sInstance->mLastEventInfo.ResetTransaction();
}
/******************************************************************************
@ -332,6 +388,11 @@ MouseScrollHandler::UserPrefs::MarkDirty()
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
("MouseScrollHandler::UserPrefs::MarkDirty(): Marking UserPrefs dirty"));
mInitialized = false;
// When user prefs for mousewheel are changed, we should reset current
// transaction.
MOZ_ASSERT(sInstance,
"Must not be called at initializing MouseScrollHandler");
MouseScrollHandler::sInstance->mLastEventInfo.ResetTransaction();
}
/******************************************************************************

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

@ -10,6 +10,7 @@
#include "nscore.h"
#include "nsDebug.h"
#include "mozilla/Assertions.h"
#include "mozilla/TimeStamp.h"
#include <windows.h>
class nsWindow;
@ -49,13 +50,16 @@ public:
class EventInfo {
public:
/**
* @param aWindow An nsWindow which is handling the event.
* @param aMessage Must be WM_MOUSEWHEEL or WM_MOUSEHWHEEL.
*/
EventInfo(UINT aMessage, WPARAM aWParam, LPARAM aLParam);
EventInfo(nsWindow* aWindow, UINT aMessage, WPARAM aWParam, LPARAM aLParam);
bool CanDispatchMouseScrollEvent() const;
PRInt32 GetNativeDelta() const { return mDelta; }
HWND GetWindowHandle() const { return mWnd; }
const TimeStamp& GetTimeStamp() const { return mTimeStamp; }
bool IsVertical() const { return mIsVertical; }
bool IsPositive() const { return (mDelta > 0); }
bool IsPage() const { return mIsPage; }
@ -76,8 +80,11 @@ public:
*/
PRInt32 GetScrollFlags() const;
private:
EventInfo() {}
protected:
EventInfo() :
mIsVertical(false), mIsPage(false), mDelta(0), mWnd(nsnull)
{
}
// TRUE if event is for vertical scroll. Otherwise, FALSE.
bool mIsVertical;
@ -85,8 +92,48 @@ public:
bool mIsPage;
// The native delta value.
PRInt32 mDelta;
// The window handle which is handling the event.
HWND mWnd;
// Timestamp of the event.
TimeStamp mTimeStamp;
};
class LastEventInfo : public EventInfo {
public:
LastEventInfo() :
EventInfo(), mRemainingDeltaForScroll(0), mRemainingDeltaForPixel(0)
{
}
/**
* CanContinueTransaction() checks whether the new event can continue the
* last transaction or not. Note that if there is no transaction, this
* returns true.
*/
bool CanContinueTransaction(const EventInfo& aNewEvent);
/**
* ResetTransaction() resets the transaction, i.e., the instance forgets
* the last event information.
*/
void ResetTransaction();
/**
* RecordEvent() saves the information of new event.
*/
void RecordEvent(const EventInfo& aEvent);
// The remaining native delta value (i.e., not handled by previous
// message handler).
PRInt32 mRemainingDeltaForScroll;
PRInt32 mRemainingDeltaForPixel;
};
LastEventInfo& GetLastEventInfo() { return mLastEventInfo; }
private:
LastEventInfo mLastEventInfo;
public:
class SystemSettings {
public:

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

@ -286,16 +286,6 @@ PRUint32 nsWindow::sOOPPPluginFocusEvent =
MSG nsWindow::sRedirectedKeyDown;
bool nsWindow::sNeedsToInitMouseWheelSettings = true;
HWND nsWindow::sLastMouseWheelWnd = NULL;
PRInt32 nsWindow::sRemainingDeltaForScroll = 0;
PRInt32 nsWindow::sRemainingDeltaForPixel = 0;
bool nsWindow::sLastMouseWheelDeltaIsPositive = false;
bool nsWindow::sLastMouseWheelOrientationIsVertical = false;
bool nsWindow::sLastMouseWheelUnitIsPage = false;
PRUint32 nsWindow::sLastMouseWheelTime = 0;
/**************************************************************
*
* SECTION: globals variables
@ -5160,15 +5150,6 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
}
break;
case WM_SETTINGCHANGE:
switch (wParam) {
case SPI_SETWHEELSCROLLLINES:
case SPI_SETWHEELSCROLLCHARS:
sNeedsToInitMouseWheelSettings = true;
break;
}
break;
case WM_INPUTLANGCHANGEREQUEST:
*aRetValue = TRUE;
result = false;
@ -6277,25 +6258,6 @@ bool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam)
return true; // Handled
}
/* static */ void
nsWindow::InitMouseWheelScrollData()
{
if (!sNeedsToInitMouseWheelSettings) {
return;
}
sNeedsToInitMouseWheelSettings = false;
ResetRemainingWheelDelta();
}
/* static */
void
nsWindow::ResetRemainingWheelDelta()
{
sRemainingDeltaForPixel = 0;
sRemainingDeltaForScroll = 0;
sLastMouseWheelWnd = NULL;
}
static PRInt32 RoundDelta(double aDelta)
{
return aDelta >= 0 ? (PRInt32)floor(aDelta) : (PRInt32)ceil(aDelta);
@ -6310,32 +6272,25 @@ void
nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
LRESULT *aRetValue)
{
InitMouseWheelScrollData();
MouseScrollHandler::EventInfo eventInfo(aMessage, aWParam, aLParam);
MouseScrollHandler* handler = MouseScrollHandler::GetInstance();
MouseScrollHandler::EventInfo eventInfo(this, aMessage, aWParam, aLParam);
if (!eventInfo.CanDispatchMouseScrollEvent()) {
ResetRemainingWheelDelta();
handler->GetLastEventInfo().ResetTransaction();
*aRetValue = eventInfo.ComputeMessageResult(false);
return;
}
MouseScrollHandler::LastEventInfo& lastEventInfo =
handler->GetLastEventInfo();
// Discard the remaining delta if current wheel message and last one are
// received by different window or to scroll different direction or
// different unit scroll. Furthermore, if the last event was too old.
PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
if (sLastMouseWheelWnd &&
(sLastMouseWheelWnd != mWnd ||
sLastMouseWheelDeltaIsPositive != eventInfo.IsPositive() ||
sLastMouseWheelOrientationIsVertical != eventInfo.IsVertical() ||
sLastMouseWheelUnitIsPage != eventInfo.IsPage() ||
now - sLastMouseWheelTime > 1500)) {
ResetRemainingWheelDelta();
if (!lastEventInfo.CanContinueTransaction(eventInfo)) {
lastEventInfo.ResetTransaction();
}
sLastMouseWheelWnd = mWnd;
sLastMouseWheelDeltaIsPositive = eventInfo.IsPositive();
sLastMouseWheelOrientationIsVertical = eventInfo.IsVertical();
sLastMouseWheelUnitIsPage = eventInfo.IsPage();
sLastMouseWheelTime = now;
lastEventInfo.RecordEvent(eventInfo);
// means we process this message
*aRetValue = eventInfo.ComputeMessageResult(true);
@ -6386,8 +6341,8 @@ nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
testEvent.isAlt = scrollEvent.isAlt;
testEvent.delta = computedScrollAmount;
if ((eventInfo.IsVertical() && sLastMouseWheelDeltaIsPositive) ||
(!eventInfo.IsVertical() && !sLastMouseWheelDeltaIsPositive)) {
if ((eventInfo.IsVertical() && eventInfo.IsPositive()) ||
(!eventInfo.IsVertical() && !eventInfo.IsPositive())) {
testEvent.delta *= -1;
}
nsQueryContentEvent queryEvent(true, NS_QUERY_SCROLL_TARGET_INFO, this);
@ -6429,14 +6384,15 @@ nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
scrollEvent.scrollFlags |= eventInfo.GetScrollFlags();
PRInt32 nativeDeltaForScroll =
eventInfo.GetNativeDelta() + sRemainingDeltaForScroll;
eventInfo.GetNativeDelta() + lastEventInfo.mRemainingDeltaForScroll;
// NOTE: Don't use computedScrollAmount for computing the delta value of
// line/page scroll event. The value will be recomputed in ESM.
if (eventInfo.IsPage()) {
scrollEvent.delta = nativeDeltaForScroll * orienter / WHEEL_DELTA;
PRInt32 recomputedNativeDelta = scrollEvent.delta * orienter / WHEEL_DELTA;
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
lastEventInfo.mRemainingDeltaForScroll =
nativeDeltaForScroll - recomputedNativeDelta;
} else {
double deltaPerUnit;
deltaPerUnit =
@ -6445,20 +6401,21 @@ nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
RoundDelta((double)nativeDeltaForScroll * orienter / deltaPerUnit);
PRInt32 recomputedNativeDelta =
(PRInt32)(scrollEvent.delta * orienter * deltaPerUnit);
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
lastEventInfo.mRemainingDeltaForScroll =
nativeDeltaForScroll - recomputedNativeDelta;
}
if (scrollEvent.delta) {
DispatchWindowEvent(&scrollEvent);
if (mOnDestroyCalled) {
ResetRemainingWheelDelta();
lastEventInfo.ResetTransaction();
return;
}
}
// If the query event failed, we cannot send pixel events.
if (!dispatchPixelScrollEvent) {
sRemainingDeltaForPixel = 0;
lastEventInfo.mRemainingDeltaForPixel = 0;
return;
}
@ -6477,7 +6434,7 @@ nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
pixelEvent.isAlt = scrollEvent.isAlt;
PRInt32 nativeDeltaForPixel =
eventInfo.GetNativeDelta() + sRemainingDeltaForPixel;
eventInfo.GetNativeDelta() + lastEventInfo.mRemainingDeltaForPixel;
// Pixel scroll event won't be recomputed the scroll amout and direction by
// ESM. Therefore, we need to set the computed amout and direction here.
PRInt32 orienterForPixel = reversePixelScrollDirection ? -orienter : orienter;
@ -6488,7 +6445,8 @@ nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
RoundDelta((double)nativeDeltaForPixel * orienterForPixel / deltaPerPixel);
PRInt32 recomputedNativeDelta =
(PRInt32)(pixelEvent.delta * orienterForPixel * deltaPerPixel);
sRemainingDeltaForPixel = nativeDeltaForPixel - recomputedNativeDelta;
lastEventInfo.mRemainingDeltaForPixel =
nativeDeltaForPixel - recomputedNativeDelta;
if (pixelEvent.delta != 0) {
DispatchWindowEvent(&pixelEvent);
}

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

@ -604,15 +604,6 @@ protected:
static bool sNeedsToInitMouseWheelSettings;
static void InitMouseWheelScrollData();
static HWND sLastMouseWheelWnd;
static PRInt32 sRemainingDeltaForScroll;
static PRInt32 sRemainingDeltaForPixel;
static bool sLastMouseWheelDeltaIsPositive;
static bool sLastMouseWheelOrientationIsVertical;
static bool sLastMouseWheelUnitIsPage;
static PRUint32 sLastMouseWheelTime; // in milliseconds
static void ResetRemainingWheelDelta();
// If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
// redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event
// because it has been dispatched before the message was redirected.