Bug 719320 part.8-6 Init lineOrPageDeltaX and lineOrPageDeltaY from accumulated delta values if the wheel event is caused by pixel scroll only device or the delta values have been modified with prefs r=smaug

This commit is contained in:
Masayuki Nakano 2012-08-12 10:42:36 +09:00
Родитель 24a276180b
Коммит e98c45fc9f
5 изменённых файлов: 127 добавлений и 84 удалений

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

@ -751,6 +751,7 @@ nsDOMEvent::DuplicatePrivateData()
wheelEvent->modifiers = oldWheelEvent->modifiers; wheelEvent->modifiers = oldWheelEvent->modifiers;
wheelEvent->inputSource = oldWheelEvent->inputSource; wheelEvent->inputSource = oldWheelEvent->inputSource;
wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs; wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs;
wheelEvent->isPixelOnlyDevice = oldWheelEvent->isPixelOnlyDevice;
wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX; wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX;
wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY; wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY;
wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX; wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX;

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

@ -138,8 +138,8 @@ TimeStamp nsEventStateManager::sHandlingInputStart;
nsEventStateManager::WheelPrefs* nsEventStateManager::WheelPrefs*
nsEventStateManager::WheelPrefs::sInstance = nullptr; nsEventStateManager::WheelPrefs::sInstance = nullptr;
nsEventStateManager::PixelDeltaAccumulator* nsEventStateManager::DeltaAccumulator*
nsEventStateManager::PixelDeltaAccumulator::sInstance = nullptr; nsEventStateManager::DeltaAccumulator::sInstance = nullptr;
static inline PRInt32 static inline PRInt32
RoundDown(double aDouble) RoundDown(double aDouble)
@ -810,6 +810,7 @@ nsEventStateManager::~nsEventStateManager()
NS_RELEASE(gUserInteractionTimer); NS_RELEASE(gUserInteractionTimer);
} }
WheelPrefs::Shutdown(); WheelPrefs::Shutdown();
DeltaAccumulator::Shutdown();
} }
if (sDragOverContent && sDragOverContent->OwnerDoc() == mDocument) { if (sDragOverContent && sDragOverContent->OwnerDoc() == mDocument) {
@ -835,7 +836,6 @@ nsEventStateManager::~nsEventStateManager()
nsresult nsresult
nsEventStateManager::Shutdown() nsEventStateManager::Shutdown()
{ {
PixelDeltaAccumulator::Shutdown();
Preferences::RemoveObservers(this, kObservedPrefs); Preferences::RemoveObservers(this, kObservedPrefs);
m_haveShutdown = true; m_haveShutdown = true;
return NS_OK; return NS_OK;
@ -1132,6 +1132,13 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(aEvent); widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(aEvent);
WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent); WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
// Init lineOrPageDelta values for line scroll events for some devices
// on some platforms which might dispatch wheel events which don't have
// lineOrPageDelta values. And also, if delta values are customized by
// prefs, this recomputes them.
DeltaAccumulator::GetInstance()->
InitLineOrPageDelta(aTargetFrame, this, wheelEvent);
} }
break; break;
case NS_QUERY_SELECTED_TEXT: case NS_QUERY_SELECTED_TEXT:
@ -5140,91 +5147,95 @@ nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
} }
/******************************************************************/ /******************************************************************/
/* nsEventStateManager::PixelDeltaAccumulator */ /* nsEventStateManager::DeltaAccumulator */
/******************************************************************/ /******************************************************************/
void void
nsEventStateManager::PixelDeltaAccumulator::OnMousePixelScrollEvent( nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
nsPresContext* aPresContext, nsIFrame* aTargetFrame,
nsIFrame* aTargetFrame, nsEventStateManager* aESM,
nsEventStateManager* aESM, widget::WheelEvent* aEvent)
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus)
{ {
MOZ_ASSERT(aPresContext);
MOZ_ASSERT(aESM); MOZ_ASSERT(aESM);
MOZ_ASSERT(aEvent); 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)) { if (!(aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL &&
aEvent->isPixelOnlyDevice) &&
!WheelPrefs::GetInstance()->NeedToComputeLineOrPageDelta(aEvent)) {
Reset(); Reset();
return; return;
} }
#if 0 // Reset if the previous wheel event is too old.
nsIScrollableFrame* scrollTarget =
aESM->ComputeScrollTarget(aTargetFrame, aEvent, false);
nsSize scrollAmount =
aESM->GetScrollAmount(aPresContext, aEvent, aTargetFrame, scrollTarget);
bool isHorizontal =
(aEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal) != 0;
PRInt32 pixelsPerLine =
nsPresContext::AppUnitsToIntCSSPixels(isHorizontal ? scrollAmount.width :
scrollAmount.height);
if (!mLastTime.IsNull()) { if (!mLastTime.IsNull()) {
TimeDuration duration = TimeStamp::Now() - mLastTime; TimeDuration duration = TimeStamp::Now() - mLastTime;
if (duration.ToMilliseconds() > nsMouseWheelTransaction::GetTimeoutTime()) { if (duration.ToMilliseconds() > nsMouseWheelTransaction::GetTimeoutTime()) {
Reset(); Reset();
} }
} }
// If we have accumulated delta, we may need to reset it.
if (mHandlingDeltaMode != PR_UINT32_MAX) {
// If wheel event type is changed, reset the values.
if (mHandlingDeltaMode != aEvent->deltaMode ||
mHandlingPixelOnlyDevice != aEvent->isPixelOnlyDevice) {
Reset();
} else {
// If the delta direction is changed, we should reset only the
// accumulated values.
if (mX && aEvent->deltaX && ((aEvent->deltaX > 0.0) != (mX > 0.0))) {
mX = 0.0;
}
if (mY && aEvent->deltaY && ((aEvent->deltaY > 0.0) != (mY > 0.0))) {
mY = 0.0;
}
}
}
mHandlingDeltaMode = aEvent->deltaMode;
mHandlingPixelOnlyDevice = aEvent->isPixelOnlyDevice;
mX += aEvent->deltaX;
mY += aEvent->deltaY;
if (mHandlingDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) {
// Records pixel delta values and init lineOrPageDeltaX and
// lineOrPageDeltaY for wheel events which are caused by pixel only
// devices. Ignore mouse wheel transaction for computing this. The
// lineOrPageDelta values will be used by dispatching legacy
// NS_MOUSE_SCROLL_EVENT (DOMMouseScroll) but not be used for scrolling
// of default action. The transaction should be used only for the default
// action.
nsIScrollableFrame* scrollTarget =
aESM->ComputeScrollTarget(aTargetFrame, aEvent, false);
nsIFrame* frame = do_QueryFrame(scrollTarget);
nsPresContext* pc =
frame ? frame->PresContext() : aTargetFrame->PresContext();
nsSize scrollAmount = aESM->GetScrollAmount(pc, aEvent, scrollTarget);
nsIntSize scrollAmountInCSSPixels(
nsPresContext::AppUnitsToIntCSSPixels(scrollAmount.width),
nsPresContext::AppUnitsToIntCSSPixels(scrollAmount.height));
aEvent->lineOrPageDeltaX = RoundDown(mX) / scrollAmountInCSSPixels.width;
aEvent->lineOrPageDeltaY = RoundDown(mY) / scrollAmountInCSSPixels.height;
mX -= aEvent->lineOrPageDeltaX * scrollAmountInCSSPixels.width;
mY -= aEvent->lineOrPageDeltaY * scrollAmountInCSSPixels.height;
} else {
aEvent->lineOrPageDeltaX = RoundDown(mX);
aEvent->lineOrPageDeltaY = RoundDown(mY);
mX -= aEvent->lineOrPageDeltaX;
mY -= aEvent->lineOrPageDeltaY;
}
mLastTime = TimeStamp::Now(); mLastTime = TimeStamp::Now();
// 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);
#endif
} }
void void
nsEventStateManager::PixelDeltaAccumulator::Reset() nsEventStateManager::DeltaAccumulator::Reset()
{ {
mX = mY = 0; mX = mY = 0.0;
mHandlingDeltaMode = PR_UINT32_MAX;
mHandlingPixelOnlyDevice = false;
} }
/******************************************************************/ /******************************************************************/
@ -5256,6 +5267,7 @@ nsEventStateManager::WheelPrefs::OnPrefChanged(const char* aPrefName,
{ {
// forget all prefs, it's not problem for performance. // forget all prefs, it's not problem for performance.
sInstance->Reset(); sInstance->Reset();
DeltaAccumulator::GetInstance()->Reset();
return 0; return 0;
} }
@ -5410,3 +5422,14 @@ nsEventStateManager::WheelPrefs::GetActionFor(nsMouseScrollEvent* aEvent)
Init(index); Init(index);
return mActions[index]; return mActions[index];
} }
bool
nsEventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
widget::WheelEvent* aEvent)
{
Index index = GetIndexFor(aEvent);
Init(index);
return (mMultiplierX[index] != 1.0 && mMultiplierX[index] != -1.0) ||
(mMultiplierY[index] != 1.0 && mMultiplierY[index] != -1.0);
}

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

@ -351,6 +351,12 @@ protected:
}; };
Action GetActionFor(nsMouseScrollEvent* aEvent); Action GetActionFor(nsMouseScrollEvent* aEvent);
/**
* NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
* computed the lineOrPageDelta values.
*/
bool NeedToComputeLineOrPageDelta(mozilla::widget::WheelEvent* aEvent);
private: private:
WheelPrefs(); WheelPrefs();
~WheelPrefs(); ~WheelPrefs();
@ -499,16 +505,18 @@ protected:
PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent); PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent);
/** /**
* PixelDeltaAccumulator class manages pixel delta values for dispatching * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
* DOMMouseScroll event. * event. If wheel events are caused by pixel scroll only devices or
* the delta values are customized by prefs, this class stores the delta
* values and set lineOrPageDelta values.
*/ */
class PixelDeltaAccumulator class DeltaAccumulator
{ {
public: public:
static PixelDeltaAccumulator* GetInstance() static DeltaAccumulator* GetInstance()
{ {
if (!sInstance) { if (!sInstance) {
sInstance = new PixelDeltaAccumulator; sInstance = new DeltaAccumulator;
} }
return sInstance; return sInstance;
} }
@ -520,31 +528,34 @@ protected:
} }
/** /**
* OnMousePixelScrollEvent() stores pixel delta values. And if the * InitLineOrPageDelta() stores pixel delta values of WheelEvents which are
* accumulated delta becomes a line height, dispatches DOMMouseScroll event * caused if it's needed. And if the accumulated delta becomes a
* automatically. * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
*/ */
void OnMousePixelScrollEvent(nsPresContext* aPresContext, void InitLineOrPageDelta(nsIFrame* aTargetFrame,
nsIFrame* aTargetFrame, nsEventStateManager* aESM,
nsEventStateManager* aESM, mozilla::widget::WheelEvent* aEvent);
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus);
/** /**
* Reset() resets both delta values. * Reset() resets both delta values.
*/ */
void Reset(); void Reset();
private: private:
PixelDeltaAccumulator() : DeltaAccumulator() :
mX(0), mY(0) mX(0.0), mY(0.0), mHandlingDeltaMode(PR_UINT32_MAX),
mHandlingPixelOnlyDevice(false)
{ {
} }
PRInt32 mX; double mX;
PRInt32 mY; double mY;
TimeStamp mLastTime; TimeStamp mLastTime;
static PixelDeltaAccumulator* sInstance; PRUint32 mHandlingDeltaMode;
bool mHandlingPixelOnlyDevice;
static DeltaAccumulator* sInstance;
}; };
// end mousewheel functions // end mousewheel functions

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

@ -1408,7 +1408,7 @@ public:
nsMouseEvent_base(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT), nsMouseEvent_base(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT),
deltaX(0.0), deltaY(0.0), deltaZ(0.0), deltaX(0.0), deltaY(0.0), deltaZ(0.0),
deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL), deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
customizedByUserPrefs(false), customizedByUserPrefs(false), isPixelOnlyDevice(false),
lineOrPageDeltaX(0), lineOrPageDeltaY(0), lineOrPageDeltaX(0), lineOrPageDeltaY(0),
overflowDeltaX(0.0), overflowDeltaY(0.0) overflowDeltaX(0.0), overflowDeltaY(0.0)
{ {
@ -1425,6 +1425,12 @@ public:
// Otherwise, i.e., they are computed from native events, false. // Otherwise, i.e., they are computed from native events, false.
bool customizedByUserPrefs; bool customizedByUserPrefs;
// If device event handlers don't know when they should set lineOrPageDeltaX
// and lineOrPageDeltaY, this is true. Otherwise, false.
// If isPixelOnlyDevice is true, ESM will generate NS_MOUSE_SCROLL events
// when accumulated pixel delta values reach a line height.
bool isPixelOnlyDevice;
// If widget sets lineOrPageDelta, nsEventStateManager will dispatch // If widget sets lineOrPageDelta, nsEventStateManager will dispatch
// NS_MOUSE_SCROLL event for compatibility. Note that the delta value means // NS_MOUSE_SCROLL event for compatibility. Note that the delta value means
// pages if the deltaMode is DOM_DELTA_PAGE, otherwise, lines. // pages if the deltaMode is DOM_DELTA_PAGE, otherwise, lines.

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

@ -130,6 +130,7 @@ struct ParamTraits<mozilla::widget::WheelEvent>
WriteParam(aMsg, aParam.deltaZ); WriteParam(aMsg, aParam.deltaZ);
WriteParam(aMsg, aParam.deltaMode); WriteParam(aMsg, aParam.deltaMode);
WriteParam(aMsg, aParam.customizedByUserPrefs); WriteParam(aMsg, aParam.customizedByUserPrefs);
WriteParam(aMsg, aParam.isPixelOnlyDevice);
WriteParam(aMsg, aParam.lineOrPageDeltaX); WriteParam(aMsg, aParam.lineOrPageDeltaX);
WriteParam(aMsg, aParam.lineOrPageDeltaY); WriteParam(aMsg, aParam.lineOrPageDeltaY);
WriteParam(aMsg, aParam.overflowDeltaX); WriteParam(aMsg, aParam.overflowDeltaX);
@ -144,6 +145,7 @@ struct ParamTraits<mozilla::widget::WheelEvent>
ReadParam(aMsg, aIter, &aResult->deltaZ) && ReadParam(aMsg, aIter, &aResult->deltaZ) &&
ReadParam(aMsg, aIter, &aResult->deltaMode) && ReadParam(aMsg, aIter, &aResult->deltaMode) &&
ReadParam(aMsg, aIter, &aResult->customizedByUserPrefs) && ReadParam(aMsg, aIter, &aResult->customizedByUserPrefs) &&
ReadParam(aMsg, aIter, &aResult->isPixelOnlyDevice) &&
ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaX) && ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaX) &&
ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaY) && ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaY) &&
ReadParam(aMsg, aIter, &aResult->overflowDeltaX) && ReadParam(aMsg, aIter, &aResult->overflowDeltaX) &&