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->inputSource = oldWheelEvent->inputSource;
wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs;
wheelEvent->isPixelOnlyDevice = oldWheelEvent->isPixelOnlyDevice;
wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX;
wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY;
wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX;

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

@ -138,8 +138,8 @@ TimeStamp nsEventStateManager::sHandlingInputStart;
nsEventStateManager::WheelPrefs*
nsEventStateManager::WheelPrefs::sInstance = nullptr;
nsEventStateManager::PixelDeltaAccumulator*
nsEventStateManager::PixelDeltaAccumulator::sInstance = nullptr;
nsEventStateManager::DeltaAccumulator*
nsEventStateManager::DeltaAccumulator::sInstance = nullptr;
static inline PRInt32
RoundDown(double aDouble)
@ -810,6 +810,7 @@ nsEventStateManager::~nsEventStateManager()
NS_RELEASE(gUserInteractionTimer);
}
WheelPrefs::Shutdown();
DeltaAccumulator::Shutdown();
}
if (sDragOverContent && sDragOverContent->OwnerDoc() == mDocument) {
@ -835,7 +836,6 @@ nsEventStateManager::~nsEventStateManager()
nsresult
nsEventStateManager::Shutdown()
{
PixelDeltaAccumulator::Shutdown();
Preferences::RemoveObservers(this, kObservedPrefs);
m_haveShutdown = true;
return NS_OK;
@ -1132,6 +1132,13 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(aEvent);
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;
case NS_QUERY_SELECTED_TEXT:
@ -5140,91 +5147,95 @@ nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
}
/******************************************************************/
/* nsEventStateManager::PixelDeltaAccumulator */
/* nsEventStateManager::DeltaAccumulator */
/******************************************************************/
void
nsEventStateManager::PixelDeltaAccumulator::OnMousePixelScrollEvent(
nsPresContext* aPresContext,
nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus)
nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
widget::WheelEvent* aEvent)
{
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)) {
if (!(aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL &&
aEvent->isPixelOnlyDevice) &&
!WheelPrefs::GetInstance()->NeedToComputeLineOrPageDelta(aEvent)) {
Reset();
return;
}
#if 0
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);
// Reset if the previous wheel event is too old.
if (!mLastTime.IsNull()) {
TimeDuration duration = TimeStamp::Now() - mLastTime;
if (duration.ToMilliseconds() > nsMouseWheelTransaction::GetTimeoutTime()) {
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();
// 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
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.
sInstance->Reset();
DeltaAccumulator::GetInstance()->Reset();
return 0;
}
@ -5410,3 +5422,14 @@ nsEventStateManager::WheelPrefs::GetActionFor(nsMouseScrollEvent* aEvent)
Init(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);
/**
* NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
* computed the lineOrPageDelta values.
*/
bool NeedToComputeLineOrPageDelta(mozilla::widget::WheelEvent* aEvent);
private:
WheelPrefs();
~WheelPrefs();
@ -499,16 +505,18 @@ protected:
PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent);
/**
* PixelDeltaAccumulator class manages pixel delta values for dispatching
* DOMMouseScroll event.
* DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
* 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:
static PixelDeltaAccumulator* GetInstance()
static DeltaAccumulator* GetInstance()
{
if (!sInstance) {
sInstance = new PixelDeltaAccumulator;
sInstance = new DeltaAccumulator;
}
return sInstance;
}
@ -520,31 +528,34 @@ protected:
}
/**
* OnMousePixelScrollEvent() stores pixel delta values. And if the
* accumulated delta becomes a line height, dispatches DOMMouseScroll event
* automatically.
* InitLineOrPageDelta() stores pixel delta values of WheelEvents which are
* caused if it's needed. And if the accumulated delta becomes a
* line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
*/
void OnMousePixelScrollEvent(nsPresContext* aPresContext,
nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
nsMouseScrollEvent* aEvent,
nsEventStatus* aStatus);
void InitLineOrPageDelta(nsIFrame* aTargetFrame,
nsEventStateManager* aESM,
mozilla::widget::WheelEvent* aEvent);
/**
* Reset() resets both delta values.
*/
void Reset();
private:
PixelDeltaAccumulator() :
mX(0), mY(0)
DeltaAccumulator() :
mX(0.0), mY(0.0), mHandlingDeltaMode(PR_UINT32_MAX),
mHandlingPixelOnlyDevice(false)
{
}
PRInt32 mX;
PRInt32 mY;
double mX;
double mY;
TimeStamp mLastTime;
static PixelDeltaAccumulator* sInstance;
PRUint32 mHandlingDeltaMode;
bool mHandlingPixelOnlyDevice;
static DeltaAccumulator* sInstance;
};
// end mousewheel functions

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

@ -1408,7 +1408,7 @@ public:
nsMouseEvent_base(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT),
deltaX(0.0), deltaY(0.0), deltaZ(0.0),
deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
customizedByUserPrefs(false),
customizedByUserPrefs(false), isPixelOnlyDevice(false),
lineOrPageDeltaX(0), lineOrPageDeltaY(0),
overflowDeltaX(0.0), overflowDeltaY(0.0)
{
@ -1425,6 +1425,12 @@ public:
// Otherwise, i.e., they are computed from native events, false.
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
// NS_MOUSE_SCROLL event for compatibility. Note that the delta value means
// 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.deltaMode);
WriteParam(aMsg, aParam.customizedByUserPrefs);
WriteParam(aMsg, aParam.isPixelOnlyDevice);
WriteParam(aMsg, aParam.lineOrPageDeltaX);
WriteParam(aMsg, aParam.lineOrPageDeltaY);
WriteParam(aMsg, aParam.overflowDeltaX);
@ -144,6 +145,7 @@ struct ParamTraits<mozilla::widget::WheelEvent>
ReadParam(aMsg, aIter, &aResult->deltaZ) &&
ReadParam(aMsg, aIter, &aResult->deltaMode) &&
ReadParam(aMsg, aIter, &aResult->customizedByUserPrefs) &&
ReadParam(aMsg, aIter, &aResult->isPixelOnlyDevice) &&
ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaX) &&
ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaY) &&
ReadParam(aMsg, aIter, &aResult->overflowDeltaX) &&