Bug 719320 part.6 Separate pixel delta value accumulation code r=smaug

This commit is contained in:
Masayuki Nakano 2012-08-12 10:42:35 +09:00
parent b65f092c51
commit 0127890358
2 changed files with 144 additions and 51 deletions

View File

@ -134,15 +134,12 @@ static PRUint32 gMouseOrKeyboardEventCounter = 0;
static nsITimer* gUserInteractionTimer = nullptr;
static nsITimerCallback* gUserInteractionTimerCallback = nullptr;
// Pixel scroll accumulation for synthetic line scrolls
static nscoord gPixelScrollDeltaX = 0;
static nscoord gPixelScrollDeltaY = 0;
static PRUint32 gPixelScrollDeltaTimeout = 0;
TimeStamp nsEventStateManager::sHandlingInputStart;
nsEventStateManager::WheelPrefs*
nsEventStateManager::WheelPrefs::sInstance = nullptr;
nsEventStateManager::PixelDeltaAccumulator*
nsEventStateManager::PixelDeltaAccumulator::sInstance = nullptr;
static inline bool
IsMouseEventReal(nsEvent* aEvent)
@ -844,6 +841,7 @@ nsEventStateManager::~nsEventStateManager()
nsresult
nsEventStateManager::Shutdown()
{
PixelDeltaAccumulator::Shutdown();
Preferences::RemoveObservers(this, kObservedPrefs);
m_haveShutdown = true;
return NS_OK;
@ -1137,6 +1135,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
if (content)
mCurrentTargetContent = content;
PixelDeltaAccumulator::GetInstance()->Reset();
nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(msEvent);
@ -1156,52 +1156,11 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsMouseScrollEvent *msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(msEvent);
// Clear old deltas after a period of non action
if (OutOfTime(gPixelScrollDeltaTimeout, nsMouseWheelTransaction::GetTimeoutTime())) {
gPixelScrollDeltaX = gPixelScrollDeltaY = 0;
}
gPixelScrollDeltaTimeout = PR_IntervalToMilliseconds(PR_IntervalNow());
// If needed send a line scroll event for pixel scrolls with kNoLines
if (msEvent->scrollFlags & nsMouseScrollEvent::kNoLines) {
nsIScrollableFrame* scrollableFrame =
ComputeScrollTarget(aTargetFrame, msEvent, false);
PRInt32 pixelsPerUnit =
nsPresContext::AppUnitsToIntCSSPixels(
GetScrollAmount(aPresContext, msEvent, aTargetFrame,
scrollableFrame));
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsVertical) {
gPixelScrollDeltaX += msEvent->delta;
if (!gPixelScrollDeltaX || !pixelsPerUnit)
break;
if (NS_ABS(gPixelScrollDeltaX) >= pixelsPerUnit) {
PRInt32 numLines = (PRInt32)ceil((float)gPixelScrollDeltaX/(float)pixelsPerUnit);
gPixelScrollDeltaX -= numLines*pixelsPerUnit;
nsWeakFrame weakFrame(aTargetFrame);
SendLineScrollEvent(aTargetFrame, msEvent, aPresContext,
aStatus, numLines);
NS_ENSURE_STATE(weakFrame.IsAlive());
}
} else if (msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal) {
gPixelScrollDeltaY += msEvent->delta;
if (!gPixelScrollDeltaY || !pixelsPerUnit)
break;
if (NS_ABS(gPixelScrollDeltaY) >= pixelsPerUnit) {
PRInt32 numLines = (PRInt32)ceil((float)gPixelScrollDeltaY/(float)pixelsPerUnit);
gPixelScrollDeltaY -= numLines*pixelsPerUnit;
nsWeakFrame weakFrame(aTargetFrame);
SendLineScrollEvent(aTargetFrame, msEvent, aPresContext,
aStatus, numLines);
NS_ENSURE_STATE(weakFrame.IsAlive());
}
}
}
nsWeakFrame weakFrame(aTargetFrame);
PixelDeltaAccumulator::GetInstance()->
OnMousePixelScrollEvent(aPresContext, aTargetFrame,
this, msEvent, aStatus);
NS_ENSURE_STATE(weakFrame.IsAlive());
// When the last line scroll has been canceled, eat the pixel scroll event
if ((msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal) ?
@ -5162,6 +5121,91 @@ nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
sActiveESM = nullptr;
}
/******************************************************************/
/* nsEventStateManager::PixelDeltaAccumulator */
/******************************************************************/
void
nsEventStateManager::PixelDeltaAccumulator::OnMousePixelScrollEvent(
nsPresContext* aPresContext,
nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus)
{
MOZ_ASSERT(aPresContext);
MOZ_ASSERT(aESM);
MOZ_ASSERT(aEvent);
MOZ_ASSERT(aEvent->message == NS_MOUSE_PIXEL_SCROLL);
MOZ_ASSERT(NS_IS_TRUSTED_EVENT(aEvent));
MOZ_ASSERT(aStatus);
if (!(aEvent->scrollFlags & nsMouseScrollEvent::kNoLines)) {
Reset();
return;
}
nsIScrollableFrame* scrollTarget =
aESM->ComputeScrollTarget(aTargetFrame, aEvent, false);
PRInt32 pixelsPerLine = nsPresContext::AppUnitsToIntCSSPixels(
aESM->GetScrollAmount(aPresContext, aEvent,
aTargetFrame, scrollTarget));
if (!mLastTime.IsNull()) {
TimeDuration duration = TimeStamp::Now() - mLastTime;
if (duration.ToMilliseconds() > nsMouseWheelTransaction::GetTimeoutTime()) {
Reset();
}
}
mLastTime = TimeStamp::Now();
bool isHorizontal =
(aEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal) != 0;
// If the delta direction is changed, we should reset the accumulated values.
if (mX && isHorizontal && aEvent->delta &&
((aEvent->delta > 0) != (mX > 0))) {
mX = 0;
}
if (mY && !isHorizontal && aEvent->delta &&
((aEvent->delta > 0) != (mY > 0))) {
mY = 0;
}
PRInt32 numLines;
if (isHorizontal) {
// Adds delta value, first.
mX += aEvent->delta;
// Compute lines in integer scrolled by the accumulated delta value.
numLines =
static_cast<PRInt32>(NS_round(static_cast<double>(mX) / pixelsPerLine));
// Consume the lines from the accumulated delta value.
mX -= numLines * pixelsPerLine;
} else {
// Adds delta value, first.
mY += aEvent->delta;
// Compute lines in integer scrolled by the accumulated delta value.
numLines =
static_cast<PRInt32>(NS_round(static_cast<double>(mY) / pixelsPerLine));
// Consume the lines from the accumulated delta value.
mY -= numLines * pixelsPerLine;
}
if (!numLines) {
return;
}
aESM->SendLineScrollEvent(aTargetFrame, aEvent, aPresContext,
aStatus, numLines);
}
void
nsEventStateManager::PixelDeltaAccumulator::Reset()
{
mX = mY = 0;
}
/******************************************************************/
/* nsEventStateManager::WheelPrefs */

View File

@ -464,6 +464,55 @@ protected:
*/
PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent);
/**
* PixelDeltaAccumulator class manages pixel delta values for dispatching
* DOMMouseScroll event.
*/
class PixelDeltaAccumulator
{
public:
static PixelDeltaAccumulator* GetInstance()
{
if (!sInstance) {
sInstance = new PixelDeltaAccumulator;
}
return sInstance;
}
static void Shutdown()
{
delete sInstance;
sInstance = nullptr;
}
/**
* OnMousePixelScrollEvent() stores pixel delta values. And if the
* accumulated delta becomes a line height, dispatches DOMMouseScroll event
* automatically.
*/
void OnMousePixelScrollEvent(nsPresContext* aPresContext,
nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus);
/**
* Reset() resets both delta values.
*/
void Reset();
private:
PixelDeltaAccumulator() :
mX(0), mY(0)
{
}
PRInt32 mX;
PRInt32 mY;
TimeStamp mLastTime;
static PixelDeltaAccumulator* sInstance;
};
// end mousewheel functions
/*